github.com/ipld/go-ipld-prime@v0.21.0/schema/gen/go/genMapReprMap.go (about) 1 package gengo 2 3 import ( 4 "io" 5 6 "github.com/ipld/go-ipld-prime/schema" 7 "github.com/ipld/go-ipld-prime/schema/gen/go/mixins" 8 ) 9 10 var _ TypeGenerator = &mapReprMapGenerator{} 11 12 func NewMapReprMapGenerator(pkgName string, typ *schema.TypeMap, adjCfg *AdjunctCfg) TypeGenerator { 13 return mapReprMapGenerator{ 14 mapGenerator{ 15 adjCfg, 16 mixins.MapTraits{ 17 PkgName: pkgName, 18 TypeName: string(typ.Name()), 19 TypeSymbol: adjCfg.TypeSymbol(typ), 20 }, 21 pkgName, 22 typ, 23 }, 24 } 25 } 26 27 type mapReprMapGenerator struct { 28 mapGenerator 29 } 30 31 func (g mapReprMapGenerator) GetRepresentationNodeGen() NodeGenerator { 32 return mapReprMapReprGenerator{ 33 g.AdjCfg, 34 mixins.MapTraits{ 35 PkgName: g.PkgName, 36 TypeName: string(g.Type.Name()) + ".Repr", 37 TypeSymbol: "_" + g.AdjCfg.TypeSymbol(g.Type) + "__Repr", 38 }, 39 g.PkgName, 40 g.Type, 41 } 42 } 43 44 type mapReprMapReprGenerator struct { 45 AdjCfg *AdjunctCfg 46 mixins.MapTraits 47 PkgName string 48 Type *schema.TypeMap 49 } 50 51 func (mapReprMapReprGenerator) IsRepr() bool { return true } // hint used in some generalized templates. 52 53 func (g mapReprMapReprGenerator) EmitNodeType(w io.Writer) { 54 // Even though this is a "natural" representation... we need a new type here, 55 // because maps are recursive, and so all our functions that access 56 // children need to remember to return the representation node of those child values. 57 // It's still structurally the same, though (and we'll be able to cast in the methodset pattern). 58 // Error-thunking methods also have a different string in their error, so those are unique even if they don't seem particularly interesting. 59 doTemplate(` 60 type _{{ .Type | TypeSymbol }}__Repr _{{ .Type | TypeSymbol }} 61 `, w, g.AdjCfg, g) 62 } 63 func (g mapReprMapReprGenerator) EmitNodeTypeAssertions(w io.Writer) { 64 doTemplate(` 65 var _ datamodel.Node = &_{{ .Type | TypeSymbol }}__Repr{} 66 `, w, g.AdjCfg, g) 67 } 68 69 func (g mapReprMapReprGenerator) EmitNodeMethodLookupByString(w io.Writer) { 70 doTemplate(` 71 func (nr *_{{ .Type | TypeSymbol }}__Repr) LookupByString(k string) (datamodel.Node, error) { 72 v, err := ({{ .Type | TypeSymbol }})(nr).LookupByString(k) 73 if err != nil || v == datamodel.Null { 74 return v, err 75 } 76 return v.({{ .Type.ValueType | TypeSymbol}}).Representation(), nil 77 } 78 `, w, g.AdjCfg, g) 79 } 80 func (g mapReprMapReprGenerator) EmitNodeMethodLookupByNode(w io.Writer) { 81 // Null is also already a branch in the method we're calling; hopefully the compiler inlines and sees this and DTRT. 82 // REVIEW: these unchecked casts are definitely safe at compile time, but I'm not sure if the compiler considers that provable, 83 // so we should investigate if there's any runtime checks injected here that waste time. If so: write this with more gsloc to avoid :( 84 doTemplate(` 85 func (nr *_{{ .Type | TypeSymbol }}__Repr) LookupByNode(k datamodel.Node) (datamodel.Node, error) { 86 v, err := ({{ .Type | TypeSymbol }})(nr).LookupByNode(k) 87 if err != nil || v == datamodel.Null { 88 return v, err 89 } 90 return v.({{ .Type.ValueType | TypeSymbol}}).Representation(), nil 91 } 92 `, w, g.AdjCfg, g) 93 } 94 func (g mapReprMapReprGenerator) EmitNodeMethodMapIterator(w io.Writer) { 95 // FUTURE: trying to get this to share the preallocated memory if we get iterators wedged into their node slab will be ... fun. 96 doTemplate(` 97 func (nr *_{{ .Type | TypeSymbol }}__Repr) MapIterator() datamodel.MapIterator { 98 return &_{{ .Type | TypeSymbol }}__ReprMapItr{({{ .Type | TypeSymbol }})(nr), 0} 99 } 100 101 type _{{ .Type | TypeSymbol }}__ReprMapItr _{{ .Type | TypeSymbol }}__MapItr 102 103 func (itr *_{{ .Type | TypeSymbol }}__ReprMapItr) Next() (k datamodel.Node, v datamodel.Node, err error) { 104 k, v, err = (*_{{ .Type | TypeSymbol }}__MapItr)(itr).Next() 105 if err != nil || v == datamodel.Null { 106 return 107 } 108 return k, v.({{ .Type.ValueType | TypeSymbol}}).Representation(), nil 109 } 110 func (itr *_{{ .Type | TypeSymbol }}__ReprMapItr) Done() bool { 111 return (*_{{ .Type | TypeSymbol }}__MapItr)(itr).Done() 112 } 113 114 `, w, g.AdjCfg, g) 115 } 116 func (g mapReprMapReprGenerator) EmitNodeMethodLength(w io.Writer) { 117 doTemplate(` 118 func (rn *_{{ .Type | TypeSymbol }}__Repr) Length() int64 { 119 return int64(len(rn.t)) 120 } 121 `, w, g.AdjCfg, g) 122 } 123 func (g mapReprMapReprGenerator) EmitNodeMethodPrototype(w io.Writer) { 124 emitNodeMethodPrototype_typical(w, g.AdjCfg, g) 125 } 126 func (g mapReprMapReprGenerator) EmitNodePrototypeType(w io.Writer) { 127 emitNodePrototypeType_typical(w, g.AdjCfg, g) 128 } 129 130 // --- NodeBuilder and NodeAssembler ---> 131 132 func (g mapReprMapReprGenerator) GetNodeBuilderGenerator() NodeBuilderGenerator { 133 return mapReprMapReprBuilderGenerator{ 134 g.AdjCfg, 135 mixins.MapAssemblerTraits{ 136 PkgName: g.PkgName, 137 TypeName: g.TypeName, 138 AppliedPrefix: "_" + g.AdjCfg.TypeSymbol(g.Type) + "__Repr", 139 }, 140 g.PkgName, 141 g.Type, 142 } 143 } 144 145 type mapReprMapReprBuilderGenerator struct { 146 AdjCfg *AdjunctCfg 147 mixins.MapAssemblerTraits 148 PkgName string 149 Type *schema.TypeMap 150 } 151 152 func (mapReprMapReprBuilderGenerator) IsRepr() bool { return true } // hint used in some generalized templates. 153 154 func (g mapReprMapReprBuilderGenerator) EmitNodeBuilderType(w io.Writer) { 155 emitEmitNodeBuilderType_typical(w, g.AdjCfg, g) 156 } 157 func (g mapReprMapReprBuilderGenerator) EmitNodeBuilderMethods(w io.Writer) { 158 emitNodeBuilderMethods_typical(w, g.AdjCfg, g) 159 } 160 func (g mapReprMapReprBuilderGenerator) EmitNodeAssemblerType(w io.Writer) { 161 // - 'w' is the "**w**ip" pointer. 162 // - 'm' is the **m**aybe which communicates our completeness to the parent if we're a child assembler. 163 // - 'state' is what it says on the tin. this is used for the map state (the broad transitions between null, start-map, and finish are handled by 'm' for consistency.) 164 // - there's no equivalent of the 'f' (**f**ocused next) field in struct assemblers -- that's implicitly the last row of the 'w.t'. 165 // 166 // - 'cm' is **c**hild **m**aybe and is used for the completion message from children. 167 // It's used for values if values aren't allowed to be nullable and thus don't have their own per-value maybe slot we can use. 168 // It's always used for key assembly, since keys are never allowed to be nullable and thus etc. 169 // - 'ka' and 'va' are the key assembler and value assembler respectively. 170 // Perhaps surprisingly, we can get away with using the assemblers for each type just straight up, no wrappers necessary; 171 // All of the required magic is handled through maybe pointers and some tidy methods used during state transitions. 172 // 173 // Note that this textually similar to the type-level assembler, but because it embeds the repr assembler for the child types, 174 // it might be *significantly* different in size and memory layout in that trailing part of the struct. 175 doTemplate(` 176 type _{{ .Type | TypeSymbol }}__ReprAssembler struct { 177 w *_{{ .Type | TypeSymbol }} 178 m *schema.Maybe 179 state maState 180 181 cm schema.Maybe 182 ka _{{ .Type.KeyType | TypeSymbol }}__ReprAssembler 183 va _{{ .Type.ValueType | TypeSymbol }}__ReprAssembler 184 } 185 186 func (na *_{{ .Type | TypeSymbol }}__ReprAssembler) reset() { 187 na.state = maState_initial 188 na.ka.reset() 189 na.va.reset() 190 } 191 `, w, g.AdjCfg, g) 192 } 193 func (g mapReprMapReprBuilderGenerator) EmitNodeAssemblerMethodBeginMap(w io.Writer) { 194 emitNodeAssemblerMethodBeginMap_mapoid(w, g.AdjCfg, g) 195 } 196 func (g mapReprMapReprBuilderGenerator) EmitNodeAssemblerMethodAssignNull(w io.Writer) { 197 emitNodeAssemblerMethodAssignNull_recursive(w, g.AdjCfg, g) 198 } 199 func (g mapReprMapReprBuilderGenerator) EmitNodeAssemblerMethodAssignNode(w io.Writer) { 200 emitNodeAssemblerMethodAssignNode_mapoid(w, g.AdjCfg, g) 201 } 202 func (g mapReprMapReprBuilderGenerator) EmitNodeAssemblerOtherBits(w io.Writer) { 203 emitNodeAssemblerHelper_mapoid_keyTidyHelper(w, g.AdjCfg, g) 204 emitNodeAssemblerHelper_mapoid_valueTidyHelper(w, g.AdjCfg, g) 205 emitNodeAssemblerHelper_mapoid_mapAssemblerMethods(w, g.AdjCfg, g) 206 }