token/read: add the usual collections of readers
This commit is contained in:
@@ -94,19 +94,7 @@ func DecodeReader[T Tokener](r io.Reader, decFn codec.Decoder) (T, error) {
|
|||||||
// An error is returned if the conversion fails, or if the resulting
|
// An error is returned if the conversion fails, or if the resulting
|
||||||
// Tokener is invalid.
|
// Tokener is invalid.
|
||||||
func FromDagCbor[T Tokener](b []byte) (T, error) {
|
func FromDagCbor[T Tokener](b []byte) (T, error) {
|
||||||
undef := *new(T)
|
return Decode[T](b, dagcbor.Decode)
|
||||||
|
|
||||||
node, err := ipld.Decode(b, dagcbor.Decode)
|
|
||||||
if err != nil {
|
|
||||||
return undef, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tkn, err := fromIPLD[T](node)
|
|
||||||
if err != nil {
|
|
||||||
return undef, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tkn, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromDagCborReader is the same as FromDagCbor, but accept an io.Reader.
|
// FromDagCborReader is the same as FromDagCbor, but accept an io.Reader.
|
||||||
@@ -132,20 +120,9 @@ func FromDagJsonReader[T Tokener](r io.Reader) (T, error) {
|
|||||||
// An error is returned if the conversion fails, or if the resulting
|
// An error is returned if the conversion fails, or if the resulting
|
||||||
// Tokener is invalid.
|
// Tokener is invalid.
|
||||||
func FromIPLD[T Tokener](node datamodel.Node) (T, error) {
|
func FromIPLD[T Tokener](node datamodel.Node) (T, error) {
|
||||||
undef := *new(T)
|
|
||||||
|
|
||||||
tkn, err := fromIPLD[T](node)
|
|
||||||
if err != nil {
|
|
||||||
return undef, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tkn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func fromIPLD[T Tokener](node datamodel.Node) (T, error) {
|
|
||||||
zero := *new(T)
|
zero := *new(T)
|
||||||
|
|
||||||
info, err := inspect(node)
|
info, err := Inspect(node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return zero, err
|
return zero, err
|
||||||
}
|
}
|
||||||
@@ -154,7 +131,7 @@ func fromIPLD[T Tokener](node datamodel.Node) (T, error) {
|
|||||||
return zero, errors.New("data doesn't match the expected type")
|
return zero, errors.New("data doesn't match the expected type")
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenPayloadNode, err := info.SigPayloadNode.LookupByString(info.Tag)
|
tokenPayloadNode, err := info.sigPayloadNode.LookupByString(info.Tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return zero, err
|
return zero, err
|
||||||
}
|
}
|
||||||
@@ -215,7 +192,7 @@ func fromIPLD[T Tokener](node datamodel.Node) (T, error) {
|
|||||||
return zero, errors.New("the VarsigHeader key type doesn't match the issuer's key type")
|
return zero, errors.New("the VarsigHeader key type doesn't match the issuer's key type")
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ipld.Encode(info.SigPayloadNode, dagcbor.Encode)
|
data, err := ipld.Encode(info.sigPayloadNode, dagcbor.Encode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return zero, err
|
return zero, err
|
||||||
}
|
}
|
||||||
@@ -335,50 +312,50 @@ func FindTag(node datamodel.Node) (string, error) {
|
|||||||
return "", fmt.Errorf("no token tag found")
|
return "", fmt.Errorf("no token tag found")
|
||||||
}
|
}
|
||||||
|
|
||||||
type info struct {
|
type Info struct {
|
||||||
Tag string
|
Tag string
|
||||||
Signature []byte
|
Signature []byte
|
||||||
SigPayloadNode datamodel.Node
|
sigPayloadNode datamodel.Node // private, we don't want to expose that
|
||||||
VarsigHeader []byte
|
VarsigHeader []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func inspect(node datamodel.Node) (info, error) {
|
func Inspect(node datamodel.Node) (Info, error) {
|
||||||
var res info
|
var res Info
|
||||||
|
|
||||||
signatureNode, err := node.LookupByIndex(0)
|
signatureNode, err := node.LookupByIndex(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return info{}, err
|
return Info{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
res.Signature, err = signatureNode.AsBytes()
|
res.Signature, err = signatureNode.AsBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return info{}, err
|
return Info{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
res.SigPayloadNode, err = node.LookupByIndex(1)
|
res.sigPayloadNode, err = node.LookupByIndex(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return info{}, err
|
return Info{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
it := res.SigPayloadNode.MapIterator()
|
it := res.sigPayloadNode.MapIterator()
|
||||||
foundVarsigHeader := false
|
foundVarsigHeader := false
|
||||||
foundTokenPayload := false
|
foundTokenPayload := false
|
||||||
i := 0
|
i := 0
|
||||||
|
|
||||||
for !it.Done() {
|
for !it.Done() {
|
||||||
if i >= 2 {
|
if i >= 2 {
|
||||||
return info{}, fmt.Errorf("expected two and only two fields in SigPayload")
|
return Info{}, fmt.Errorf("expected two and only two fields in SigPayload")
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
|
|
||||||
k, v, err := it.Next()
|
k, v, err := it.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return info{}, err
|
return Info{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
key, err := k.AsString()
|
key, err := k.AsString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return info{}, err
|
return Info{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
@@ -386,24 +363,24 @@ func inspect(node datamodel.Node) (info, error) {
|
|||||||
foundVarsigHeader = true
|
foundVarsigHeader = true
|
||||||
res.VarsigHeader, err = v.AsBytes()
|
res.VarsigHeader, err = v.AsBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return info{}, err
|
return Info{}, err
|
||||||
}
|
}
|
||||||
case strings.HasPrefix(key, UCANTagPrefix):
|
case strings.HasPrefix(key, UCANTagPrefix):
|
||||||
foundTokenPayload = true
|
foundTokenPayload = true
|
||||||
res.Tag = key
|
res.Tag = key
|
||||||
default:
|
default:
|
||||||
return info{}, fmt.Errorf("unexpected key type %q", key)
|
return Info{}, fmt.Errorf("unexpected key type %q", key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if i != 2 {
|
if i != 2 {
|
||||||
return info{}, fmt.Errorf("expected two and only two fields in SigPayload: %d", i)
|
return Info{}, fmt.Errorf("expected two and only two fields in SigPayload: %d", i)
|
||||||
}
|
}
|
||||||
if !foundVarsigHeader {
|
if !foundVarsigHeader {
|
||||||
return info{}, errors.New("failed to find VarsigHeader field")
|
return Info{}, errors.New("failed to find VarsigHeader field")
|
||||||
}
|
}
|
||||||
if !foundTokenPayload {
|
if !foundTokenPayload {
|
||||||
return info{}, errors.New("failed to find TokenPayload field")
|
return Info{}, errors.New("failed to find TokenPayload field")
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
|
|||||||
@@ -2,20 +2,70 @@ package tokens
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/ipld/go-ipld-prime"
|
"github.com/ipld/go-ipld-prime"
|
||||||
|
"github.com/ipld/go-ipld-prime/codec"
|
||||||
"github.com/ipld/go-ipld-prime/codec/dagcbor"
|
"github.com/ipld/go-ipld-prime/codec/dagcbor"
|
||||||
|
"github.com/ipld/go-ipld-prime/codec/dagjson"
|
||||||
|
"github.com/ipld/go-ipld-prime/datamodel"
|
||||||
|
|
||||||
"github.com/ucan-wg/go-ucan/tokens/delegation"
|
"github.com/ucan-wg/go-ucan/tokens/delegation"
|
||||||
"github.com/ucan-wg/go-ucan/tokens/internal/envelope"
|
"github.com/ucan-wg/go-ucan/tokens/internal/envelope"
|
||||||
)
|
)
|
||||||
|
|
||||||
func FromDagCbor(b []byte) (any, error) {
|
// Decode unmarshals the input data using the format specified by the
|
||||||
node, err := ipld.Decode(b, dagcbor.Decode)
|
// provided codec.Decoder into an arbitrary UCAN token.
|
||||||
|
// An error is returned if the conversion fails, or if the resulting
|
||||||
|
// Token is invalid.
|
||||||
|
// Supported and returned types are:
|
||||||
|
// - delegation.Token
|
||||||
|
func Decode(b []byte, decFn codec.Decoder) (any, error) {
|
||||||
|
node, err := ipld.Decode(b, decFn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return fromIPLD(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeReader is the same as Decode, but accept an io.Reader.
|
||||||
|
func DecodeReader(r io.Reader, decFn codec.Decoder) (any, error) {
|
||||||
|
node, err := ipld.DecodeStreaming(r, decFn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return fromIPLD(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromDagCbor unmarshals an arbitrary DagCbor encoded UCAN token.
|
||||||
|
// An error is returned if the conversion fails, or if the resulting
|
||||||
|
// Token is invalid.
|
||||||
|
// Supported and returned types are:
|
||||||
|
// - delegation.Token
|
||||||
|
func FromDagCbor(b []byte) (any, error) {
|
||||||
|
return Decode(b, dagcbor.Decode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromDagCborReader is the same as FromDagCbor, but accept an io.Reader.
|
||||||
|
func FromDagCborReader(r io.Reader) (any, error) {
|
||||||
|
return DecodeReader(r, dagcbor.Decode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromDagCbor unmarshals an arbitrary DagJson encoded UCAN token.
|
||||||
|
// An error is returned if the conversion fails, or if the resulting
|
||||||
|
// Token is invalid.
|
||||||
|
// Supported and returned types are:
|
||||||
|
// - delegation.Token
|
||||||
|
func FromDagJson(b []byte) (any, error) {
|
||||||
|
return Decode(b, dagjson.Decode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromDagJsonReader is the same as FromDagJson, but accept an io.Reader.
|
||||||
|
func FromDagJsonReader(r io.Reader) (any, error) {
|
||||||
|
return DecodeReader(r, dagjson.Decode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fromIPLD(node datamodel.Node) (any, error) {
|
||||||
tag, err := envelope.FindTag(node)
|
tag, err := envelope.FindTag(node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
Reference in New Issue
Block a user