github.com/ipld/go-ipld-prime@v0.21.0/node/basicnode/list.go (about)

     1  package basicnode
     2  
     3  import (
     4  	"github.com/ipld/go-ipld-prime/datamodel"
     5  	"github.com/ipld/go-ipld-prime/node/mixins"
     6  )
     7  
     8  var (
     9  	_ datamodel.Node          = &plainList{}
    10  	_ datamodel.NodePrototype = Prototype__List{}
    11  	_ datamodel.NodeBuilder   = &plainList__Builder{}
    12  	_ datamodel.NodeAssembler = &plainList__Assembler{}
    13  )
    14  
    15  // plainList is a concrete type that provides a list-kind datamodel.Node.
    16  // It can contain any kind of value.
    17  // plainList is also embedded in the 'any' struct and usable from there.
    18  type plainList struct {
    19  	x []datamodel.Node
    20  }
    21  
    22  // -- Node interface methods -->
    23  
    24  func (plainList) Kind() datamodel.Kind {
    25  	return datamodel.Kind_List
    26  }
    27  func (plainList) LookupByString(string) (datamodel.Node, error) {
    28  	return mixins.List{TypeName: "list"}.LookupByString("")
    29  }
    30  func (plainList) LookupByNode(datamodel.Node) (datamodel.Node, error) {
    31  	return mixins.List{TypeName: "list"}.LookupByNode(nil)
    32  }
    33  func (n *plainList) LookupByIndex(idx int64) (datamodel.Node, error) {
    34  	if n.Length() <= idx {
    35  		return nil, datamodel.ErrNotExists{Segment: datamodel.PathSegmentOfInt(idx)}
    36  	}
    37  	return n.x[idx], nil
    38  }
    39  func (n *plainList) LookupBySegment(seg datamodel.PathSegment) (datamodel.Node, error) {
    40  	idx, err := seg.Index()
    41  	if err != nil {
    42  		return nil, datamodel.ErrInvalidSegmentForList{TroubleSegment: seg, Reason: err}
    43  	}
    44  	return n.LookupByIndex(idx)
    45  }
    46  func (plainList) MapIterator() datamodel.MapIterator {
    47  	return nil
    48  }
    49  func (n *plainList) ListIterator() datamodel.ListIterator {
    50  	return &plainList_ListIterator{n, 0}
    51  }
    52  func (n *plainList) Length() int64 {
    53  	return int64(len(n.x))
    54  }
    55  func (plainList) IsAbsent() bool {
    56  	return false
    57  }
    58  func (plainList) IsNull() bool {
    59  	return false
    60  }
    61  func (plainList) AsBool() (bool, error) {
    62  	return mixins.List{TypeName: "list"}.AsBool()
    63  }
    64  func (plainList) AsInt() (int64, error) {
    65  	return mixins.List{TypeName: "list"}.AsInt()
    66  }
    67  func (plainList) AsFloat() (float64, error) {
    68  	return mixins.List{TypeName: "list"}.AsFloat()
    69  }
    70  func (plainList) AsString() (string, error) {
    71  	return mixins.List{TypeName: "list"}.AsString()
    72  }
    73  func (plainList) AsBytes() ([]byte, error) {
    74  	return mixins.List{TypeName: "list"}.AsBytes()
    75  }
    76  func (plainList) AsLink() (datamodel.Link, error) {
    77  	return mixins.List{TypeName: "list"}.AsLink()
    78  }
    79  func (plainList) Prototype() datamodel.NodePrototype {
    80  	return Prototype.List
    81  }
    82  
    83  type plainList_ListIterator struct {
    84  	n   *plainList
    85  	idx int
    86  }
    87  
    88  func (itr *plainList_ListIterator) Next() (idx int64, v datamodel.Node, _ error) {
    89  	if itr.Done() {
    90  		return -1, nil, datamodel.ErrIteratorOverread{}
    91  	}
    92  	v = itr.n.x[itr.idx]
    93  	idx = int64(itr.idx)
    94  	itr.idx++
    95  	return
    96  }
    97  func (itr *plainList_ListIterator) Done() bool {
    98  	return itr.idx >= len(itr.n.x)
    99  }
   100  
   101  // -- NodePrototype -->
   102  
   103  type Prototype__List struct{}
   104  
   105  func (Prototype__List) NewBuilder() datamodel.NodeBuilder {
   106  	return &plainList__Builder{plainList__Assembler{w: &plainList{}}}
   107  }
   108  
   109  // -- NodeBuilder -->
   110  
   111  type plainList__Builder struct {
   112  	plainList__Assembler
   113  }
   114  
   115  func (nb *plainList__Builder) Build() datamodel.Node {
   116  	if nb.state != laState_finished {
   117  		panic("invalid state: assembler must be 'finished' before Build can be called!")
   118  	}
   119  	return nb.w
   120  }
   121  func (nb *plainList__Builder) Reset() {
   122  	*nb = plainList__Builder{}
   123  	nb.w = &plainList{}
   124  }
   125  
   126  // -- NodeAssembler -->
   127  
   128  type plainList__Assembler struct {
   129  	w *plainList
   130  
   131  	va plainList__ValueAssembler
   132  
   133  	state laState
   134  }
   135  type plainList__ValueAssembler struct {
   136  	la *plainList__Assembler
   137  }
   138  
   139  // laState is an enum of the state machine for a list assembler.
   140  // (this might be something to export reusably, but it's also very much an impl detail that need not be seen, so, dubious.)
   141  // it's similar to maState for maps, but has fewer states because we never have keys to assemble.
   142  type laState uint8
   143  
   144  const (
   145  	laState_initial  laState = iota // also the 'expect value or finish' state
   146  	laState_midValue                // waiting for a 'finished' state in the ValueAssembler.
   147  	laState_finished                // 'w' will also be nil, but this is a politer statement
   148  )
   149  
   150  func (plainList__Assembler) BeginMap(sizeHint int64) (datamodel.MapAssembler, error) {
   151  	return mixins.ListAssembler{TypeName: "list"}.BeginMap(0)
   152  }
   153  func (na *plainList__Assembler) BeginList(sizeHint int64) (datamodel.ListAssembler, error) {
   154  	if sizeHint < 0 {
   155  		sizeHint = 0
   156  	}
   157  	// Allocate storage space.
   158  	na.w.x = make([]datamodel.Node, 0, sizeHint)
   159  	// That's it; return self as the ListAssembler.  We already have all the right methods on this structure.
   160  	return na, nil
   161  }
   162  func (plainList__Assembler) AssignNull() error {
   163  	return mixins.ListAssembler{TypeName: "list"}.AssignNull()
   164  }
   165  func (plainList__Assembler) AssignBool(bool) error {
   166  	return mixins.ListAssembler{TypeName: "list"}.AssignBool(false)
   167  }
   168  func (plainList__Assembler) AssignInt(int64) error {
   169  	return mixins.ListAssembler{TypeName: "list"}.AssignInt(0)
   170  }
   171  func (plainList__Assembler) AssignFloat(float64) error {
   172  	return mixins.ListAssembler{TypeName: "list"}.AssignFloat(0)
   173  }
   174  func (plainList__Assembler) AssignString(string) error {
   175  	return mixins.ListAssembler{TypeName: "list"}.AssignString("")
   176  }
   177  func (plainList__Assembler) AssignBytes([]byte) error {
   178  	return mixins.ListAssembler{TypeName: "list"}.AssignBytes(nil)
   179  }
   180  func (plainList__Assembler) AssignLink(datamodel.Link) error {
   181  	return mixins.ListAssembler{TypeName: "list"}.AssignLink(nil)
   182  }
   183  func (na *plainList__Assembler) AssignNode(v datamodel.Node) error {
   184  	// Sanity check, then update, assembler state.
   185  	//  Update of state to 'finished' comes later; where exactly depends on if shortcuts apply.
   186  	if na.state != laState_initial {
   187  		panic("misuse")
   188  	}
   189  	// Copy the content.
   190  	if v2, ok := v.(*plainList); ok { // if our own type: shortcut.
   191  		// Copy the structure by value.
   192  		//  This means we'll have pointers into the same internal maps and slices;
   193  		//   this is okay, because the Node type promises it's immutable, and we are going to instantly finish ourselves to also maintain that.
   194  		// FIXME: the shortcut behaves differently than the long way: it discards any existing progress.  Doesn't violate immut, but is odd.
   195  		*na.w = *v2
   196  		na.state = laState_finished
   197  		return nil
   198  	}
   199  	// If the above shortcut didn't work, resort to a generic copy.
   200  	//  We call AssignNode for all the child values, giving them a chance to hit shortcuts even if we didn't.
   201  	if v.Kind() != datamodel.Kind_List {
   202  		return datamodel.ErrWrongKind{TypeName: "list", MethodName: "AssignNode", AppropriateKind: datamodel.KindSet_JustList, ActualKind: v.Kind()}
   203  	}
   204  	itr := v.ListIterator()
   205  	for !itr.Done() {
   206  		_, v, err := itr.Next()
   207  		if err != nil {
   208  			return err
   209  		}
   210  		if err := na.AssembleValue().AssignNode(v); err != nil {
   211  			return err
   212  		}
   213  	}
   214  	return na.Finish()
   215  }
   216  func (plainList__Assembler) Prototype() datamodel.NodePrototype {
   217  	return Prototype.List
   218  }
   219  
   220  // -- ListAssembler -->
   221  
   222  // AssembleValue is part of conforming to ListAssembler, which we do on
   223  // plainList__Assembler so that BeginList can just return a retyped pointer rather than new object.
   224  func (la *plainList__Assembler) AssembleValue() datamodel.NodeAssembler {
   225  	// Sanity check, then update, assembler state.
   226  	if la.state != laState_initial {
   227  		panic("misuse")
   228  	}
   229  	la.state = laState_midValue
   230  	// Make value assembler valid by giving it pointer back to whole 'la'; yield it.
   231  	la.va.la = la
   232  	return &la.va
   233  }
   234  
   235  // Finish is part of conforming to ListAssembler, which we do on
   236  // plainList__Assembler so that BeginList can just return a retyped pointer rather than new object.
   237  func (la *plainList__Assembler) Finish() error {
   238  	// Sanity check, then update, assembler state.
   239  	if la.state != laState_initial {
   240  		panic("misuse")
   241  	}
   242  	la.state = laState_finished
   243  	// validators could run and report errors promptly, if this type had any.
   244  	return nil
   245  }
   246  func (plainList__Assembler) ValuePrototype(_ int64) datamodel.NodePrototype {
   247  	return Prototype.Any
   248  }
   249  
   250  // -- ListAssembler.ValueAssembler -->
   251  
   252  func (lva *plainList__ValueAssembler) BeginMap(sizeHint int64) (datamodel.MapAssembler, error) {
   253  	ma := plainList__ValueAssemblerMap{}
   254  	ma.ca.w = &plainMap{}
   255  	ma.p = lva.la
   256  	_, err := ma.ca.BeginMap(sizeHint)
   257  	return &ma, err
   258  }
   259  func (lva *plainList__ValueAssembler) BeginList(sizeHint int64) (datamodel.ListAssembler, error) {
   260  	la := plainList__ValueAssemblerList{}
   261  	la.ca.w = &plainList{}
   262  	la.p = lva.la
   263  	_, err := la.ca.BeginList(sizeHint)
   264  	return &la, err
   265  }
   266  func (lva *plainList__ValueAssembler) AssignNull() error {
   267  	return lva.AssignNode(datamodel.Null)
   268  }
   269  func (lva *plainList__ValueAssembler) AssignBool(v bool) error {
   270  	vb := plainBool(v)
   271  	return lva.AssignNode(&vb)
   272  }
   273  func (lva *plainList__ValueAssembler) AssignInt(v int64) error {
   274  	vb := plainInt(v)
   275  	return lva.AssignNode(&vb)
   276  }
   277  func (lva *plainList__ValueAssembler) AssignFloat(v float64) error {
   278  	vb := plainFloat(v)
   279  	return lva.AssignNode(&vb)
   280  }
   281  func (lva *plainList__ValueAssembler) AssignString(v string) error {
   282  	vb := plainString(v)
   283  	return lva.AssignNode(&vb)
   284  }
   285  func (lva *plainList__ValueAssembler) AssignBytes(v []byte) error {
   286  	vb := plainBytes(v)
   287  	return lva.AssignNode(&vb)
   288  }
   289  func (lva *plainList__ValueAssembler) AssignLink(v datamodel.Link) error {
   290  	vb := plainLink{v}
   291  	return lva.AssignNode(&vb)
   292  }
   293  func (lva *plainList__ValueAssembler) AssignNode(v datamodel.Node) error {
   294  	lva.la.w.x = append(lva.la.w.x, v)
   295  	lva.la.state = laState_initial
   296  	lva.la = nil // invalidate self to prevent further incorrect use.
   297  	return nil
   298  }
   299  func (plainList__ValueAssembler) Prototype() datamodel.NodePrototype {
   300  	return Prototype.Any
   301  }
   302  
   303  type plainList__ValueAssemblerMap struct {
   304  	ca plainMap__Assembler
   305  	p  *plainList__Assembler // pointer back to parent, for final insert and state bump
   306  }
   307  
   308  // we briefly state only the methods we need to delegate here.
   309  // just embedding plainMap__Assembler also behaves correctly,
   310  //  but causes a lot of unnecessary autogenerated functions in the final binary.
   311  
   312  func (ma *plainList__ValueAssemblerMap) AssembleEntry(k string) (datamodel.NodeAssembler, error) {
   313  	return ma.ca.AssembleEntry(k)
   314  }
   315  func (ma *plainList__ValueAssemblerMap) AssembleKey() datamodel.NodeAssembler {
   316  	return ma.ca.AssembleKey()
   317  }
   318  func (ma *plainList__ValueAssemblerMap) AssembleValue() datamodel.NodeAssembler {
   319  	return ma.ca.AssembleValue()
   320  }
   321  func (plainList__ValueAssemblerMap) KeyPrototype() datamodel.NodePrototype {
   322  	return Prototype__String{}
   323  }
   324  func (plainList__ValueAssemblerMap) ValuePrototype(_ string) datamodel.NodePrototype {
   325  	return Prototype.Any
   326  }
   327  
   328  func (ma *plainList__ValueAssemblerMap) Finish() error {
   329  	if err := ma.ca.Finish(); err != nil {
   330  		return err
   331  	}
   332  	w := ma.ca.w
   333  	ma.ca.w = nil
   334  	return ma.p.va.AssignNode(w)
   335  }
   336  
   337  type plainList__ValueAssemblerList struct {
   338  	ca plainList__Assembler
   339  	p  *plainList__Assembler // pointer back to parent, for final insert and state bump
   340  }
   341  
   342  // we briefly state only the methods we need to delegate here.
   343  // just embedding plainList__Assembler also behaves correctly,
   344  //  but causes a lot of unnecessary autogenerated functions in the final binary.
   345  
   346  func (la *plainList__ValueAssemblerList) AssembleValue() datamodel.NodeAssembler {
   347  	return la.ca.AssembleValue()
   348  }
   349  func (plainList__ValueAssemblerList) ValuePrototype(_ int64) datamodel.NodePrototype {
   350  	return Prototype.Any
   351  }
   352  
   353  func (la *plainList__ValueAssemblerList) Finish() error {
   354  	if err := la.ca.Finish(); err != nil {
   355  		return err
   356  	}
   357  	w := la.ca.w
   358  	la.ca.w = nil
   359  	return la.p.va.AssignNode(w)
   360  }