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  }