2024-10-02 11:56:32 +02:00
|
|
|
package container
|
|
|
|
|
|
|
|
|
|
import (
|
2024-11-21 15:49:29 +01:00
|
|
|
"bytes"
|
2024-10-02 11:56:32 +02:00
|
|
|
"encoding/base64"
|
|
|
|
|
"io"
|
|
|
|
|
|
|
|
|
|
"github.com/ipfs/go-cid"
|
|
|
|
|
"github.com/ipld/go-ipld-prime"
|
2025-01-07 18:16:27 +01:00
|
|
|
"github.com/ipld/go-ipld-prime/codec/cbor"
|
2024-10-02 11:56:32 +02:00
|
|
|
"github.com/ipld/go-ipld-prime/datamodel"
|
|
|
|
|
"github.com/ipld/go-ipld-prime/fluent/qp"
|
|
|
|
|
"github.com/ipld/go-ipld-prime/node/basicnode"
|
|
|
|
|
)
|
|
|
|
|
|
2024-10-07 18:46:19 +02:00
|
|
|
// Writer is a token container writer. It provides a convenient way to aggregate and serialize tokens together.
|
2024-10-02 11:56:32 +02:00
|
|
|
type Writer map[cid.Cid][]byte
|
|
|
|
|
|
|
|
|
|
func NewWriter() Writer {
|
|
|
|
|
return make(Writer)
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-07 18:46:19 +02:00
|
|
|
// AddSealed includes a "sealed" token (serialized with a ToSealed* function) in the container.
|
2024-10-02 11:56:32 +02:00
|
|
|
func (ctn Writer) AddSealed(cid cid.Cid, data []byte) {
|
|
|
|
|
ctn[cid] = data
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-21 15:49:29 +01:00
|
|
|
const currentContainerVersion = "ctn-v1"
|
2024-10-02 11:56:32 +02:00
|
|
|
|
2025-01-07 18:16:27 +01:00
|
|
|
// ToCbor encode the container into a CBOR binary format.
|
2024-11-21 15:49:29 +01:00
|
|
|
func (ctn Writer) ToCbor() ([]byte, error) {
|
|
|
|
|
var buf bytes.Buffer
|
|
|
|
|
err := ctn.ToCborWriter(&buf)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return buf.Bytes(), nil
|
2024-10-02 11:56:32 +02:00
|
|
|
}
|
|
|
|
|
|
2024-11-21 15:49:29 +01:00
|
|
|
// ToCborWriter is the same as ToCbor, but with an io.Writer.
|
|
|
|
|
func (ctn Writer) ToCborWriter(w io.Writer) error {
|
2024-11-13 18:03:00 +01:00
|
|
|
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) {
|
2024-11-21 15:49:29 +01:00
|
|
|
for _, data := range ctn {
|
|
|
|
|
qp.ListEntry(la, qp.Bytes(data))
|
2024-11-13 18:03:00 +01:00
|
|
|
}
|
|
|
|
|
}))
|
2024-10-02 11:56:32 +02:00
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2025-01-07 18:16:27 +01:00
|
|
|
return ipld.EncodeStreaming(w, node, cbor.Encode)
|
2024-10-02 11:56:32 +02:00
|
|
|
}
|
|
|
|
|
|
2025-01-07 18:16:27 +01:00
|
|
|
// ToCborBase64 encode the container into a base64 encoded CBOR binary format.
|
2024-12-11 16:05:16 +01:00
|
|
|
func (ctn Writer) ToCborBase64() (string, error) {
|
2024-11-21 15:49:29 +01:00
|
|
|
var buf bytes.Buffer
|
|
|
|
|
err := ctn.ToCborBase64Writer(&buf)
|
|
|
|
|
if err != nil {
|
2024-12-11 16:05:16 +01:00
|
|
|
return "", err
|
2024-11-21 15:49:29 +01:00
|
|
|
}
|
2024-12-11 16:05:16 +01:00
|
|
|
return buf.String(), nil
|
2024-11-21 15:49:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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.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.
|
2024-12-11 16:05:16 +01:00
|
|
|
func (ctn Writer) ToCarBase64() (string, error) {
|
2024-11-21 15:49:29 +01:00
|
|
|
var buf bytes.Buffer
|
|
|
|
|
err := ctn.ToCarBase64Writer(&buf)
|
|
|
|
|
if err != nil {
|
2024-12-11 16:05:16 +01:00
|
|
|
return "", err
|
2024-11-21 15:49:29 +01:00
|
|
|
}
|
2024-12-11 16:05:16 +01:00
|
|
|
return buf.String(), nil
|
2024-11-21 15:49:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ToCarBase64Writer is the same as ToCarBase64, but with an io.Writer.
|
|
|
|
|
func (ctn Writer) ToCarBase64Writer(w io.Writer) error {
|
2024-10-02 11:56:32 +02:00
|
|
|
w2 := base64.NewEncoder(base64.StdEncoding, w)
|
|
|
|
|
defer w2.Close()
|
2024-11-21 15:49:29 +01:00
|
|
|
return ctn.ToCarWriter(w2)
|
2024-10-02 11:56:32 +02:00
|
|
|
}
|