any.go 5.76 KB
Newer Older
1
package basicnode
2

Eric Myhre's avatar
Eric Myhre committed
3
import (
tavit ohanian's avatar
tavit ohanian committed
4
	ld "gitlab.dms3.io/ld/go-ld-prime"
Eric Myhre's avatar
Eric Myhre committed
5 6 7
)

var (
tavit ohanian's avatar
tavit ohanian committed
8 9 10 11
	//_ ld.Node          = &anyNode{}
	_ ld.NodePrototype = Prototype__Any{}
	_ ld.NodeBuilder   = &anyBuilder{}
	//_ ld.NodeAssembler = &anyAssembler{}
Eric Myhre's avatar
Eric Myhre committed
12 13
)

Daniel Martí's avatar
Daniel Martí committed
14 15 16 17 18 19 20 21 22 23
// Note that we don't use a "var _" declaration to assert that Chooser
// implements traversal.LinkTargetNodePrototypeChooser, to keep basicnode's
// dependencies fairly light.

// Chooser implements traversal.LinkTargetNodePrototypeChooser.
//
// It can be used directly when loading links into the "any" prototype,
// or with another chooser layer on top, such as:
//
//    prototypeChooser := dagpb.AddSupportToChooser(basicnode.Chooser)
tavit ohanian's avatar
tavit ohanian committed
24
func Chooser(_ ld.Link, _ ld.LinkContext) (ld.NodePrototype, error) {
Daniel Martí's avatar
Daniel Martí committed
25 26 27
	return Prototype__Any{}, nil
}

Eric Myhre's avatar
Eric Myhre committed
28 29 30 31 32
// anyNode is a union meant for alloc amortization; see anyAssembler.
// Note that anyBuilder doesn't use anyNode, because it's not aiming to amortize anything.
//
// REVIEW: if there's any point in keeping this around.  It's here for completeness,
// but not currently used anywhere in package, and also not currently exported.
33
// type anyNode struct {
tavit ohanian's avatar
tavit ohanian committed
34
// 	kind ld.Kind
35 36 37 38 39 40 41 42 43 44
//
// 	plainMap
// 	plainList
// 	plainBool
// 	plainInt
// 	plainFloat
// 	plainString
// 	plainBytes
// 	plainLink
// }
Eric Myhre's avatar
Eric Myhre committed
45 46 47 48 49

// -- Node interface methods -->

// Unimplemented at present -- see "REVIEW" comment on anyNode.

50
// -- NodePrototype -->
Eric Myhre's avatar
Eric Myhre committed
51

52
type Prototype__Any struct{}
Eric Myhre's avatar
Eric Myhre committed
53

tavit ohanian's avatar
tavit ohanian committed
54
func (Prototype__Any) NewBuilder() ld.NodeBuilder {
Eric Myhre's avatar
Eric Myhre committed
55
	return &anyBuilder{}
56 57
}

Eric Myhre's avatar
Eric Myhre committed
58 59 60 61 62 63 64 65 66 67 68 69 70
// -- NodeBuilder -->

// anyBuilder is a builder for any kind of node.
//
// anyBuilder is a little unusual in its internal workings:
// unlike most builders, it doesn't embed the corresponding assembler,
// nor will it end up using anyNode,
// but instead embeds a builder for each of the kinds it might contain.
// This is because we want a more granular return at the end:
// if we used anyNode, and returned a pointer to just the relevant part of it,
// we'd have all the extra bytes of anyNode still reachable in GC terms
// for as long as that handle to the interior of it remains live.
type anyBuilder struct {
71 72
	// kind is set on first interaction, and used to select which builder to delegate 'Build' to!
	// As soon as it's been set to a value other than zero (being "Invalid"), all other Assign/Begin calls will fail since something is already in progress.
73
	// May also be set to the magic value '99', which means "i dunno, I'm just carrying another node of unknown prototype".
tavit ohanian's avatar
tavit ohanian committed
74
	kind ld.Kind
Eric Myhre's avatar
Eric Myhre committed
75 76 77 78 79

	// Only one of the following ends up being used...
	//  but we don't know in advance which one, so all are embeded here.
	//   This uses excessive space, but amortizes allocations, and all will be
	//    freed as soon as the builder is done.
80 81
	// Builders are only used for recursives;
	//  scalars are simple enough we just do them directly.
82
	// 'scalarNode' may also hold another Node of unknown prototype (possibly not even from this package),
83
	//  in which case this is indicated by 'kind==99'.
Eric Myhre's avatar
Eric Myhre committed
84

85 86
	mapBuilder  plainMap__Builder
	listBuilder plainList__Builder
tavit ohanian's avatar
tavit ohanian committed
87
	scalarNode  ld.Node
Eric Myhre's avatar
Eric Myhre committed
88 89 90 91 92 93
}

func (nb *anyBuilder) Reset() {
	*nb = anyBuilder{}
}

tavit ohanian's avatar
tavit ohanian committed
94 95
func (nb *anyBuilder) BeginMap(sizeHint int64) (ld.MapAssembler, error) {
	if nb.kind != ld.Kind_Invalid {
Eric Myhre's avatar
Eric Myhre committed
96 97
		panic("misuse")
	}
tavit ohanian's avatar
tavit ohanian committed
98
	nb.kind = ld.Kind_Map
99
	nb.mapBuilder.w = &plainMap{}
Eric Myhre's avatar
Eric Myhre committed
100 101
	return nb.mapBuilder.BeginMap(sizeHint)
}
tavit ohanian's avatar
tavit ohanian committed
102 103
func (nb *anyBuilder) BeginList(sizeHint int64) (ld.ListAssembler, error) {
	if nb.kind != ld.Kind_Invalid {
104 105
		panic("misuse")
	}
tavit ohanian's avatar
tavit ohanian committed
106
	nb.kind = ld.Kind_List
107 108
	nb.listBuilder.w = &plainList{}
	return nb.listBuilder.BeginList(sizeHint)
Eric Myhre's avatar
Eric Myhre committed
109 110
}
func (nb *anyBuilder) AssignNull() error {
tavit ohanian's avatar
tavit ohanian committed
111
	if nb.kind != ld.Kind_Invalid {
Eric Myhre's avatar
Eric Myhre committed
112 113
		panic("misuse")
	}
tavit ohanian's avatar
tavit ohanian committed
114
	nb.kind = ld.Kind_Null
Eric Myhre's avatar
Eric Myhre committed
115 116 117
	return nil
}
func (nb *anyBuilder) AssignBool(v bool) error {
tavit ohanian's avatar
tavit ohanian committed
118
	if nb.kind != ld.Kind_Invalid {
119 120
		panic("misuse")
	}
tavit ohanian's avatar
tavit ohanian committed
121
	nb.kind = ld.Kind_Bool
122
	nb.scalarNode = NewBool(v)
123
	return nil
Eric Myhre's avatar
Eric Myhre committed
124
}
125
func (nb *anyBuilder) AssignInt(v int64) error {
tavit ohanian's avatar
tavit ohanian committed
126
	if nb.kind != ld.Kind_Invalid {
Eric Myhre's avatar
Eric Myhre committed
127 128
		panic("misuse")
	}
tavit ohanian's avatar
tavit ohanian committed
129
	nb.kind = ld.Kind_Int
130
	nb.scalarNode = NewInt(v)
131
	return nil
Eric Myhre's avatar
Eric Myhre committed
132 133
}
func (nb *anyBuilder) AssignFloat(v float64) error {
tavit ohanian's avatar
tavit ohanian committed
134
	if nb.kind != ld.Kind_Invalid {
135 136
		panic("misuse")
	}
tavit ohanian's avatar
tavit ohanian committed
137
	nb.kind = ld.Kind_Float
138
	nb.scalarNode = NewFloat(v)
139
	return nil
Eric Myhre's avatar
Eric Myhre committed
140 141
}
func (nb *anyBuilder) AssignString(v string) error {
tavit ohanian's avatar
tavit ohanian committed
142
	if nb.kind != ld.Kind_Invalid {
Eric Myhre's avatar
Eric Myhre committed
143 144
		panic("misuse")
	}
tavit ohanian's avatar
tavit ohanian committed
145
	nb.kind = ld.Kind_String
146
	nb.scalarNode = NewString(v)
147
	return nil
Eric Myhre's avatar
Eric Myhre committed
148 149
}
func (nb *anyBuilder) AssignBytes(v []byte) error {
tavit ohanian's avatar
tavit ohanian committed
150
	if nb.kind != ld.Kind_Invalid {
151 152
		panic("misuse")
	}
tavit ohanian's avatar
tavit ohanian committed
153
	nb.kind = ld.Kind_Bytes
154
	nb.scalarNode = NewBytes(v)
155
	return nil
Eric Myhre's avatar
Eric Myhre committed
156
}
tavit ohanian's avatar
tavit ohanian committed
157 158
func (nb *anyBuilder) AssignLink(v ld.Link) error {
	if nb.kind != ld.Kind_Invalid {
159 160
		panic("misuse")
	}
tavit ohanian's avatar
tavit ohanian committed
161
	nb.kind = ld.Kind_Link
162
	nb.scalarNode = NewLink(v)
163
	return nil
164
}
tavit ohanian's avatar
tavit ohanian committed
165 166
func (nb *anyBuilder) AssignNode(v ld.Node) error {
	if nb.kind != ld.Kind_Invalid {
167 168 169 170 171
		panic("misuse")
	}
	nb.kind = 99
	nb.scalarNode = v
	return nil
Eric Myhre's avatar
Eric Myhre committed
172
}
tavit ohanian's avatar
tavit ohanian committed
173
func (anyBuilder) Prototype() ld.NodePrototype {
174
	return Prototype__Any{}
Eric Myhre's avatar
Eric Myhre committed
175 176
}

