github.com/ipld/go-ipld-prime@v0.21.0/testutil/multibytenode.go (about)

     1  package testutil
     2  
     3  import (
     4  	"io"
     5  
     6  	"github.com/ipld/go-ipld-prime/datamodel"
     7  	"github.com/ipld/go-ipld-prime/node/basicnode"
     8  )
     9  
    10  var _ datamodel.Node = MultiByteNode{}
    11  var _ datamodel.LargeBytesNode = (*MultiByteNode)(nil)
    12  
    13  // MultiByteNode is a node that is a concatenation of multiple byte slices.
    14  // It's not particularly sophisticated but lets us exercise LargeBytesNode in a
    15  // non-trivial way.
    16  // The novel behaviour of Read() and Seek() on the AsLargeBytes is similar to
    17  // that which would be expected from a LBN ADL, such as UnixFS sharded files.
    18  type MultiByteNode struct {
    19  	bytes [][]byte
    20  }
    21  
    22  func NewMultiByteNode(bytes ...[]byte) MultiByteNode {
    23  	return MultiByteNode{bytes: bytes}
    24  }
    25  
    26  func (mbn MultiByteNode) Kind() datamodel.Kind {
    27  	return datamodel.Kind_Bytes
    28  }
    29  
    30  func (mbn MultiByteNode) AsBytes() ([]byte, error) {
    31  	ret := make([]byte, 0, mbn.TotalLength())
    32  	for _, b := range mbn.bytes {
    33  		ret = append(ret, b...)
    34  	}
    35  	return ret, nil
    36  }
    37  
    38  func (mbn MultiByteNode) TotalLength() int {
    39  	var size int
    40  	for _, b := range mbn.bytes {
    41  		size += len(b)
    42  	}
    43  	return size
    44  }
    45  
    46  func (mbn MultiByteNode) AsLargeBytes() (io.ReadSeeker, error) {
    47  	return &mbnReadSeeker{node: mbn}, nil
    48  }
    49  
    50  func (mbn MultiByteNode) AsBool() (bool, error) {
    51  	return false, datamodel.ErrWrongKind{TypeName: "bool", MethodName: "AsBool", AppropriateKind: datamodel.KindSet_JustBytes}
    52  }
    53  
    54  func (mbn MultiByteNode) AsInt() (int64, error) {
    55  	return 0, datamodel.ErrWrongKind{TypeName: "int", MethodName: "AsInt", AppropriateKind: datamodel.KindSet_JustBytes}
    56  }
    57  
    58  func (mbn MultiByteNode) AsFloat() (float64, error) {
    59  	return 0, datamodel.ErrWrongKind{TypeName: "float", MethodName: "AsFloat", AppropriateKind: datamodel.KindSet_JustBytes}
    60  }
    61  
    62  func (mbn MultiByteNode) AsString() (string, error) {
    63  	return "", datamodel.ErrWrongKind{TypeName: "string", MethodName: "AsString", AppropriateKind: datamodel.KindSet_JustBytes}
    64  }
    65  
    66  func (mbn MultiByteNode) AsLink() (datamodel.Link, error) {
    67  	return nil, datamodel.ErrWrongKind{TypeName: "link", MethodName: "AsLink", AppropriateKind: datamodel.KindSet_JustBytes}
    68  }
    69  
    70  func (mbn MultiByteNode) AsNode() (datamodel.Node, error) {
    71  	return nil, nil
    72  }
    73  
    74  func (mbn MultiByteNode) Size() int {
    75  	return 0
    76  }
    77  
    78  func (mbn MultiByteNode) IsAbsent() bool {
    79  	return false
    80  }
    81  
    82  func (mbn MultiByteNode) IsNull() bool {
    83  	return false
    84  }
    85  
    86  func (mbn MultiByteNode) Length() int64 {
    87  	return 0
    88  }
    89  
    90  func (mbn MultiByteNode) ListIterator() datamodel.ListIterator {
    91  	return nil
    92  }
    93  
    94  func (mbn MultiByteNode) MapIterator() datamodel.MapIterator {
    95  	return nil
    96  }
    97  
    98  func (mbn MultiByteNode) LookupByIndex(idx int64) (datamodel.Node, error) {
    99  	return nil, datamodel.ErrWrongKind{}
   100  }
   101  
   102  func (mbn MultiByteNode) LookupByString(key string) (datamodel.Node, error) {
   103  	return nil, datamodel.ErrWrongKind{}
   104  }
   105  
   106  func (mbn MultiByteNode) LookupByNode(key datamodel.Node) (datamodel.Node, error) {
   107  	return nil, datamodel.ErrWrongKind{}
   108  }
   109  
   110  func (mbn MultiByteNode) LookupBySegment(seg datamodel.PathSegment) (datamodel.Node, error) {
   111  	return nil, datamodel.ErrWrongKind{}
   112  }
   113  
   114  func (mbn MultiByteNode) Prototype() datamodel.NodePrototype {
   115  	return basicnode.Prototype.Bytes // not really ... but it'll do for this test
   116  }
   117  
   118  type mbnReadSeeker struct {
   119  	node   MultiByteNode
   120  	offset int
   121  }
   122  
   123  func (mbnrs *mbnReadSeeker) Read(p []byte) (int, error) {
   124  	var acc int
   125  	for _, byts := range mbnrs.node.bytes {
   126  		if mbnrs.offset-acc >= len(byts) {
   127  			acc += len(byts)
   128  			continue
   129  		}
   130  		n := copy(p, byts[mbnrs.offset-acc:])
   131  		mbnrs.offset += n
   132  		return n, nil
   133  	}
   134  	return 0, io.EOF
   135  }
   136  
   137  func (mbnrs *mbnReadSeeker) Seek(offset int64, whence int) (int64, error) {
   138  	switch whence {
   139  	case io.SeekStart:
   140  		mbnrs.offset = int(offset)
   141  	case io.SeekCurrent:
   142  		mbnrs.offset += int(offset)
   143  	case io.SeekEnd:
   144  		mbnrs.offset = mbnrs.node.TotalLength() + int(offset)
   145  	}
   146  	return int64(mbnrs.offset), nil
   147  }