// TODO: errors in this package remain somewhat slapdash.
...
...
@@ -20,19 +22,22 @@ import (
// - it's possible that we should wrap *all* schema-level errors in a single "ipld.ErrSchemaNoMatch" error of some kind, to fix the above. as yet undecided.
// 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.
// interface when a field is requested which doesn't exist,
// or from assigning data into on a MapAssembler for a struct
// when the key doesn't match a field name in the structure
// (or, when assigning data into a ListAssembler and the list size has
// reached out of bounds, in case of a struct with list-like representations!).
typeErrNoSuchFieldstruct{
TypeType
FieldNamestring
Fieldipld.PathSegment
}
func(eErrNoSuchField)Error()string{
ife.Type==nil{
returnfmt.Sprintf("no such field: {typeinfomissing}.%s",e.FieldName)
returnfmt.Sprintf("no such field: {typeinfomissing}.%s",e.Field)
}
returnfmt.Sprintf("no such field: %s.%s",e.Type.Name(),e.FieldName)
returnfmt.Sprintf("no such field: %s.%s",e.Type.Name(),e.Field)
}
// ErrNotUnionStructure means data was fed into a union assembler that can't match the union.
// - 'm' is the **m**aybe which communicates our completeness to the parent if we're a child assembler.
// - 'state' is what it says on the tin. this is used for the list state (the broad transitions between null, start-list, and finish are handled by 'm' for consistency with other types).
// - contrasted to the map representation, there's no 's' bitfield for what's been **s**et -- because we know things must procede in order, it would be redundant with 'f'.
// - 'f' is the **f**ocused field that will be assembled next.
//
// - 'cm' is **c**hild **m**aybe and is used for the completion message from children that aren't allowed to be nullable (for those that are, their own maybe.m is used).
// - the 'ca_*' fields embed **c**hild **a**ssemblers -- these are embedded so we can yield pointers to them without causing new allocations.
//
// Note that this textually similar to the type-level assembler, but because it embeds the repr assembler for the child types,
// it might be *significantly* different in size and memory layout in that trailing part of the struct.
doTemplate(`
type _{{ .Type | TypeSymbol }}__ReprAssembler struct {
func (la *_{{ .Type | TypeSymbol }}__ReprAssembler) AssembleValue() ipld.NodeAssembler {
switch la.state {
case laState_initial:
// carry on
case laState_midValue:
if !la.valueFinishTidy() {
panic("invalid state: AssembleValue cannot be called when still in the middle of assembling the previous value")
} // if tidy success: carry on
case laState_finished:
panic("invalid state: AssembleValue cannot be called on an assembler that's already finished")
}
if la.f >= {{ len .Type.Fields }} {
return nil // schema.ErrNoSuchField{Type: nil /*TODO*/, Field: ipld.PathSegmentOfInt({{ len .Type.Fields }})} // FIXME: need an error thunking assembler! it has returned. sigh.