Commit 6ead630a authored by Eric Myhre's avatar Eric Myhre

Work out essense of anyNode.

When I started typing this, I thought I was going to need it -- or at
least *want* it -- in the recursive bits of map value assemblers.
By the end, it turns out... no, actually, I don't.  Map value assembler
does better just embedding the (very sparse) amount of relevant logic
without abstraction in this case; and it also *couldn't* embed the
anyBuilder regardless, because the anyBuilder embeds the map assembler
which embeds it's value assembler..... Fhwooo.

As you can see in some of the comments, I was also surprised to find
that it currently shakes out that there's no demand at all for an
'anyNode' type.  There could be! -- if we had maps and lists use that
rather space-costly mechanism in exchange for fewer value allocs -- but
at present, we don't.

But even if that supposed dependency path turned out wrong, of course
we still need an 'anyBuilder' regardless -- deserialization often
starts here! -- so, here it is.

More things need to be filled in yet -- for the other scalars I haven't
bothered to stamp out in this package yet, namely -- but these will be
cookie cutter and shan't be interesting.
parent 10737830
package impls package impls
type node struct { import (
ipld "github.com/ipld/go-ipld-prime/_rsrch/nodesolution"
)
var (
//_ ipld.Node = &anyNode{}
_ ipld.NodeStyle = Style__Any{}
_ ipld.NodeBuilder = &anyBuilder{}
//_ ipld.NodeAssembler = &anyAssembler{}
)
// 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.
type anyNode struct {
plainMap
plainString
plainInt
// TODO: more of these embeds for the remaining kinds.
}
// -- Node interface methods -->
// Unimplemented at present -- see "REVIEW" comment on anyNode.
// -- NodeStyle -->
type Style__Any struct{}
func (Style__Any) NewBuilder() ipld.NodeBuilder {
return &anyBuilder{}
} }
// -- 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 {
kind ipld.ReprKind // used to select which builder to delegate 'Done' to, and which embedded builder to return 'w' from!
// 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.
mapBuilder plainMap__Builder
stringBuilder plainString__Builder
intBuilder plainInt__Builder
// TODO: more of these embeds for the remaining kinds.
}
func (nb *anyBuilder) Reset() {
*nb = anyBuilder{}
}
func (nb *anyBuilder) BeginMap(sizeHint int) (ipld.MapNodeAssembler, error) {
if nb.kind != ipld.ReprKind_Invalid {
panic("misuse")
}
nb.kind = ipld.ReprKind_Map
return nb.mapBuilder.BeginMap(sizeHint)
}
func (nb *anyBuilder) BeginList(sizeHint int) (ipld.ListNodeAssembler, error) {
panic("soon")
}
func (nb *anyBuilder) AssignNull() error {
if nb.kind != ipld.ReprKind_Invalid {
panic("misuse")
}
nb.kind = ipld.ReprKind_Null
return nil
}
func (nb *anyBuilder) AssignBool(v bool) error {
panic("soon")
}
func (nb *anyBuilder) AssignInt(v int) error {
if nb.kind != ipld.ReprKind_Invalid {
panic("misuse")
}
nb.kind = ipld.ReprKind_Int
return nb.intBuilder.AssignInt(v)
}
func (nb *anyBuilder) AssignFloat(v float64) error {
panic("soon")
}
func (nb *anyBuilder) AssignString(v string) error {
if nb.kind != ipld.ReprKind_Invalid {
panic("misuse")
}
nb.kind = ipld.ReprKind_String
return nb.stringBuilder.AssignString(v)
}
func (nb *anyBuilder) AssignBytes(v []byte) error {
panic("soon")
}
func (nb *anyBuilder) Assign(v ipld.Node) error {
// TODO what to do here? should we just... keep it, in another `Node` field?
panic("soon")
}
func (anyBuilder) Style() ipld.NodeStyle {
return Style__Any{}
}
func (nb *anyBuilder) Build() (ipld.Node, error) {
switch nb.kind {
case ipld.ReprKind_Invalid:
panic("misuse")
case ipld.ReprKind_Map:
return nb.mapBuilder.Build()
case ipld.ReprKind_List:
panic("soon")
case ipld.ReprKind_Null:
//return ipld.Null
panic("soon")
case ipld.ReprKind_Bool:
panic("soon")
case ipld.ReprKind_Int:
return nb.intBuilder.Build()
case ipld.ReprKind_Float:
panic("soon")
case ipld.ReprKind_String:
return nb.stringBuilder.Build()
case ipld.ReprKind_Bytes:
panic("soon")
case ipld.ReprKind_Link:
panic("soon")
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.
type anyAssembler struct { type anyAssembler struct {
w *node w *anyNode
}
// -- Additional typedefs for maintaining 'any' style property -->
type anyInhabitedByString plainString
func (anyInhabitedByString) Style() ipld.NodeStyle {
return Style__Any{}
} }
type anyInhabitedByInt plainInt
func (anyInhabitedByInt) Style() ipld.NodeStyle {
return Style__Any{}
}
// TODO: more of these typedefs for the remaining kinds.
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