Commit 6f760b87 authored by hannahhoward's avatar hannahhoward

feat(typed): expand to include generation, switch to node type

parent 64bf8a21
......@@ -2,23 +2,23 @@ package typed
import "github.com/ipld/go-ipld-prime"
// typed.Link is a superset of the ipld.Link interface, and has one additional behavior.
// typed.LinkNode is a superset of the typed.Node interface, and has one additional behavior.
//
// A typed.Link contains a hint for the appropriate node builder to use for loading data
// on the other side of a link, so that it can be assembled into a node representation
// and validated against the schema as quickly as possible
// 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
// into a node representation and validated against the schema as quickly as possible
//
// So, for example, if you wanted to support loading the other side of a link
// with a code-gen'd node builder while utilizing the automatic loading facilities
// of the traversal package, you could write a LinkNodeBuilderChooser as follows:
//
// func LinkNodeBuilderChooser(lnk ipld.Link, lnkCtx ipld.LinkContext) ipld.NodeBuilder {
// if tlnk, ok := lnk.(typed.Link); ok {
// return tlnk.SuggestedNodeBuilder()
// if tlnkNd, ok := lnkCtx.LinkNode.(typed.LinkNode); ok {
// return tlnkNd.SuggestedNodeBuilder()
// }
// return ipldfree.NodeBuilder()
// }
//
type Link interface {
SuggestedNodeBuilder() ipld.NodeBuilder
type LinkNode interface {
ReferencedNodeBuilder() ipld.NodeBuilder
}
......@@ -46,6 +46,14 @@ type typedNodeGenerator interface {
GetRepresentationNodeGen() nodeGenerator // includes transitively the matched nodebuilderGenerator
}
type typedLinkNodeGenerator interface {
// all methods in typedNodeGenerator
typedNodeGenerator
// as typed.LinkNode.ReferencedNodeBuilder generator
EmitTypedLinkNodeMethodReferencedLinkBuilder(io.Writer)
}
type nodeGenerator interface {
EmitNodeType(io.Writer)
EmitNodeMethodReprKind(io.Writer)
......@@ -140,6 +148,11 @@ func EmitEntireType(tg typedNodeGenerator, w io.Writer) {
tnbg.EmitNodebuilderMethodCreateBytes(w)
tnbg.EmitNodebuilderMethodCreateLink(w)
tlg, ok := tg.(typedLinkNodeGenerator)
if ok {
tlg.EmitTypedLinkNodeMethodReferencedLinkBuilder(w)
}
tg.EmitTypedNodeMethodRepresentation(w)
rng := tg.GetRepresentationNodeGen()
if rng == nil { // FIXME: hack to save me from stubbing tons right now, remove when done
......
......@@ -98,6 +98,16 @@ func (gk generateKindLink) EmitTypedNodeMethodRepresentation(w io.Writer) {
`, w, gk)
}
func (gk generateKindLink) EmitTypedLinkNodeMethodReferencedLinkBuilder(w io.Writer) {
if gk.Type.HasReferencedType() {
doTemplate(`
func ({{ .Type | mungeTypeNodeIdent }}) ReferencedNodeBuilder() ipld.NodeBuilder {
return {{ .Type.ReferencedType | mungeTypeNodebuilderIdent }}{}
}
`, w, gk)
}
}
func (gk generateKindLink) GetRepresentationNodeGen() nodeGenerator {
return nil // TODO of course
}
......@@ -24,6 +24,7 @@ func TestNuevo(t *testing.T) {
tInt := schema.SpawnInt("Int")
tBytes := schema.SpawnBytes("Bytes")
tLink := schema.SpawnLink("Link")
tIntLink := schema.SpawnLinkReference("IntLink", tInt)
tIntList := schema.SpawnList("IntList", tInt, false)
tNullableIntList := schema.SpawnList("NullableIntList", tInt, true)
......@@ -81,6 +82,10 @@ func TestNuevo(t *testing.T) {
EmitFileHeader("whee", f)
EmitEntireType(NewGeneratorForKindLink(tLink), f)
f = openOrPanic("_test/tIntLink.go")
EmitFileHeader("whee", f)
EmitEntireType(NewGeneratorForKindLink(tIntLink), f)
f = openOrPanic("_test/tIntList.go")
EmitFileHeader("whee", f)
EmitEntireType(NewGeneratorForKindList(tIntList), f)
......
......@@ -22,9 +22,12 @@ func SpawnBytes(name TypeName) TypeBytes {
}
func SpawnLink(name TypeName) TypeLink {
return TypeLink{anyType{name, nil}}
return TypeLink{anyType{name, nil}, nil, false}
}
func SpawnLinkReference(name TypeName, referenceType Type) TypeLink {
return TypeLink{anyType{name, nil}, referenceType, true}
}
func SpawnList(name TypeName, typ Type, nullable bool) TypeList {
return TypeList{anyType{name, nil}, false, typ, nullable}
}
......
......@@ -128,6 +128,8 @@ type TypeList struct {
type TypeLink struct {
anyType
referencedType Type
hasReferencedType bool
// ...?
}
......
......@@ -143,3 +143,18 @@ func (t TypeEnum) Members() []string {
}
return a
}
// Links can keep a referenced type, which is a hint only about the data on the
// other side of the link, no something that can be explicitly validated without
// loading the link
// HasReferencedType returns true if the link has a hint about the type it references
// false if it's generic
func (t TypeLink) HasReferencedType() bool {
return t.hasReferencedType
}
// ReferencedType returns the type hint for the node on the other side of the link
func (t TypeLink) ReferencedType() Type {
return t.referencedType
}
......@@ -23,8 +23,8 @@ func (tc *Config) init() {
}
if tc.LinkNodeBuilderChooser == nil {
tc.LinkNodeBuilderChooser = func(lnk ipld.Link, lnkCtx ipld.LinkContext) ipld.NodeBuilder {
if tlnk, ok := lnk.(typed.Link); ok {
return tlnk.SuggestedNodeBuilder()
if tlnkNd, ok := lnkCtx.LinkNode.(typed.LinkNode); ok {
return tlnkNd.ReferencedNodeBuilder()
}
return ipldfree.NodeBuilder()
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment