container: streamed and non-streamed IO, documentation

This commit is contained in:
Michael Muré
2024-11-21 15:49:29 +01:00
parent ba0038b0ae
commit 820057e41e
4 changed files with 134 additions and 63 deletions

View File

@@ -1,6 +1,7 @@
package container
import (
"bytes"
"encoding/base64"
"io"
@@ -12,10 +13,6 @@ import (
"github.com/ipld/go-ipld-prime/node/basicnode"
)
// TODO: should we have a multibase to wrap the cbor? but there is no reader/write in go-multibase :-(
const currentContainerVersion = "ctn-v1"
// Writer is a token container writer. It provides a convenient way to aggregate and serialize tokens together.
type Writer map[cid.Cid][]byte
@@ -28,27 +25,24 @@ func (ctn Writer) AddSealed(cid cid.Cid, data []byte) {
ctn[cid] = data
}
func (ctn Writer) ToCar(w io.Writer) error {
return writeCar(w, nil, func(yield func(carBlock, error) bool) {
for c, bytes := range ctn {
if !yield(carBlock{c: c, data: bytes}, nil) {
return
}
}
})
const currentContainerVersion = "ctn-v1"
// ToCbor encode the container into a DAG-CBOR binary format.
func (ctn Writer) ToCbor() ([]byte, error) {
var buf bytes.Buffer
err := ctn.ToCborWriter(&buf)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func (ctn Writer) ToCarBase64(w io.Writer) error {
w2 := base64.NewEncoder(base64.StdEncoding, w)
defer w2.Close()
return ctn.ToCar(w2)
}
func (ctn Writer) ToCbor(w io.Writer) error {
// ToCborWriter is the same as ToCbor, but with an io.Writer.
func (ctn Writer) ToCborWriter(w io.Writer) error {
node, err := qp.BuildMap(basicnode.Prototype.Any, 1, func(ma datamodel.MapAssembler) {
qp.MapEntry(ma, currentContainerVersion, qp.List(int64(len(ctn)), func(la datamodel.ListAssembler) {
for _, bytes := range ctn {
qp.ListEntry(la, qp.Bytes(bytes))
for _, data := range ctn {
qp.ListEntry(la, qp.Bytes(data))
}
}))
})
@@ -58,8 +52,57 @@ func (ctn Writer) ToCbor(w io.Writer) error {
return ipld.EncodeStreaming(w, node, dagcbor.Encode)
}
func (ctn Writer) ToCborBase64(w io.Writer) error {
// ToCborBase64 encode the container into a base64 encoded DAG-CBOR binary format.
func (ctn Writer) ToCborBase64() ([]byte, error) {
var buf bytes.Buffer
err := ctn.ToCborBase64Writer(&buf)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// ToCborBase64Writer is the same as ToCborBase64, but with an io.Writer.
func (ctn Writer) ToCborBase64Writer(w io.Writer) error {
w2 := base64.NewEncoder(base64.StdEncoding, w)
defer w2.Close()
return ctn.ToCbor(w2)
return ctn.ToCborWriter(w2)
}
// ToCar encode the container into a CAR file.
func (ctn Writer) ToCar() ([]byte, error) {
var buf bytes.Buffer
err := ctn.ToCarWriter(&buf)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// ToCarWriter is the same as ToCar, but with an io.Writer.
func (ctn Writer) ToCarWriter(w io.Writer) error {
return writeCar(w, nil, func(yield func(carBlock, error) bool) {
for c, data := range ctn {
if !yield(carBlock{c: c, data: data}, nil) {
return
}
}
})
}
// ToCarBase64 encode the container into a base64 encoded CAR file.
func (ctn Writer) ToCarBase64() ([]byte, error) {
var buf bytes.Buffer
err := ctn.ToCarBase64Writer(&buf)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// ToCarBase64Writer is the same as ToCarBase64, but with an io.Writer.
func (ctn Writer) ToCarBase64Writer(w io.Writer) error {
w2 := base64.NewEncoder(base64.StdEncoding, w)
defer w2.Close()
return ctn.ToCarWriter(w2)
}