tavit ohanian's avatar
tavit ohanian committed
177
func (nb *anyBuilder) Build() ld.Node {
Eric Myhre's avatar
Eric Myhre committed
178
	switch nb.kind {
tavit ohanian's avatar
tavit ohanian committed
179
	case ld.Kind_Invalid:
Eric Myhre's avatar
Eric Myhre committed
180
		panic("misuse")
tavit ohanian's avatar
tavit ohanian committed
181
	case ld.Kind_Map:
Eric Myhre's avatar
Eric Myhre committed
182
		return nb.mapBuilder.Build()
tavit ohanian's avatar
tavit ohanian committed
183
	case ld.Kind_List:
184
		return nb.listBuilder.Build()
tavit ohanian's avatar
tavit ohanian committed
185 186 187
	case ld.Kind_Null:
		return ld.Null
	case ld.Kind_Bool:
188
		return nb.scalarNode
tavit ohanian's avatar
tavit ohanian committed
189
	case ld.Kind_Int:
190
		return nb.scalarNode
tavit ohanian's avatar
tavit ohanian committed
191
	case ld.Kind_Float:
192
		return nb.scalarNode
tavit ohanian's avatar
tavit ohanian committed
193
	case ld.Kind_String:
194
		return nb.scalarNode
tavit ohanian's avatar
tavit ohanian committed
195
	case ld.Kind_Bytes:
196
		return nb.scalarNode
tavit ohanian's avatar
tavit ohanian committed
197
	case ld.Kind_Link:
198 199 200
		return nb.scalarNode
	case 99:
		return nb.scalarNode
Eric Myhre's avatar
Eric Myhre committed
201 202 203 204 205 206 207 208 209 210 211
	default:
		panic("unreachable")
	}
}

// -- NodeAssembler -->

// ... oddly enough, we seem to be able to put off implementing this
//  until we also implement something that goes full-hog on amortization
//   and actually has a slab of `anyNode`.  Which so far, nothing does.
//    See "REVIEW" comment on anyNode.
212 213 214
// type anyAssembler struct {
// 	w *anyNode
// }