diff --git a/README.md b/README.md index 98c6c14c998beed313a2cadfc6232a7c3ae7b0c8..ffb3732bd6fbe9b7a2612a69bfc757aae3e9a25e 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,8 @@ or new codecs, or new higher-order order functions!) - `github.com/ipld/go-ipld-prime/encoding/dagcbor` -- implementations of marshalling and unmarshalling as CBOR (a fast, binary serialization format). - `github.com/ipld/go-ipld-prime/encoding/dagjson` -- implementations of marshalling and unmarshalling as JSON (a popular human readable format). - `github.com/ipld/go-ipld-prime/linking/cid` -- imported as `cidlink` -- provides concrete implementations of `Link` as a CID. Also, the multicodec registry. -- `github.com/ipld/go-ipld-prime/schema` -- contains the `schema.Type` declarations, which represent IPLD Schema type information. -- `github.com/ipld/go-ipld-prime/impl/typed` -- contains the `typed.Node` interface, which enhances the basic `Node` to have additional features described by IPLD Schemas. +- `github.com/ipld/go-ipld-prime/schema` -- contains the `schema.Type` and `schema.TypedNode` interface declarations, which represent IPLD Schema type information. +- `github.com/ipld/go-ipld-prime/impl/typed` -- provides concrete implementations of `schema.TypedNode` which decorate a basic `Node` at runtime to have additional features described by IPLD Schemas. diff --git a/_rsrch/nodesolution/codec/unmarshal.go b/_rsrch/nodesolution/codec/unmarshal.go index c7004377ddc5643fd6a91d6b8d7b071bba7b17e0..504573c42d7416f92ecf792c17b4d34d7f93ef9a 100644 --- a/_rsrch/nodesolution/codec/unmarshal.go +++ b/_rsrch/nodesolution/codec/unmarshal.go @@ -53,7 +53,7 @@ func Unmarshal(na ipld.NodeAssembler, tokSrc shared.TokenSource) error { // starts with the first token already primed. Necessary to get recursion // to flow right without a peek+unpeek system. func unmarshal(na ipld.NodeAssembler, tokSrc shared.TokenSource, tk *tok.Token) error { - // FUTURE: check for typed.NodeBuilder that's going to parse a Link (they can slurp any token kind they want). + // FUTURE: check for schema.TypedNodeBuilder that's going to parse a Link (they can slurp any token kind they want). switch tk.Type { case tok.TMapOpen: expectLen := tk.Length diff --git a/_rsrch/nodesolution/errors.go b/_rsrch/nodesolution/errors.go index 2844f0e06813bac8e24e8cfbd4f04d8073905af2..a392c6dc326848d2fffc2a11d460782965692cd2 100644 --- a/_rsrch/nodesolution/errors.go +++ b/_rsrch/nodesolution/errors.go @@ -43,7 +43,7 @@ func (e ErrWrongKind) Error() string { // ErrNotExists may be returned from the lookup functions of the Node interface // to indicate a missing value. // -// Note that typed.ErrNoSuchField is another type of error which sometimes +// Note that schema.ErrNoSuchField is another type of error which sometimes // occurs in similar places as ErrNotExists. ErrNoSuchField is preferred // when handling data with constraints provided by a schema that mean that // a field can *never* exist (as differentiated from a map key which is diff --git a/_rsrch/nodesolution/node.go b/_rsrch/nodesolution/node.go index 9a710c16319b3349fe4a6655b5ba71d0e70859fd..45834d12c2016bd177d75e4ddf556b2d624a35b1 100644 --- a/_rsrch/nodesolution/node.go +++ b/_rsrch/nodesolution/node.go @@ -71,12 +71,12 @@ type Node interface { // Lookup is the equivalent of LookupString, but takes a reified Node // as a parameter instead of a plain string. // This mechanism is useful if working with typed maps (if the key types - // have constraints, and you already have a reified `typed.Node` value, + // have constraints, and you already have a reified `schema.TypedNode` value, // using that value can save parsing and validation costs); // and may simply be convenient if you already have a Node value in hand. // // (When writing generic functions over Node, a good rule of thumb is: - // when handling a map, check for `typed.Node`, and in this case prefer + // when handling a map, check for `schema.TypedNode`, and in this case prefer // the Lookup(Node) method; otherwise, favor LookupString; typically // implementations will have their fastest paths thusly.) Lookup(key Node) (Node, error) @@ -126,7 +126,7 @@ type Node interface { // Undefined nodes are returned when traversing a struct field that is // defined by a schema but unset in the data. (Undefined nodes are not - // possible otherwise; you'll only see them from `typed.Node`.) + // possible otherwise; you'll only see them from `schema.TypedNode`.) // The undefined flag is necessary so iterating over structs can // unambiguously make the distinction between values that are // present-and-null versus values that are absent. diff --git a/doc/dev/node-implementations.md b/doc/dev/node-implementations.md index 135fe936e01aa3eed2b4f5b39b574f4bcddc2881..482dd511c67a8f121e44c6f24bbd620073bf230d 100644 --- a/doc/dev/node-implementations.md +++ b/doc/dev/node-implementations.md @@ -26,7 +26,7 @@ Concerns: - 2. Performance A `Node` implementation must of course conform with the Data Model. -Some nodes (especially, those that also implement `typed.Node`) may also +Some nodes (especially, those that also implement `schema.TypedNode`) may also have additional constraints. A `Node` implementation must maintain immutablity, or it shatters abstractions @@ -70,7 +70,7 @@ Castability for strings is safe when the `Node` is "general" (i.e. has no constr With no constraints, there's no Correctness concern; and since strings are immutable, there's no Immutablity concern. -Castability for strings is often *unsafe* when the `Node` is a `typed.Node`. +Castability for strings is often *unsafe* when the `Node` is a `schema.TypedNode`. Typed nodes may have additional constraints, so we would have a Correctness problem. (Note that the way we handle constraints in codegeneration means users can add them *after* the code is generated, so the generation system can't presume @@ -94,7 +94,7 @@ If the struct type is unexported, the concern is absolved: the zero value can't be initialized outside the package. If the `Node` implementation has no other constraints -(e.g., it's not also a `typed.Node` in addition to just an `ipld.Node`), +(e.g., it's not also a `schema.TypedNode` in addition to just an `ipld.Node`), the concern is (alomst certainly) absolved: the zero value is simply a valid value. diff --git a/doc/schema.md b/doc/schema.md index 057b65807e46583d52366ab6959b1fbc071478e2..9886b08bbbd985e65e19555fc138214db29fd6e1 100644 --- a/doc/schema.md +++ b/doc/schema.md @@ -98,7 +98,7 @@ allowed to contain pointers (including cyclic references), etc. The reified schema can be computed purely from the schema declaration. The reified schema implementation lives in `go-ipld-prime//typed/system`, -and `go-ipld-prime//typed.Node` notably has a `Type() typesystem.Type` method +and `go-ipld-prime//schema.TypedNode` notably has a `Type() typesystem.Type` method which provides the reified schema information for any typed node. Note that multiple disjoint `typesystem.Universe` instances can exist in the diff --git a/encoding/dagcbor/unmarshal.go b/encoding/dagcbor/unmarshal.go index 2c57e4b15738938f7b2f2b9f37ac0fbdfeade286..741498c15aa7fc67a5808efe8adefa9f456e84eb 100644 --- a/encoding/dagcbor/unmarshal.go +++ b/encoding/dagcbor/unmarshal.go @@ -36,7 +36,7 @@ func Unmarshal(nb ipld.NodeBuilder, tokSrc shared.TokenSource) (ipld.Node, error // starts with the first token already primed. Necessary to get recursion // to flow right without a peek+unpeek system. func unmarshal(nb ipld.NodeBuilder, tokSrc shared.TokenSource, tk *tok.Token) (ipld.Node, error) { - // FUTURE: check for typed.NodeBuilder that's going to parse a Link (they can slurp any token kind they want). + // FUTURE: check for schema.TypedNodeBuilder that's going to parse a Link (they can slurp any token kind they want). switch tk.Type { case tok.TMapOpen: mb, err := nb.CreateMap() diff --git a/encoding/dagjson/unmarshal.go b/encoding/dagjson/unmarshal.go index 652bf44631f09e30f4c578faf007bbb5b9920c0b..d9a8decdf9c6cc1367e7f4734e7c48597063e116 100644 --- a/encoding/dagjson/unmarshal.go +++ b/encoding/dagjson/unmarshal.go @@ -31,7 +31,7 @@ func Unmarshal(nb ipld.NodeBuilder, tokSrc shared.TokenSource) (ipld.Node, error // starts with the first token already primed. Necessary to get recursion // to flow right without a peek+unpeek system. func unmarshal(nb ipld.NodeBuilder, tokSrc shared.TokenSource, tk *tok.Token) (ipld.Node, error) { - // FUTURE: check for typed.NodeBuilder that's going to parse a Link (they can slurp any token kind they want). + // FUTURE: check for schema.TypedNodeBuilder that's going to parse a Link (they can slurp any token kind they want). switch tk.Type { case tok.TMapOpen: mb, err := nb.CreateMap() diff --git a/encoding/unmarshal.go b/encoding/unmarshal.go index 7e581829d2be4d532411703d5ed764c7b3fc74ad..1c5415d0c399729ea19dfb137bdd35ec6228fa52 100644 --- a/encoding/unmarshal.go +++ b/encoding/unmarshal.go @@ -42,7 +42,7 @@ func Unmarshal(nb ipld.NodeBuilder, tokSrc shared.TokenSource) (ipld.Node, error // starts with the first token already primed. Necessary to get recursion // to flow right without a peek+unpeek system. func unmarshal(nb ipld.NodeBuilder, tokSrc shared.TokenSource, tk *tok.Token) (ipld.Node, error) { - // FUTURE: check for typed.NodeBuilder that's going to parse a Link (they can slurp any token kind they want). + // FUTURE: check for schema.TypedNodeBuilder that's going to parse a Link (they can slurp any token kind they want). switch tk.Type { case tok.TMapOpen: mb, err := nb.CreateMap() diff --git a/errors.go b/errors.go index 382b0a10dee3256d062ddd5c95febfb43ff54559..46a7fc4b946bf1d8df8c219a1737d416d08763e8 100644 --- a/errors.go +++ b/errors.go @@ -43,7 +43,7 @@ func (e ErrWrongKind) Error() string { // ErrNotExists may be returned from the lookup functions of the Node interface // to indicate a missing value. // -// Note that typed.ErrNoSuchField is another type of error which sometimes +// Note that schema.ErrNoSuchField is another type of error which sometimes // occurs in similar places as ErrNotExists. ErrNoSuchField is preferred // when handling data with constraints provided by a schema that mean that // a field can *never* exist (as differentiated from a map key which is @@ -64,7 +64,7 @@ func (e ErrNotExists) Error() string { type ErrInvalidKey struct { Reason string - // Perhaps typed.ErrNoSuchField could be folded into this? + // Perhaps schema.ErrNoSuchField could be folded into this? // Perhaps Reason could be replaced by an enum of "NoSuchField"|"NotAString"|"ConstraintRejected"? // Might be hard to get rid of the freetext field entirely -- constraints may be nontrivial to describe. } diff --git a/fluent/fluentNodeBuilder.go b/fluent/fluentNodeBuilder.go index 622cc5f68cfa0c2607ce5de512b08762e5ba5342..95352f182f2511b0f347309512507b045a93024f 100644 --- a/fluent/fluentNodeBuilder.go +++ b/fluent/fluentNodeBuilder.go @@ -81,7 +81,7 @@ func (nb *nodeBuilder) CreateMap(fn MapBuildingClosure) ipld.Node { if err != nil { panic(Error{err}) } - fn(mapBuilder{mb}, nb, nb) // FUTURE: check for typed.NodeBuilder; need to specialize latter params before calling down if so. + fn(mapBuilder{mb}, nb, nb) // FUTURE: check for schema.TypedNodeBuilder; need to specialize latter params before calling down if so. n, err := mb.Build() if err != nil { panic(Error{err}) @@ -93,7 +93,7 @@ func (nb *nodeBuilder) AmendMap(fn MapBuildingClosure) ipld.Node { if err != nil { panic(Error{err}) } - fn(mapBuilder{mb}, nb, nb) // FUTURE: check for typed.NodeBuilder; need to specialize latter params before calling down if so. + fn(mapBuilder{mb}, nb, nb) // FUTURE: check for schema.TypedNodeBuilder; need to specialize latter params before calling down if so. n, err := mb.Build() if err != nil { panic(Error{err}) @@ -105,7 +105,7 @@ func (nb *nodeBuilder) CreateList(fn ListBuildingClosure) ipld.Node { if err != nil { panic(Error{err}) } - fn(listBuilder{lb}, nb) // FUTURE: check for typed.NodeBuilder; need to specialize latter params before calling down if so. + fn(listBuilder{lb}, nb) // FUTURE: check for schema.TypedNodeBuilder; need to specialize latter params before calling down if so. n, err := lb.Build() if err != nil { panic(Error{err}) @@ -117,7 +117,7 @@ func (nb *nodeBuilder) AmendList(fn ListBuildingClosure) ipld.Node { if err != nil { panic(Error{err}) } - fn(listBuilder{lb}, nb) // FUTURE: check for typed.NodeBuilder; need to specialize latter params before calling down if so. + fn(listBuilder{lb}, nb) // FUTURE: check for schema.TypedNodeBuilder; need to specialize latter params before calling down if so. n, err := lb.Build() if err != nil { panic(Error{err}) diff --git a/impl/typed/typedLinkNode.go b/impl/typed/typedLinkNode.go index 271ebc19df68343c59964451ccd3e411f15ad629..e6f8080d257af501fdadd1c4a6caeb159cee14cc 100644 --- a/impl/typed/typedLinkNode.go +++ b/impl/typed/typedLinkNode.go @@ -2,7 +2,7 @@ package typed import "github.com/ipld/go-ipld-prime" -// typed.LinkNode is a superset of the typed.Node interface, and has one additional behavior. +// typed.LinkNode is a superset of the schema.TypedNode interface, and has one additional behavior. // // A typed.LinkNode contains a hint for the appropriate node builder to use for loading data // on the other side of the link contained within the node, so that it can be assembled diff --git a/impl/typed/typedNode.go b/impl/typed/typedNode.go deleted file mode 100644 index 1d9196cfe2029121120b2cbaa35880a49c25460c..0000000000000000000000000000000000000000 --- a/impl/typed/typedNode.go +++ /dev/null @@ -1,66 +0,0 @@ -package typed - -import ( - "github.com/ipld/go-ipld-prime" - "github.com/ipld/go-ipld-prime/schema" -) - -// typed.Node is a superset of the ipld.Node interface, and has additional behaviors. -// -// A typed.Node can be inspected for its schema.Type and schema.Kind, -// 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. -// -// 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! -// -// Typed nodes sometimes have slightly different behaviors than plain nodes: -// For example, when looking up fields on a typed node that's a struct, -// the error returned for a lookup with a key that's not a field name will -// be ErrNoSuchField (instead of ErrNotExists). -// These behaviors apply to the typed.Node only and not their representations; -// continuing the example, the .Representation().LookupString() method on -// that same node for the same key as plain `.LookupString()` will still -// return ErrNotExists, because the representation isn't a typed.Node! -type Node interface { - // 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"). - ipld.Node - - // Type returns a reference to the reified schema.Type value. - Type() schema.Type - - // 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 -} - -// 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. diff --git a/impl/typed/wrapStruct.go b/impl/typed/wrapStruct.go index 1673a352574b0388a9b70f54d378e0ebde667b1b..817b228033f9f5bb4310ddcc93020228e5db8d4d 100644 --- a/impl/typed/wrapStruct.go +++ b/impl/typed/wrapStruct.go @@ -8,7 +8,7 @@ import ( "github.com/ipld/go-ipld-prime/schema" ) -var _ Node = wrapnodeStruct{} +var _ schema.TypedNode = wrapnodeStruct{} type wrapnodeStruct struct { ipld.Node @@ -16,7 +16,7 @@ type wrapnodeStruct struct { } // Most of the 'nope' methods from the inner node are fine; -// we add the extra things required for typed.Node; +// we add the extra things required for schema.TypedNode; // we decorate the getters and iterators to handle the distinct path around optionals // and return a different error for missing fields; // length becomes fixed to a constant; @@ -42,7 +42,7 @@ func (tn wrapnodeStruct) LookupString(key string) (ipld.Node, error) { } return nil, e1 } - return nil, ErrNoSuchField{Type: tn.typ, FieldName: key} + return nil, schema.ErrNoSuchField{Type: tn.typ, FieldName: key} } func (tn wrapnodeStruct) MapIterator() ipld.MapIterator { @@ -168,10 +168,10 @@ func (mb *wrapnodeStruct_MapBuilder) Insert(k, v ipld.Node) error { // Check that the field exists at all. field := mb.typ.Field(ks) if field == nil { - return ErrNoSuchField{Type: mb.typ, FieldName: ks} + return schema.ErrNoSuchField{Type: mb.typ, FieldName: ks} } // Check that the value is assignable to this field, or return error. - vt, ok := v.(Node) + vt, ok := v.(schema.TypedNode) switch { case v.IsNull(): if !field.IsNullable() { @@ -184,7 +184,7 @@ func (mb *wrapnodeStruct_MapBuilder) Insert(k, v ipld.Node) error { } // if typed node, and it matches: carry on. default: - return fmt.Errorf("need typed.Node for insertion into struct") // FUTURE: maybe if it's a basic enough thing we sholud attempt coerce? + return fmt.Errorf("need schema.TypedNode for insertion into struct") // FUTURE: maybe if it's a basic enough thing we sholud attempt coerce? } // Insert the value, and note it's now been set. if err := mb.utmb.Insert(k, v); err != nil { diff --git a/must/must.go b/must/must.go index 71528bbb04921a12c4b0b2b7d5751e2b2d585f3d..9559c6d3164a03b2c54a1ac2f8d176a5df1f2d5f 100644 --- a/must/must.go +++ b/must/must.go @@ -18,7 +18,7 @@ package must import ( ipld "github.com/ipld/go-ipld-prime" - "github.com/ipld/go-ipld-prime/impl/typed" + "github.com/ipld/go-ipld-prime/schema" ) // must.NotError simply panics if given an error. @@ -47,18 +47,18 @@ func Node(n ipld.Node, e error) ipld.Node { // must.TypedNode helps write pointfree/chainable-style code // by taking a Node and an error and transforming any error into a panic. -// It will also cast the `ipld.Node` to a `typed.Node`, panicking if impossible. +// It will also cast the `ipld.Node` to a `schema.TypedNode`, panicking if impossible. // // Because golang supports implied destructuring of multiple-return functions // into arguments for another funtion of matching arity, it can be used like this: // // must.TypedNode(SomeNodeBuilder{}.CreateString("a")) // -func TypedNode(n ipld.Node, e error) typed.Node { +func TypedNode(n ipld.Node, e error) schema.TypedNode { if e != nil { panic(e) } - return n.(typed.Node) + return n.(schema.TypedNode) } // must.True panics if the given bool is false. diff --git a/node.go b/node.go index 1d8d50db592e4ed869a23ad844290cdffa46de6d..7260f436f1355cdc38fd0b3694ee39384b1463e5 100644 --- a/node.go +++ b/node.go @@ -71,12 +71,12 @@ type Node interface { // Lookup is the equivalent of LookupString, but takes a reified Node // as a parameter instead of a plain string. // This mechanism is useful if working with typed maps (if the key types - // have constraints, and you already have a reified `typed.Node` value, + // have constraints, and you already have a reified `schema.TypedNode` value, // using that value can save parsing and validation costs); // and may simply be convenient if you already have a Node value in hand. // // (When writing generic functions over Node, a good rule of thumb is: - // when handling a map, check for `typed.Node`, and in this case prefer + // when handling a map, check for `schema.TypedNode`, and in this case prefer // the Lookup(Node) method; otherwise, favor LookupString; typically // implementations will have their fastest paths thusly.) Lookup(key Node) (Node, error) @@ -128,7 +128,7 @@ type Node interface { // Undefined nodes are returned when traversing a struct field that is // defined by a schema but unset in the data. (Undefined nodes are not - // possible otherwise; you'll only see them from `typed.Node`.) + // possible otherwise; you'll only see them from `schema.TypedNode`.) // The undefined flag is necessary so iterating over structs can // unambiguously make the distinction between values that are // present-and-null versus values that are absent. diff --git a/nodeBuilder.go b/nodeBuilder.go index cbed0d716a2601b62418a6a98f60dd6058683d48..3add5e51efa5141f31a96ad2bcbbcfc175a80632 100644 --- a/nodeBuilder.go +++ b/nodeBuilder.go @@ -31,10 +31,10 @@ package ipld // `reflect.Type` handle it can use to create a new value of that native type; // similarly, schema-typed Nodes will yield a NodeBuilder that keeps the schema // info and type constraints from that Node! -// (Continuing the typed.Node example: if you have a typed.Node that is +// (Continuing the schema.TypedNode example: if you have a schema.TypedNode that is // constrained to be of some `type Foo = {Bar:Baz}` type, then any new Node // produced from its NodeBuilder will still answer -// `n.(typed.Node).Type().Name()` as `Foo`; and if +// `n.(schema.TypedNode).Type().Name()` as `Foo`; and if // `n.NodeBuilder().AmendMap().Insert(...)` is called with nodes of unmatching // type given to the insertion, the builder will error!) // diff --git a/impl/typed/errors.go b/schema/errors.go similarity index 84% rename from impl/typed/errors.go rename to schema/errors.go index 817688ad6f34c46ed54885aec69b30d416910dfd..d0f908ee010b769baff218c0845e3d561f51dd8e 100644 --- a/impl/typed/errors.go +++ b/schema/errors.go @@ -1,16 +1,14 @@ -package typed +package schema import ( "fmt" - - "github.com/ipld/go-ipld-prime/schema" ) // ErrNoSuchField may be returned from lookup functions on the Node // interface when a field is requested which doesn't exist, or from Insert // on a MapBuilder when a key doesn't match a field name in the structure. type ErrNoSuchField struct { - Type schema.Type + Type Type FieldName string } diff --git a/schema/gen/go/_test/wow_test.go b/schema/gen/go/_test/wow_test.go index bef3e10c429934c2d0e167a5fdacbffb2b05ef61..3dcacf5f52edbbf16dc8f79c29e4f25ef9b895bf 100644 --- a/schema/gen/go/_test/wow_test.go +++ b/schema/gen/go/_test/wow_test.go @@ -13,7 +13,7 @@ import ( "github.com/ipld/go-ipld-prime/encoding" "github.com/ipld/go-ipld-prime/fluent" ipldfree "github.com/ipld/go-ipld-prime/impl/free" - "github.com/ipld/go-ipld-prime/impl/typed" + "github.com/ipld/go-ipld-prime/schema" ) // TokenSourceBucket acts like a TokenSource by yielding tokens from a pre-made @@ -65,7 +65,7 @@ func TestScalarUnmarshal(t *testing.T) { func TestGeneratedStructs(t *testing.T) { t.Run("struct with map repr", func(t *testing.T) { var ( - v0, v1, v2, v3, v4 typed.Node + v0, v1, v2, v3, v4 schema.TypedNode ) t.Run("type-level build and read", func(t *testing.T) { t.Run("all fields set", func(t *testing.T) { @@ -76,7 +76,7 @@ func TestGeneratedStructs(t *testing.T) { mb.Insert(ipldfree.String("f3"), plz(String__NodeBuilder().CreateString("c"))) mb.Insert(ipldfree.String("f4"), plz(String__NodeBuilder().CreateString("d"))) n, err := mb.Build() - v0 = n.(typed.Node) + v0 = n.(schema.TypedNode) Wish(t, err, ShouldEqual, nil) Wish(t, n.ReprKind(), ShouldEqual, ipld.ReprKind_Map) @@ -93,7 +93,7 @@ func TestGeneratedStructs(t *testing.T) { mb.Insert(ipldfree.String("f3"), plz(String__NodeBuilder().CreateString("c"))) mb.Insert(ipldfree.String("f4"), ipld.Null) n, err := mb.Build() - v1 = n.(typed.Node) + v1 = n.(schema.TypedNode) Wish(t, err, ShouldEqual, nil) Wish(t, n.ReprKind(), ShouldEqual, ipld.ReprKind_Map) @@ -111,7 +111,7 @@ func TestGeneratedStructs(t *testing.T) { mb.Insert(ipldfree.String("f3"), ipld.Null) mb.Insert(ipldfree.String("f4"), plz(String__NodeBuilder().CreateString("d"))) n, err := mb.Build() - v2 = n.(typed.Node) + v2 = n.(schema.TypedNode) Wish(t, err, ShouldEqual, nil) Wish(t, n.ReprKind(), ShouldEqual, ipld.ReprKind_Map) @@ -128,7 +128,7 @@ func TestGeneratedStructs(t *testing.T) { mb.Insert(ipldfree.String("f3"), plz(String__NodeBuilder().CreateString("c"))) mb.Insert(ipldfree.String("f4"), plz(String__NodeBuilder().CreateString("d"))) n, err := mb.Build() - v3 = n.(typed.Node) + v3 = n.(schema.TypedNode) Wish(t, err, ShouldEqual, nil) Wish(t, n.ReprKind(), ShouldEqual, ipld.ReprKind_Map) @@ -145,7 +145,7 @@ func TestGeneratedStructs(t *testing.T) { mb.Insert(ipldfree.String("f2"), plz(String__NodeBuilder().CreateString("b"))) mb.Insert(ipldfree.String("f4"), plz(String__NodeBuilder().CreateString("d"))) n, err := mb.Build() - v4 = n.(typed.Node) + v4 = n.(schema.TypedNode) Wish(t, err, ShouldEqual, nil) Wish(t, n.ReprKind(), ShouldEqual, ipld.ReprKind_Map) diff --git a/schema/gen/go/gen.go b/schema/gen/go/gen.go index 951d952390d65559b3890e06968797e9a2eb8d9e..c423cb9b395a244009ce431722ea0347e989bf8b 100644 --- a/schema/gen/go/gen.go +++ b/schema/gen/go/gen.go @@ -30,7 +30,7 @@ type typedNodeGenerator interface { EmitNativeBuilder(io.Writer) // typically emits some kind of struct that has a Build method. EmitNativeMaybe(io.Writer) // a pointer-free 'maybe' mechanism is generated for all types. - // -- the typed.Node.Type method and vars --> + // -- the schema.TypedNode.Type method and vars --> EmitTypedNodeMethodType(io.Writer) // these emit dummies for now @@ -100,7 +100,6 @@ func EmitFileHeader(packageName string, w io.Writer) { fmt.Fprintf(w, "package %s\n\n", packageName) fmt.Fprintf(w, "import (\n") fmt.Fprintf(w, "\tipld \"github.com/ipld/go-ipld-prime\"\n") - fmt.Fprintf(w, "\t\"github.com/ipld/go-ipld-prime/impl/typed\"\n") fmt.Fprintf(w, "\t\"github.com/ipld/go-ipld-prime/schema\"\n") fmt.Fprintf(w, ")\n\n") fmt.Fprintf(w, "// Code generated go-ipld-prime DO NOT EDIT.\n\n") diff --git a/schema/gen/go/genKindBytes.go b/schema/gen/go/genKindBytes.go index aaa3a80d518f95758a6357660055cb636c5d84b3..3ec09e288a94088ab95758a8b2df25c7dbe56768 100644 --- a/schema/gen/go/genKindBytes.go +++ b/schema/gen/go/genKindBytes.go @@ -46,12 +46,12 @@ func (gk generateKindBytes) EmitNativeMaybe(w io.Writer) { // TODO this can most likely be extracted and DRY'd, just not 100% sure yet doTemplate(` type Maybe{{ .Type | mungeTypeNodeIdent }} struct { - Maybe typed.Maybe + Maybe schema.Maybe Value {{ .Type | mungeTypeNodeIdent }} } func (m Maybe{{ .Type | mungeTypeNodeIdent }}) Must() {{ .Type | mungeTypeNodeIdent }} { - if m.Maybe != typed.Maybe_Value { + if m.Maybe != schema.Maybe_Value { panic("unbox of a maybe rejected") } return m.Value diff --git a/schema/gen/go/genKindBytesNode.go b/schema/gen/go/genKindBytesNode.go index 99f7e665a823cec2c02d74133295ac7b5b5fcbb6..7fed94edc7d6dfde2d4c93f64b46840a98db464a 100644 --- a/schema/gen/go/genKindBytesNode.go +++ b/schema/gen/go/genKindBytesNode.go @@ -11,7 +11,7 @@ import ( func (gk generateKindBytes) EmitNodeType(w io.Writer) { doTemplate(` var _ ipld.Node = {{ .Type | mungeTypeNodeIdent }}{} - var _ typed.Node = {{ .Type | mungeTypeNodeIdent }}{} + var _ schema.TypedNode = {{ .Type | mungeTypeNodeIdent }}{} `, w, gk) } diff --git a/schema/gen/go/genKindInt.go b/schema/gen/go/genKindInt.go index 3fea5d29d52848407fe2fca3df58b44437b2518d..3d97a33f2248e365ef0ef19b5a5c299ad792deea 100644 --- a/schema/gen/go/genKindInt.go +++ b/schema/gen/go/genKindInt.go @@ -51,12 +51,12 @@ func (gk generateKindInt) EmitNativeMaybe(w io.Writer) { // TODO this can most likely be extracted and DRY'd, just not 100% sure yet doTemplate(` type Maybe{{ .Type | mungeTypeNodeIdent }} struct { - Maybe typed.Maybe + Maybe schema.Maybe Value {{ .Type | mungeTypeNodeIdent }} } func (m Maybe{{ .Type | mungeTypeNodeIdent }}) Must() {{ .Type | mungeTypeNodeIdent }} { - if m.Maybe != typed.Maybe_Value { + if m.Maybe != schema.Maybe_Value { panic("unbox of a maybe rejected") } return m.Value diff --git a/schema/gen/go/genKindIntNode.go b/schema/gen/go/genKindIntNode.go index 88123055ccda7b2c1737b94457845e131f8b84fd..17d35659a5f89919c6331b91580432763b9cfed3 100644 --- a/schema/gen/go/genKindIntNode.go +++ b/schema/gen/go/genKindIntNode.go @@ -11,7 +11,7 @@ import ( func (gk generateKindInt) EmitNodeType(w io.Writer) { doTemplate(` var _ ipld.Node = {{ .Type | mungeTypeNodeIdent }}{} - var _ typed.Node = {{ .Type | mungeTypeNodeIdent }}{} + var _ schema.TypedNode = {{ .Type | mungeTypeNodeIdent }}{} `, w, gk) } diff --git a/schema/gen/go/genKindLink.go b/schema/gen/go/genKindLink.go index a00526ebccbc335cb73a369c335e42e0f3c31bbc..bfc57f2b5bb16ee8f95220292e8b00ac434cd30c 100644 --- a/schema/gen/go/genKindLink.go +++ b/schema/gen/go/genKindLink.go @@ -46,12 +46,12 @@ func (gk generateKindLink) EmitNativeMaybe(w io.Writer) { // TODO this can most likely be extracted and DRY'd, just not 100% sure yet doTemplate(` type Maybe{{ .Type | mungeTypeNodeIdent }} struct { - Maybe typed.Maybe + Maybe schema.Maybe Value {{ .Type | mungeTypeNodeIdent }} } func (m Maybe{{ .Type | mungeTypeNodeIdent }}) Must() {{ .Type | mungeTypeNodeIdent }} { - if m.Maybe != typed.Maybe_Value { + if m.Maybe != schema.Maybe_Value { panic("unbox of a maybe rejected") } return m.Value diff --git a/schema/gen/go/genKindLinkNode.go b/schema/gen/go/genKindLinkNode.go index 6bfe465eecab6a7995288a62e0fe52ac93f76b4d..2dd1a7ea206bb4140dd921e95a73cd64b2672357 100644 --- a/schema/gen/go/genKindLinkNode.go +++ b/schema/gen/go/genKindLinkNode.go @@ -11,7 +11,7 @@ import ( func (gk generateKindLink) EmitNodeType(w io.Writer) { doTemplate(` var _ ipld.Node = {{ .Type | mungeTypeNodeIdent }}{} - var _ typed.Node = {{ .Type | mungeTypeNodeIdent }}{} + var _ schema.TypedNode = {{ .Type | mungeTypeNodeIdent }}{} `, w, gk) } diff --git a/schema/gen/go/genKindList.go b/schema/gen/go/genKindList.go index 6a19e53d1882168f029b15b6610c9eb6f6bcfce7..4950ba7ea12aee9af0269a5bae4a4e38653b5a60 100644 --- a/schema/gen/go/genKindList.go +++ b/schema/gen/go/genKindList.go @@ -50,12 +50,12 @@ func (gk generateKindList) EmitNativeMaybe(w io.Writer) { // TODO this can most likely be extracted and DRY'd, just not 100% sure yet doTemplate(` type Maybe{{ .Type | mungeTypeNodeIdent }} struct { - Maybe typed.Maybe + Maybe schema.Maybe Value {{ .Type | mungeTypeNodeIdent }} } func (m Maybe{{ .Type | mungeTypeNodeIdent }}) Must() {{ .Type | mungeTypeNodeIdent }} { - if m.Maybe != typed.Maybe_Value { + if m.Maybe != schema.Maybe_Value { panic("unbox of a maybe rejected") } return m.Value diff --git a/schema/gen/go/genKindListNode.go b/schema/gen/go/genKindListNode.go index e874915aa3a8510b26ac3d20ab9a768821a0d58b..c51e4ba98bc0134db5f227f16c48caa1e8685b0d 100644 --- a/schema/gen/go/genKindListNode.go +++ b/schema/gen/go/genKindListNode.go @@ -11,7 +11,7 @@ import ( func (gk generateKindList) EmitNodeType(w io.Writer) { doTemplate(` var _ ipld.Node = {{ .Type | mungeTypeNodeIdent }}{} - var _ typed.Node = {{ .Type | mungeTypeNodeIdent }}{} + var _ schema.TypedNode = {{ .Type | mungeTypeNodeIdent }}{} `, w, gk) } @@ -151,8 +151,8 @@ func (gk generateNbKindList) EmitNodebuilderMethodCreateList(w io.Writer) { // - This builder, being all about semantics and not at all about serialization, // is order-insensitive. // - We don't specially handle being given 'undef' as a value. - // It just falls into the "need a typed.Node" error bucket. - // - We only accept *codegenerated values* -- a typed.Node created + // It just falls into the "need a schema.TypedNode" error bucket. + // - We only accept *codegenerated values* -- a schema.TypedNode created // in the same schema universe *isn't accepted*. // REVIEW: We could try to accept those, but it might have perf/sloc costs, // and it's hard to imagine a user story that gets here. @@ -214,9 +214,9 @@ func (gk generateNbKindList) EmitNodebuilderMethodCreateList(w io.Writer) { panic("type mismatch on struct field assignment: cannot assign null to non-nullable field") // FIXME need an error type for this } {{- end}} - tv, ok := v.(typed.Node) + tv, ok := v.(schema.TypedNode) if !ok { - panic("need typed.Node for insertion into struct") // FIXME need an error type for this + panic("need schema.TypedNode for insertion into struct") // FIXME need an error type for this } _, ok = v.({{ .Type.ValueType | mungeTypeNodeIdent }}) if !ok { diff --git a/schema/gen/go/genKindString.go b/schema/gen/go/genKindString.go index 7846da6605b87266bec86c9f128cef898dd36d9e..af342f3c33ef662f075a17f3b7338369fc915388 100644 --- a/schema/gen/go/genKindString.go +++ b/schema/gen/go/genKindString.go @@ -72,12 +72,12 @@ func (gk generateKindString) EmitNativeBuilder(w io.Writer) { func (gk generateKindString) EmitNativeMaybe(w io.Writer) { doTemplate(` type Maybe{{ .Type | mungeTypeNodeIdent }} struct { - Maybe typed.Maybe + Maybe schema.Maybe Value {{ .Type | mungeTypeNodeIdent }} } func (m Maybe{{ .Type | mungeTypeNodeIdent }}) Must() {{ .Type | mungeTypeNodeIdent }} { - if m.Maybe != typed.Maybe_Value { + if m.Maybe != schema.Maybe_Value { panic("unbox of a maybe rejected") } return m.Value diff --git a/schema/gen/go/genKindStringNode.go b/schema/gen/go/genKindStringNode.go index af88f0f01a3db650dcffd375a9ac84d9a0a928ac..0972d8a3033a5431496d40d210e36b6046eff743 100644 --- a/schema/gen/go/genKindStringNode.go +++ b/schema/gen/go/genKindStringNode.go @@ -11,7 +11,7 @@ import ( func (gk generateKindString) EmitNodeType(w io.Writer) { doTemplate(` var _ ipld.Node = {{ .Type | mungeTypeNodeIdent }}{} - var _ typed.Node = {{ .Type | mungeTypeNodeIdent }}{} + var _ schema.TypedNode = {{ .Type | mungeTypeNodeIdent }}{} `, w, gk) } diff --git a/schema/gen/go/genKindStruct.go b/schema/gen/go/genKindStruct.go index c3b05e9252a9dd8034e206335888ab5885179727..a668c4cbc784a97a0e31531f395344b56904fafb 100644 --- a/schema/gen/go/genKindStruct.go +++ b/schema/gen/go/genKindStruct.go @@ -60,11 +60,11 @@ func (gk generateKindStruct) EmitNativeBuilder(w io.Writer) { {{- if or $field.IsOptional $field.IsNullable }} {{- /* if both modifiers present, anything goes */ -}} {{- else if $field.IsOptional }} - if b.{{ $field.Name | titlize }}.Maybe == typed.Maybe_Null { + if b.{{ $field.Name | titlize }}.Maybe == schema.Maybe_Null { return {{ $field.Type | mungeTypeNodeIdent }}{}, fmt.Errorf("cannot be absent") } {{- else if $field.IsNullable }} - if b.{{ $field.Name | titlize }}.Maybe == typed.Maybe_Absent { + if b.{{ $field.Name | titlize }}.Maybe == schema.Maybe_Absent { return {{ $field.Type | mungeTypeNodeIdent }}{}, fmt.Errorf("cannot be null") } {{- end}} @@ -88,12 +88,12 @@ func (gk generateKindStruct) EmitNativeBuilder(w io.Writer) { func (gk generateKindStruct) EmitNativeMaybe(w io.Writer) { doTemplate(` type Maybe{{ .Type | mungeTypeNodeIdent }} struct { - Maybe typed.Maybe + Maybe schema.Maybe Value {{ .Type | mungeTypeNodeIdent }} } func (m Maybe{{ .Type | mungeTypeNodeIdent }}) Must() {{ .Type | mungeTypeNodeIdent }} { - if m.Maybe != typed.Maybe_Value { + if m.Maybe != schema.Maybe_Value { panic("unbox of a maybe rejected") } return m.Value diff --git a/schema/gen/go/genKindStructNode.go b/schema/gen/go/genKindStructNode.go index 9fee6d502bfa477c4a398cea1e9e1303a5607c57..c9f8c8ef3696a7add73dabc1b5ffa109c4dd4253 100644 --- a/schema/gen/go/genKindStructNode.go +++ b/schema/gen/go/genKindStructNode.go @@ -11,7 +11,7 @@ import ( func (gk generateKindStruct) EmitNodeType(w io.Writer) { doTemplate(` var _ ipld.Node = {{ .Type | mungeTypeNodeIdent }}{} - var _ typed.Node = {{ .Type | mungeTypeNodeIdent }}{} + var _ schema.TypedNode = {{ .Type | mungeTypeNodeIdent }}{} `, w, gk) } @@ -39,12 +39,12 @@ func (gk generateKindStruct) EmitNodeMethodLookupString(w io.Writer) { {{- range $field := .Type.Fields }} case "{{ $field.Name }}": {{- if $field.IsOptional }} - if x.d.{{ $field.Name | titlize }}.Maybe == typed.Maybe_Absent { + if x.d.{{ $field.Name | titlize }}.Maybe == schema.Maybe_Absent { return ipld.Undef, nil } {{- end}} {{- if $field.IsNullable }} - if x.d.{{ $field.Name | titlize }}.Maybe == typed.Maybe_Null { + if x.d.{{ $field.Name | titlize }}.Maybe == schema.Maybe_Null { return ipld.Null, nil } {{- end}} @@ -55,7 +55,7 @@ func (gk generateKindStruct) EmitNodeMethodLookupString(w io.Writer) { {{- end}} {{- end}} default: - return nil, typed.ErrNoSuchField{Type: nil /*TODO*/, FieldName: key} + return nil, schema.ErrNoSuchField{Type: nil /*TODO*/, FieldName: key} } } `, w, gk) @@ -95,13 +95,13 @@ func (gk generateKindStruct) EmitNodeMethodMapIterator(w io.Writer) { case {{ $i }}: k = String{"{{ $field.Name }}"} {{- if $field.IsOptional }} - if itr.node.d.{{ $field.Name | titlize }}.Maybe == typed.Maybe_Absent { + if itr.node.d.{{ $field.Name | titlize }}.Maybe == schema.Maybe_Absent { v = ipld.Undef break } {{- end}} {{- if $field.IsNullable }} - if itr.node.d.{{ $field.Name | titlize }}.Maybe == typed.Maybe_Null { + if itr.node.d.{{ $field.Name | titlize }}.Maybe == schema.Maybe_Null { v = ipld.Null break } @@ -178,8 +178,8 @@ func (gk generateNbKindStruct) EmitNodebuilderMethodCreateMap(w io.Writer) { // - This builder, being all about semantics and not at all about serialization, // is order-insensitive. // - We don't specially handle being given 'undef' as a value. - // It just falls into the "need a typed.Node" error bucket. - // - We only accept *codegenerated values* -- a typed.Node created + // It just falls into the "need a schema.TypedNode" error bucket. + // - We only accept *codegenerated values* -- a schema.TypedNode created // in the same schema universe *isn't accepted*. // REVIEW: We could try to accept those, but it might have perf/sloc costs, // and it's hard to imagine a user story that gets here. @@ -195,7 +195,7 @@ func (gk generateNbKindStruct) EmitNodebuilderMethodCreateMap(w io.Writer) { mb := &{{ .Type | mungeTypeNodeMapBuilderIdent }}{v:&{{ .Type | mungeTypeNodeIdent }}{}} {{- range $field := .Type.Fields }} {{- if $field.IsOptional }} - mb.v.d.{{ $field.Name | titlize }}.Maybe = typed.Maybe_Absent + mb.v.d.{{ $field.Name | titlize }}.Maybe = schema.Maybe_Absent {{- end}} {{- end}} return mb, nil @@ -221,7 +221,7 @@ func (gk generateNbKindStruct) EmitNodebuilderMethodCreateMap(w io.Writer) { case "{{ $field.Name }}": {{- if $field.IsNullable }} if v.IsNull() { - mb.v.d.{{ $field.Name | titlize}}.Maybe = typed.Maybe_Null + mb.v.d.{{ $field.Name | titlize}}.Maybe = schema.Maybe_Null {{- if not $field.IsOptional }} mb.{{ $field.Name }}__isset = true {{- end}} @@ -232,9 +232,9 @@ func (gk generateNbKindStruct) EmitNodebuilderMethodCreateMap(w io.Writer) { panic("type mismatch on struct field assignment: cannot assign null to non-nullable field") // FIXME need an error type for this } {{- end}} - tv, ok := v.(typed.Node) + tv, ok := v.(schema.TypedNode) if !ok { - panic("need typed.Node for insertion into struct") // FIXME need an error type for this + panic("need schema.TypedNode for insertion into struct") // FIXME need an error type for this } x, ok := v.({{ $field.Type | mungeTypeNodeIdent }}) if !ok { @@ -247,13 +247,13 @@ func (gk generateNbKindStruct) EmitNodebuilderMethodCreateMap(w io.Writer) { mb.v.d.{{ $field.Name | titlize}} = x {{- end}} {{- if $field.IsOptional }} - mb.v.d.{{ $field.Name | titlize}}.Maybe = typed.Maybe_Value + mb.v.d.{{ $field.Name | titlize}}.Maybe = schema.Maybe_Value {{- else}} mb.{{ $field.Name }}__isset = true {{- end}} {{- end}} default: - return typed.ErrNoSuchField{Type: nil /*TODO:typelit*/, FieldName: ks} + return schema.ErrNoSuchField{Type: nil /*TODO:typelit*/, FieldName: ks} } return nil } @@ -283,7 +283,7 @@ func (gk generateNbKindStruct) EmitNodebuilderMethodCreateMap(w io.Writer) { return {{ $field.Type | mungeNodebuilderConstructorIdent }}() {{- end}} default: - panic(typed.ErrNoSuchField{Type: nil /*TODO:typelit*/, FieldName: ks}) + panic(schema.ErrNoSuchField{Type: nil /*TODO:typelit*/, FieldName: ks}) } return nil } diff --git a/schema/gen/go/genKindStructReprMap.go b/schema/gen/go/genKindStructReprMap.go index 68888ed2d50626ffe2b421a50f92b5b887e98c30..2bfde776c0372dd8e20fc014dcdcb88580ec9c1a 100644 --- a/schema/gen/go/genKindStructReprMap.go +++ b/schema/gen/go/genKindStructReprMap.go @@ -50,12 +50,12 @@ func (gk generateStructReprMapNode) EmitNodeMethodLookupString(w io.Writer) { {{- range $field := .Type.Fields }} case "{{ $field | $type.RepresentationStrategy.GetFieldKey }}": {{- if $field.IsOptional }} - if rn.n.d.{{ $field.Name | titlize}}.Maybe == typed.Maybe_Absent { + if rn.n.d.{{ $field.Name | titlize}}.Maybe == schema.Maybe_Absent { return ipld.Undef, ipld.ErrNotExists{ipld.PathSegmentOfString(key)} } {{- end}} {{- if $field.IsNullable }} - if rn.n.d.{{ $field.Name | titlize}}.Maybe == typed.Maybe_Null { + if rn.n.d.{{ $field.Name | titlize}}.Maybe == schema.Maybe_Null { return ipld.Null, nil } {{- end}} @@ -66,7 +66,7 @@ func (gk generateStructReprMapNode) EmitNodeMethodLookupString(w io.Writer) { {{- end}} {{- end}} default: - return nil, typed.ErrNoSuchField{Type: nil /*TODO*/, FieldName: key} + return nil, schema.ErrNoSuchField{Type: nil /*TODO*/, FieldName: key} } } `, w, gk) @@ -110,13 +110,13 @@ func (gk generateStructReprMapNode) EmitNodeMethodMapIterator(w io.Writer) { case {{ $i }}: k = String{"{{ $field | $type.RepresentationStrategy.GetFieldKey }}"} {{- if $field.IsOptional }} - if itr.node.d.{{ $field.Name | titlize}}.Maybe == typed.Maybe_Absent { + if itr.node.d.{{ $field.Name | titlize}}.Maybe == schema.Maybe_Absent { itr.idx++ continue } {{- end}} {{- if $field.IsNullable }} - if itr.node.d.{{ $field.Name | titlize}}.Maybe == typed.Maybe_Null { + if itr.node.d.{{ $field.Name | titlize}}.Maybe == schema.Maybe_Null { v = ipld.Null break } @@ -150,7 +150,7 @@ func (gk generateStructReprMapNode) EmitNodeMethodLength(w io.Writer) { l := {{ len .Type.Fields }} {{- range $field := .Type.Fields }} {{- if $field.IsOptional }} - if rn.n.d.{{ $field.Name | titlize}}.Maybe == typed.Maybe_Absent { + if rn.n.d.{{ $field.Name | titlize}}.Maybe == schema.Maybe_Absent { l-- } {{- end}} @@ -220,7 +220,7 @@ func (gk generateStructReprMapNb) EmitNodebuilderMethodCreateMap(w io.Writer) { mb := &{{ .Type | mungeTypeReprNodeMapBuilderIdent }}{v:&{{ .Type | mungeTypeNodeIdent }}{}} {{- range $field := .Type.Fields }} {{- if $field.IsOptional }} - mb.v.d.{{ $field.Name | titlize }}.Maybe = typed.Maybe_Absent + mb.v.d.{{ $field.Name | titlize }}.Maybe = schema.Maybe_Absent {{- end}} {{- end}} return mb, nil @@ -247,7 +247,7 @@ func (gk generateStructReprMapNb) EmitNodebuilderMethodCreateMap(w io.Writer) { } {{- if $field.IsNullable }} if v.IsNull() { - mb.v.d.{{ $field.Name | titlize}}.Maybe = typed.Maybe_Null + mb.v.d.{{ $field.Name | titlize}}.Maybe = schema.Maybe_Null mb.{{ $field.Name }}__isset = true return nil } @@ -256,9 +256,9 @@ func (gk generateStructReprMapNb) EmitNodebuilderMethodCreateMap(w io.Writer) { panic("type mismatch on struct field assignment: cannot assign null to non-nullable field") // FIXME need an error type for this } {{- end}} - tv, ok := v.(typed.Node) + tv, ok := v.(schema.TypedNode) if !ok { - panic("need typed.Node for insertion into struct") // FIXME need an error type for this + panic("need schema.TypedNode for insertion into struct") // FIXME need an error type for this } x, ok := v.({{ $field.Type | mungeTypeNodeIdent }}) if !ok { @@ -271,12 +271,12 @@ func (gk generateStructReprMapNb) EmitNodebuilderMethodCreateMap(w io.Writer) { mb.v.d.{{ $field.Name | titlize}} = x {{- end}} {{- if $field.IsOptional }} - mb.v.d.{{ $field.Name | titlize}}.Maybe = typed.Maybe_Value + mb.v.d.{{ $field.Name | titlize}}.Maybe = schema.Maybe_Value {{- end}} mb.{{ $field.Name }}__isset = true {{- end}} default: - return typed.ErrNoSuchField{Type: nil /*TODO:typelit*/, FieldName: ks} + return schema.ErrNoSuchField{Type: nil /*TODO:typelit*/, FieldName: ks} } return nil } @@ -307,7 +307,7 @@ func (gk generateStructReprMapNb) EmitNodebuilderMethodCreateMap(w io.Writer) { return {{ $field.Type | mungeNodebuilderConstructorIdent }}() {{- end}} default: - panic(typed.ErrNoSuchField{Type: nil /*TODO:typelit*/, FieldName: ks}) + panic(schema.ErrNoSuchField{Type: nil /*TODO:typelit*/, FieldName: ks}) } return nil } diff --git a/impl/typed/maybe.go b/schema/maybe.go similarity index 87% rename from impl/typed/maybe.go rename to schema/maybe.go index ab36facec2a9254fd5ba67905f65c17e9a6d4c2d..670a6bcf6c4eb3c83b5076b3afc560bafa7c09b1 100644 --- a/impl/typed/maybe.go +++ b/schema/maybe.go @@ -1,4 +1,4 @@ -package typed +package schema type Maybe uint8 diff --git a/schema/tests/doc.go b/schema/tests/doc.go index 8b1efbbdf9f6a6dc0a808fca3b75a959809d593c..dacc6f7727991be45189cfcaf240b76a4e399f98 100644 --- a/schema/tests/doc.go +++ b/schema/tests/doc.go @@ -1,4 +1,4 @@ // The `schema/tests` package contains behavioral tests for type-constrained // Node implementations -- meant to work with either codegenerated Nodes OR -// with the runtime typed.Node wrappers, checking for the same behavior on each. +// with the runtime schema.TypedNode wrappers, checking for the same behavior on each. package tests diff --git a/schema/type.go b/schema/type.go index 0f5f36c32403be473ef028d6fa5bca53994c3e92..dd6c622f13bab783d92c0fc25f317c5f8311e774 100644 --- a/schema/type.go +++ b/schema/type.go @@ -59,13 +59,13 @@ type Type interface { // // Note that a schema.Kind is a different enum than ipld.ReprKind; // and furthermore, there's no strict relationship between them. - // typed.Node values can be described by *two* distinct ReprKinds: + // schema.TypedNode values can be described by *two* distinct ReprKinds: // one which describes how the Node itself will act, // and another which describes how the Node presents for serialization. // For some combinations of Type and representation strategy, one or both // of the ReprKinds can be determined statically; but not always: // it can sometimes be necessary to inspect the value quite concretely - // (e.g., `typed.Node{}.Representation().ReprKind()`) in order to find + // (e.g., `schema.TypedNode{}.Representation().ReprKind()`) in order to find // out exactly how a node will be serialized! This is because some types // can vary in representation kind based on their value (specifically, // kinded-representation unions have this property). diff --git a/schema/typedNode.go b/schema/typedNode.go new file mode 100644 index 0000000000000000000000000000000000000000..24dd00e1f106397a4770e5e6e21e7a320cd70a7b --- /dev/null +++ b/schema/typedNode.go @@ -0,0 +1,52 @@ +package schema + +import ( + "github.com/ipld/go-ipld-prime" +) + +// schema.TypedNode is a superset of the ipld.Node interface, and has additional behaviors. +// +// A schema.TypedNode can be inspected for its schema.Type and schema.Kind, +// which conveys much more and richer information than the Data Model layer +// ipld.ReprKind. +// +// There are many different implementations of schema.TypedNode. +// 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 schema.TypedNode. +// +// Typed nodes sometimes have slightly different behaviors than plain nodes: +// For example, when looking up fields on a typed node that's a struct, +// the error returned for a lookup with a key that's not a field name will +// be ErrNoSuchField (instead of ErrNotExists). +// These behaviors apply to the schema.TypedNode only and not their representations; +// continuing the example, the .Representation().LookupString() method on +// that same node for the same key as plain `.LookupString()` will still +// return ErrNotExists, because the representation isn't a schema.TypedNode! +type TypedNode interface { + // schema.TypedNode acts just like a regular Node for almost all purposes; + // which ipld.ReprKind it acts as is determined by the TypeKind. + // (Note that the representation strategy of the type does *not* affect + // the ReprKind of schema.TypedNode -- 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"). + ipld.Node + + // Type returns a reference to the reified schema.Type value. + Type() Type + + // 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 +} diff --git a/schema/validate.go b/schema/validate.go index 32f51db8cfdf45ee1882a6bf906ddc0872320dce..c9465261dcf794104866d3a15ecf74428413cf72 100644 --- a/schema/validate.go +++ b/schema/validate.go @@ -26,7 +26,7 @@ package schema --- We may also need to consider distinct reification paths: we may want one - that returns a new node tree which is eagerly converted to typed.Node + that returns a new node tree which is eagerly converted to schema.TypedNode recursively; and another that returns a lazyNode which wraps things with their typed node constraints only as they're requested. (Note that the latter would have interesting implications for any code @@ -37,8 +37,8 @@ package schema A further fun issue which needs consideration: well, I'll just save a snip of prospective docs I wrote while trying to iterate on these functions: - // Note that using Validate on a node that's already a typed.Node is likely - // to be nonsensical. In many schemas, the typed.Node tree is actually a + // Note that using Validate on a node that's already a schema.TypedNode is likely + // to be nonsensical. In many schemas, the schema.TypedNode tree is actually a // different depth than its representational tree (e.g. unions can cause this), ... and that's ... that's a fairly sizable issue that needs resolving. @@ -62,7 +62,7 @@ package schema --- And finally: both "Validate" and "Reify" methods might actually belong - in the typed.Node package -- if they make *any* reference to `typed.Node`, + in the schema.TypedNode package -- if they make *any* reference to `schema.TypedNode`, then they have no choice (otherwise, cyclic imports would occur). If we make a "Validate" that works purely on the schema.Type info, and returns *only* errors: only then we can have it in the schema package.