typedNode.go 3.03 KB
Newer Older
1 2 3 4
package typed

import (
	"github.com/ipld/go-ipld-prime"
Eric Myhre's avatar
Eric Myhre committed
5
	"github.com/ipld/go-ipld-prime/schema"
6 7
)

8 9
// typed.Node is a superset of the ipld.Node interface, and has additional behaviors.
//
Eric Myhre's avatar
Eric Myhre committed
10
// A typed.Node can be inspected for its schema.Type and schema.Kind,
11 12 13 14 15 16 17 18 19 20
// which conveys much more and richer information than the Data Model layer
// ipld.ReprKind.
//
// There are many different implementations of typed.Node.
// One implementation can wrap any other existing ipld.Node (i.e., it's zero-copy)
// and promises that it has *already* been validated to match the typesystem.Type;
// another implementation similarly wraps any other existing ipld.Node, but
// defers to the typesystem validation checking to fields that are accessed;
// and when using code generation tools, all of the generated native Golang
// types produced by the codegen will each individually implement typed.Node.
21 22 23 24 25
//
// Note that typed.Node can wrap *other* typed.Node instances.
// Imagine you have two parts of a very large code base which have codegen'd
// components which are from different versions of a schema.  Smooth migrations
// and zero-copy type-safe data sharing between them: We can accommodate that!
26
type Node interface {
27 28 29 30 31 32 33 34 35
	// typed.Node acts just like a regular Node for almost all purposes;
	// which ReprKind it acts as is determined by the TypeKind.
	// (Note that the representation strategy of the type does *not* affect
	// the ReprKind of typed.Node -- rather, the representation strategy
	// affects the `.Representation().ReprKind()`.)
	//
	// For example: if the `.Type().Kind()` of this node is "struct",
	// it will act like ReprKind() == "map"
	// (even if Type().(Struct).ReprStrategy() is "tuple").
36
	ipld.Node
37

38
	// Type returns a reference to the reified schema.Type value.
Eric Myhre's avatar
Eric Myhre committed
39
	Type() schema.Type
40 41 42 43 44 45 46 47 48

	// Representation returns an ipld.Node which sees the data in this node
	// in its representation form.
	//
	// For example: if the `.Type().Kind()` of this node is "struct",
	// `.Representation().Kind()` may vary based on its representation strategy:
	// if the representation strategy is "map", then it will be ReprKind=="map";
	// if the streatgy is "tuple", then it will be ReprKind=="list".
	Representation() ipld.Node
49
}
Eric Myhre's avatar
Eric Myhre committed
50 51 52 53 54 55 56 57

// unboxing is... ugh, we probably should codegen an unbox method per concrete type.
//  (or, attach them to the non-pointer type, which would namespace in an alloc-free way, but i don't know if that's anything but confusing.)
//  there are notes about this from way back at 2019.01; reread to see if any remain relevant and valid.
// main important point is: it's not gonna be casting.
//  if casting was sufficient to unbox, it'd mean every method on the Node interface would be difficult to use as a field name on a struct type.  undesirable.
//   okay, or, alternative, we flip this to `superapi.Footype{}.Fields().FrobFieldName()`.  that strikes me as unlikely to be pleasing, though.
//    istm we can safely expect direct use of field names much, much more often that flipping back and forth to hypergeneric node; so we should optimize syntax for that accordingly.