diff --git a/generator/generator.go b/generator/generator.go index b19794a62..f4918253a 100644 --- a/generator/generator.go +++ b/generator/generator.go @@ -93,6 +93,7 @@ var ( generateGetters = flag.Bool("generate_getters", false, "If set to true, getter methdos that retrieve or create an element are generated for YANG container (Go struct pointer) or list (Go map) fields within the generated code.") generateDelete = flag.Bool("generate_delete", false, "If set to true, delete methods are generated for YANG lists (Go maps) within the Go code.") generateLeafGetters = flag.Bool("generate_leaf_getters", false, "If set to true, getters for YANG leaves are generated within the Go code. Caution should be exercised when using leaf getters, since values that are explicitly set to the Go default/zero value are not distinguishable from those that are unset when retrieved via the GetXXX method.") + generateLeafSetters = flag.Bool("generate_leaf_setters", false, "If set to true, setters for YANG leaves are generated within the Go code.") generateSimpleUnions = flag.Bool("generate_simple_unions", false, "If set to true, then generated typedefs will be used to represent union subtypes within Go code instead of wrapper struct types.") includeModelData = flag.Bool("include_model_data", false, "If set to true, a slice of gNMI ModelData messages are included in the generated Go code containing the details of the input schemas from which the code was generated.") generatePopulateDefault = flag.Bool("generate_populate_defaults", false, "If set to true, a PopulateDefault method will be generated for all GoStructs which recursively populates default values.") @@ -362,6 +363,7 @@ func main() { GenerateDeleteMethod: *generateDelete, GenerateAppendMethod: *generateAppend, GenerateLeafGetters: *generateLeafGetters, + GenerateLeafSetters: *generateLeafSetters, GeneratePopulateDefault: *generatePopulateDefault, ValidateFunctionName: *generateValidateFnName, GenerateSimpleUnions: *generateSimpleUnions, diff --git a/gogen/codegen.go b/gogen/codegen.go index ac7d38053..2d14c61f0 100644 --- a/gogen/codegen.go +++ b/gogen/codegen.go @@ -90,6 +90,9 @@ type GoOpts struct { // whether a field has been explicitly set to the zero value (i.e., an integer // field is set to 0), or whether the field was actually unset. GenerateLeafGetters bool + // GenerateLeafSetters specifies whether Set* methods should be created for + // leaf fields of a struct. + GenerateLeafSetters bool // GeneratePopulateDefault specifies whether a PopulateDefaults method // should be generated for every GoStruct that recursively populates // default values within the subtree. diff --git a/gogen/codegen_test.go b/gogen/codegen_test.go index fef7355a9..922615559 100644 --- a/gogen/codegen_test.go +++ b/gogen/codegen_test.go @@ -64,6 +64,7 @@ func TestSimpleStructs(t *testing.T) { GoOptions: GoOpts{ GenerateSimpleUnions: true, GenerateLeafGetters: true, + GenerateLeafSetters: true, GeneratePopulateDefault: true, }, }, @@ -197,6 +198,7 @@ func TestSimpleStructs(t *testing.T) { GoOptions: GoOpts{ GenerateSimpleUnions: true, GenerateLeafGetters: true, + GenerateLeafSetters: true, GeneratePopulateDefault: true, }, }, @@ -652,6 +654,7 @@ func TestSimpleStructs(t *testing.T) { GoOptions: GoOpts{ GenerateSimpleUnions: true, GenerateLeafGetters: true, + GenerateLeafSetters: true, }, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-union.formatted-txt"), @@ -711,6 +714,7 @@ func TestSimpleStructs(t *testing.T) { }, GoOptions: GoOpts{ GenerateLeafGetters: true, + GenerateLeafSetters: true, GeneratePopulateDefault: true, AppendEnumSuffixForSimpleUnionEnums: true, }, @@ -732,6 +736,7 @@ func TestSimpleStructs(t *testing.T) { GoOptions: GoOpts{ GenerateSimpleUnions: true, GenerateLeafGetters: true, + GenerateLeafSetters: true, }, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-module.formatted-txt"), @@ -855,6 +860,26 @@ func TestSimpleStructs(t *testing.T) { }, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "openconfig-list-enum-key.leaf-getters.formatted-txt"), + }, { + name: "module with leaf setters", + inFiles: []string{filepath.Join(datapath, "", "openconfig-list-enum-key.yang")}, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + CompressBehaviour: genutil.PreferIntendedConfig, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateLeafSetters: true, + GeneratePopulateDefault: true, + GenerateSimpleUnions: true, + }, + }, + wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "openconfig-list-enum-key.leaf-setters.formatted-txt"), }, { name: "uncompressed module with two different enums", inFiles: []string{filepath.Join(datapath, "", "enum-list-uncompressed.yang")}, diff --git a/gogen/gogen.go b/gogen/gogen.go index 52ab44d92..8da9d8610 100644 --- a/gogen/gogen.go +++ b/gogen/gogen.go @@ -281,6 +281,20 @@ type generatedLeafGetter struct { Receiver string } +// generatedLeafSetter is used to represent the parameters required to generate a +// setter for a leaf within the generated Go code. +type generatedLeafSetter struct { + // Name is the name of the field. It is used as a suffix to Set to generate + // the setter. + Name string + // Type is the type of the field, required by the setter method. + Type string + // IsPtr stores whether the value is a pointer. + IsPtr bool + // Receiver is the name of the receiver for the setter method. + Receiver string +} + // generatedDefaultMethod is used to represent parameters required to generate // a PopulateDefaults method for a GoStruct that recursively populates default // values within the subtree. @@ -781,6 +795,16 @@ func (t *{{ .Receiver }}) Get{{ .Name }}() {{ .Type }} { } return {{ if .IsPtr -}} * {{- end -}} t.{{ .Name }} } +`) + + // goLeafSetterTemplate defines a template for a function that, for a + // particular leaf, generates a setter method. + goLeafSetterTemplate = mustMakeTemplate("setLeaf", ` +// Set{{ .Name }} sets the value of the leaf {{ .Name }} in the {{ .Receiver }} +// struct. +func (t *{{ .Receiver }}) Set{{ .Name }}(v {{ .Type }}) { + t.{{ .Name }} = {{ if .IsPtr -}} & {{- end -}} v +} `) // goDefaultMethodTemplate is a template for generating a PopulateDefaults method @@ -1323,6 +1347,10 @@ func writeGoStruct(targetStruct *ygen.ParsedDirectory, goStructElements map[stri // to generated for the struct. var associatedLeafGetters []*generatedLeafGetter + // associatedLeafSetters is a slice of structs which define the set of leaf setters + // to generated for the struct. + var associatedLeafSetters []*generatedLeafSetter + associatedDefaultMethod := generatedDefaultMethod{ Receiver: targetStruct.Name, } @@ -1495,6 +1523,16 @@ func writeGoStruct(targetStruct *ygen.ParsedDirectory, goStructElements map[stri Default: field.LangType.DefaultValue, }) + // If we are generating leaf setters, then append the relevant information + // to the associatedLeafSetters slice to be generated along with other + // associated methods. + associatedLeafSetters = append(associatedLeafSetters, &generatedLeafSetter{ + Name: fieldName, + Type: fType, + IsPtr: scalarField, + Receiver: targetStruct.Name, + }) + fieldDef = &goStructField{ Name: fieldName, Type: fType, @@ -1644,6 +1682,13 @@ func writeGoStruct(targetStruct *ygen.ParsedDirectory, goStructElements map[stri errs = append(errs, err) } } + + if goOpts.GenerateLeafSetters { + if err := generateLeafSetters(&methodBuf, associatedLeafSetters); err != nil { + errs = append(errs, err) + } + } + if goOpts.GeneratePopulateDefault { associatedDefaultMethod.Leaves = associatedLeafGetters if err := goDefaultMethodTemplate.Execute(&methodBuf, associatedDefaultMethod); err != nil { @@ -1834,6 +1879,18 @@ func generateLeafGetters(buf *bytes.Buffer, leaves []*generatedLeafGetter) error return errs.Err() } +// generateLeafSetters generates SetXXX methods for the leaf fields described by +// the supplied slice of generatedLeafSetter structs. +func generateLeafSetters(buf *bytes.Buffer, leaves []*generatedLeafSetter) error { + var errs errlist.List + for _, l := range leaves { + if err := goLeafSetterTemplate.Execute(buf, l); err != nil { + errs.Add(err) + } + } + return errs.Err() +} + // generateGetOrCreateList generates a getter function similar to that created // by the generateGetOrCreateStruct function for maps within the generated Go // code (which represent YANG lists). It handles both simple and composite key diff --git a/gogen/gogen_test.go b/gogen/gogen_test.go index 3021ec8a3..af635e875 100644 --- a/gogen/gogen_test.go +++ b/gogen/gogen_test.go @@ -1843,6 +1843,156 @@ func (t *Container) ΛEnumTypeMap() map[string][]reflect.Type { return ΛEnumTyp func (*Container) ΛBelongingModule() string { return "m1" } +`, + }, + }, { + name: "container with leaf setters", + inStructToMap: &ygen.ParsedDirectory{ + Name: "Container", + Fields: map[string]*ygen.NodeDetails{ + "leafStr": { + Name: "LeafStr", + YANGDetails: ygen.YANGNodeDetails{ + Name: "leafStr", + Defaults: nil, + RootElementModule: "m1", + Path: "/m1/foo/bar/leafStr", + LeafrefTargetPath: "", + }, + Type: ygen.LeafNode, + LangType: &ygen.MappedType{ + NativeType: "string", + UnionTypes: nil, + IsEnumeratedValue: false, + ZeroValue: `""`, + DefaultValue: nil, + }, + MappedPaths: [][]string{{"bar", "leafStr"}}, + MappedPathModules: [][]string{{"m1", "m1"}}, + ShadowMappedPaths: nil, + ShadowMappedPathModules: nil, + }, + "leafUnion": { + Name: "LeafUnion", + YANGDetails: ygen.YANGNodeDetails{ + Name: "leafUnion", + Defaults: nil, + RootElementModule: "m1", + Path: "/m1/foo/bar/leafUnion", + LeafrefTargetPath: "", + }, + Type: ygen.LeafNode, + LangType: &ygen.MappedType{ + NativeType: "Container_U1_Union", + UnionTypes: map[string]ygen.MappedUnionSubtype{ + "string": { + Index: 0, + }, + "int8": { + Index: 1, + }, + }, + IsEnumeratedValue: false, + ZeroValue: "nil", + DefaultValue: nil, + }, + MappedPaths: [][]string{{"bar", "leafUnion"}}, + MappedPathModules: [][]string{{"m1", "m1"}}, + ShadowMappedPaths: nil, + ShadowMappedPathModules: nil, + }, + }, + Path: "/m1/foo", + BelongingModule: "m1", + }, + inGoOpts: GoOpts{ + GenerateJSONSchema: true, + GenerateLeafSetters: true, + }, + want: wantGoStructOut{ + structs: ` +// Container represents the /m1/foo YANG schema element. +type Container struct { + LeafStr *string ` + "`" + `path:"bar/leafStr" module:"m1/m1"` + "`" + ` + LeafUnion Container_U1_Union ` + "`" + `path:"bar/leafUnion" module:"m1/m1"` + "`" + ` +} + +// IsYANGGoStruct ensures that Container implements the yang.GoStruct +// interface. This allows functions that need to handle this struct to +// identify it as being generated by ygen. +func (*Container) IsYANGGoStruct() {} +`, + methods: ` +// SetLeafStr sets the value of the leaf LeafStr in the Container +// struct. +func (t *Container) SetLeafStr(v string) { + t.LeafStr = &v +} + +// SetLeafUnion sets the value of the leaf LeafUnion in the Container +// struct. +func (t *Container) SetLeafUnion(v Container_U1_Union) { + t.LeafUnion = v +} + +// Validate validates s against the YANG schema corresponding to its type. +func (t *Container) ΛValidate(opts ...ygot.ValidationOption) error { + if err := ytypes.Validate(SchemaTree["Container"], t, opts...); err != nil { + return err + } + return nil +} + +// ΛEnumTypeMap returns a map, keyed by YANG schema path, of the enumerated types +// that are included in the generated code. +func (t *Container) ΛEnumTypeMap() map[string][]reflect.Type { return ΛEnumTypes } + +// ΛBelongingModule returns the name of the module that defines the namespace +// of Container. +func (*Container) ΛBelongingModule() string { + return "m1" +} +`, + interfaces: ` +// Container_U1_Union is an interface that is implemented by valid types for the union +// for the leaf /m1/foo/bar/leafUnion within the YANG schema. +type Container_U1_Union interface { + Is_Container_U1_Union() +} + +// Container_U1_Union_Int8 is used when /m1/foo/bar/leafUnion +// is to be set to a int8 value. +type Container_U1_Union_Int8 struct { + Int8 int8 +} + +// Is_Container_U1_Union ensures that Container_U1_Union_Int8 +// implements the Container_U1_Union interface. +func (*Container_U1_Union_Int8) Is_Container_U1_Union() {} + +// Container_U1_Union_String is used when /m1/foo/bar/leafUnion +// is to be set to a string value. +type Container_U1_Union_String struct { + String string +} + +// Is_Container_U1_Union ensures that Container_U1_Union_String +// implements the Container_U1_Union interface. +func (*Container_U1_Union_String) Is_Container_U1_Union() {} + +// To_Container_U1_Union takes an input interface{} and attempts to convert it to a struct +// which implements the Container_U1_Union union. It returns an error if the interface{} supplied +// cannot be converted to a type within the union. +func (t *Container) To_Container_U1_Union(i interface{}) (Container_U1_Union, error) { + switch v := i.(type) { + case int8: + return &Container_U1_Union_Int8{v}, nil + case string: + return &Container_U1_Union_String{v}, nil + default: + return nil, fmt.Errorf("cannot convert %v to Container_U1_Union, unknown union type, got: %T, want any of [int8, string]", i, i) + } +} `, }, }} diff --git a/gogen/testdata/structs/enum-module.formatted-txt b/gogen/testdata/structs/enum-module.formatted-txt index bef718731..bc6380180 100644 --- a/gogen/testdata/structs/enum-module.formatted-txt +++ b/gogen/testdata/structs/enum-module.formatted-txt @@ -96,6 +96,12 @@ func (t *AList) GetValue() AList_Value_Union { return t.Value } +// SetValue sets the value of the leaf Value in the AList +// struct. +func (t *AList) SetValue(v AList_Value_Union) { + t.Value = v +} + // ΛListKeyMap returns the keys of the AList struct, which is a YANG list entry. func (t *AList) ΛListKeyMap() (map[string]interface{}, error) { @@ -166,6 +172,12 @@ func (t *BList) GetValue() BList_Value_Union { return t.Value } +// SetValue sets the value of the leaf Value in the BList +// struct. +func (t *BList) SetValue(v BList_Value_Union) { + t.Value = v +} + // ΛListKeyMap returns the keys of the BList struct, which is a YANG list entry. func (t *BList) ΛListKeyMap() (map[string]interface{}, error) { @@ -236,6 +248,12 @@ func (t *C) GetCl() E_EnumModule_Cl { return t.Cl } +// SetCl sets the value of the leaf Cl in the C +// struct. +func (t *C) SetCl(v E_EnumModule_Cl) { + t.Cl = v +} + // ΛBelongingModule returns the name of the module that defines the namespace // of C. func (*C) ΛBelongingModule() string { @@ -335,6 +353,30 @@ func (t *Parent_Child) GetInlineEnum() E_Child_InlineEnum { return t.InlineEnum } +// SetEnum sets the value of the leaf Enum in the Parent_Child +// struct. +func (t *Parent_Child) SetEnum(v E_EnumTypes_TdEnum) { + t.Enum = v +} + +// SetId sets the value of the leaf Id in the Parent_Child +// struct. +func (t *Parent_Child) SetId(v E_EnumTypes_ID) { + t.Id = v +} + +// SetId2 sets the value of the leaf Id2 in the Parent_Child +// struct. +func (t *Parent_Child) SetId2(v E_EnumTypes_ID) { + t.Id2 = v +} + +// SetInlineEnum sets the value of the leaf InlineEnum in the Parent_Child +// struct. +func (t *Parent_Child) SetInlineEnum(v E_Child_InlineEnum) { + t.InlineEnum = v +} + // ΛBelongingModule returns the name of the module that defines the namespace // of Parent_Child. func (*Parent_Child) ΛBelongingModule() string { diff --git a/gogen/testdata/structs/enum-union.formatted-txt b/gogen/testdata/structs/enum-union.formatted-txt index 0b671b6a7..94ed16e3a 100644 --- a/gogen/testdata/structs/enum-union.formatted-txt +++ b/gogen/testdata/structs/enum-union.formatted-txt @@ -163,6 +163,30 @@ func (t *Outer_Inner) GetLeaf4() Outer_Inner_Leaf4_Union { return t.Leaf4 } +// SetLeaf1 sets the value of the leaf Leaf1 in the Outer_Inner +// struct. +func (t *Outer_Inner) SetLeaf1(v Outer_Inner_Leaf1_Union) { + t.Leaf1 = v +} + +// SetLeaf2 sets the value of the leaf Leaf2 in the Outer_Inner +// struct. +func (t *Outer_Inner) SetLeaf2(v Outer_Inner_Leaf2_Union) { + t.Leaf2 = v +} + +// SetLeaf3 sets the value of the leaf Leaf3 in the Outer_Inner +// struct. +func (t *Outer_Inner) SetLeaf3(v Outer_Inner_Leaf3_Union) { + t.Leaf3 = v +} + +// SetLeaf4 sets the value of the leaf Leaf4 in the Outer_Inner +// struct. +func (t *Outer_Inner) SetLeaf4(v Outer_Inner_Leaf4_Union) { + t.Leaf4 = v +} + // ΛBelongingModule returns the name of the module that defines the namespace // of Outer_Inner. func (*Outer_Inner) ΛBelongingModule() string { diff --git a/gogen/testdata/structs/openconfig-leaflist-default.formatted-txt b/gogen/testdata/structs/openconfig-leaflist-default.formatted-txt index 4d78744ba..8aef03ded 100644 --- a/gogen/testdata/structs/openconfig-leaflist-default.formatted-txt +++ b/gogen/testdata/structs/openconfig-leaflist-default.formatted-txt @@ -173,6 +173,30 @@ func (t *Parent_Child) GetTwo() []string { return t.Two } +// SetFour sets the value of the leaf Four in the Parent_Child +// struct. +func (t *Parent_Child) SetFour(v []Binary) { + t.Four = v +} + +// SetOne sets the value of the leaf One in the Parent_Child +// struct. +func (t *Parent_Child) SetOne(v []string) { + t.One = v +} + +// SetThree sets the value of the leaf Three in the Parent_Child +// struct. +func (t *Parent_Child) SetThree(v []E_Child_Three) { + t.Three = v +} + +// SetTwo sets the value of the leaf Two in the Parent_Child +// struct. +func (t *Parent_Child) SetTwo(v []string) { + t.Two = v +} + // PopulateDefaults recursively populates unset leaf fields in the Parent_Child // with default values as specified in the YANG schema, instantiating any nil // container fields. diff --git a/gogen/testdata/structs/openconfig-list-enum-key.leaf-setters.formatted-txt b/gogen/testdata/structs/openconfig-list-enum-key.leaf-setters.formatted-txt new file mode 100644 index 000000000..ad3241a71 --- /dev/null +++ b/gogen/testdata/structs/openconfig-list-enum-key.leaf-setters.formatted-txt @@ -0,0 +1,433 @@ +/* +Package ocstructs is a generated package which contains definitions +of structs which represent a YANG schema. The generated schema can be +compressed by a series of transformations (compression was true +in this case). + +This package was generated by codegen-tests +using the following YANG input files: + - ../testdata/modules/openconfig-list-enum-key.yang +Imported modules were sourced from: +*/ +package ocstructs + +import ( + "encoding/json" + "fmt" + "reflect" + + "github.com/openconfig/ygot/ygot" +) + +// Binary is a type that is used for fields that have a YANG type of +// binary. It is used such that binary fields can be distinguished from +// leaf-lists of uint8s (which are mapped to []uint8, equivalent to +// []byte in reflection). +type Binary []byte + +// YANGEmpty is a type that is used for fields that have a YANG type of +// empty. It is used such that empty fields can be distinguished from boolean fields +// in the generated code. +type YANGEmpty bool + +// UnionInt8 is an int8 type assignable to unions of which it is a subtype. +type UnionInt8 int8 + +// UnionInt16 is an int16 type assignable to unions of which it is a subtype. +type UnionInt16 int16 + +// UnionInt32 is an int32 type assignable to unions of which it is a subtype. +type UnionInt32 int32 + +// UnionInt64 is an int64 type assignable to unions of which it is a subtype. +type UnionInt64 int64 + +// UnionUint8 is a uint8 type assignable to unions of which it is a subtype. +type UnionUint8 uint8 + +// UnionUint16 is a uint16 type assignable to unions of which it is a subtype. +type UnionUint16 uint16 + +// UnionUint32 is a uint32 type assignable to unions of which it is a subtype. +type UnionUint32 uint32 + +// UnionUint64 is a uint64 type assignable to unions of which it is a subtype. +type UnionUint64 uint64 + +// UnionFloat64 is a float64 type assignable to unions of which it is a subtype. +type UnionFloat64 float64 + +// UnionString is a string type assignable to unions of which it is a subtype. +type UnionString string + +// UnionBool is a bool type assignable to unions of which it is a subtype. +type UnionBool bool + +// UnionUnsupported is an interface{} wrapper type for unsupported types. It is +// assignable to unions of which it is a subtype. +type UnionUnsupported struct { + Value interface{} +} + +// Device represents the /device YANG schema element. +type Device struct { + Top *Top `path:"top" module:"openconfig-list-enum-key"` +} + +// IsYANGGoStruct ensures that Device implements the yang.GoStruct +// interface. This allows functions that need to handle this struct to +// identify it as being generated by ygen. +func (*Device) IsYANGGoStruct() {} + +// PopulateDefaults recursively populates unset leaf fields in the Device +// with default values as specified in the YANG schema, instantiating any nil +// container fields. +func (t *Device) PopulateDefaults() { + if (t == nil) { + return + } + ygot.BuildEmptyTree(t) + t.Top.PopulateDefaults() +} + +// ΛBelongingModule returns the name of the module that defines the namespace +// of Device. +func (*Device) ΛBelongingModule() string { + return "" +} + +// Top represents the /openconfig-list-enum-key/top YANG schema element. +type Top struct { + Ekm map[Top_Ekm_Key]*Top_Ekm `path:"multi-key/ekm" module:"openconfig-list-enum-key/openconfig-list-enum-key"` + Eks map[E_Eks_K]*Top_Eks `path:"single-key/eks" module:"openconfig-list-enum-key/openconfig-list-enum-key"` +} + +// IsYANGGoStruct ensures that Top implements the yang.GoStruct +// interface. This allows functions that need to handle this struct to +// identify it as being generated by ygen. +func (*Top) IsYANGGoStruct() {} + +// Top_Ekm_Key represents the key for list Ekm of element /openconfig-list-enum-key/top. +type Top_Ekm_Key struct { + K1 E_Ekm_K1 `path:"k1"` + K2 E_OpenconfigListEnumKey_FooIdentity `path:"k2"` +} + +// NewEkm creates a new entry in the Ekm list of the +// Top struct. The keys of the list are populated from the input +// arguments. +func (t *Top) NewEkm(K1 E_Ekm_K1, K2 E_OpenconfigListEnumKey_FooIdentity) (*Top_Ekm, error){ + + // Initialise the list within the receiver struct if it has not already been + // created. + if t.Ekm == nil { + t.Ekm = make(map[Top_Ekm_Key]*Top_Ekm) + } + + key := Top_Ekm_Key{ + K1: K1, + K2: K2, + } + + // Ensure that this key has not already been used in the + // list. Keyed YANG lists do not allow duplicate keys to + // be created. + if _, ok := t.Ekm[key]; ok { + return nil, fmt.Errorf("duplicate key %v for list Ekm", key) + } + + t.Ekm[key] = &Top_Ekm{ + K1: K1, + K2: K2, + } + + return t.Ekm[key], nil +} + +// NewEks creates a new entry in the Eks list of the +// Top struct. The keys of the list are populated from the input +// arguments. +func (t *Top) NewEks(K E_Eks_K) (*Top_Eks, error){ + + // Initialise the list within the receiver struct if it has not already been + // created. + if t.Eks == nil { + t.Eks = make(map[E_Eks_K]*Top_Eks) + } + + key := K + + // Ensure that this key has not already been used in the + // list. Keyed YANG lists do not allow duplicate keys to + // be created. + if _, ok := t.Eks[key]; ok { + return nil, fmt.Errorf("duplicate key %v for list Eks", key) + } + + t.Eks[key] = &Top_Eks{ + K: K, + } + + return t.Eks[key], nil +} + +// PopulateDefaults recursively populates unset leaf fields in the Top +// with default values as specified in the YANG schema, instantiating any nil +// container fields. +func (t *Top) PopulateDefaults() { + if (t == nil) { + return + } + ygot.BuildEmptyTree(t) + for _, e := range t.Ekm { + e.PopulateDefaults() + } + for _, e := range t.Eks { + e.PopulateDefaults() + } +} + +// ΛBelongingModule returns the name of the module that defines the namespace +// of Top. +func (*Top) ΛBelongingModule() string { + return "openconfig-list-enum-key" +} + +// Top_Ekm represents the /openconfig-list-enum-key/top/multi-key/ekm YANG schema element. +type Top_Ekm struct { + K1 E_Ekm_K1 `path:"config/k1|k1" module:"openconfig-list-enum-key/openconfig-list-enum-key|openconfig-list-enum-key"` + K2 E_OpenconfigListEnumKey_FooIdentity `path:"config/k2|k2" module:"openconfig-list-enum-key/openconfig-list-enum-key|openconfig-list-enum-key"` + K3 Top_Ekm_K3_Union `path:"config/k3" module:"openconfig-list-enum-key/openconfig-list-enum-key"` +} + +// IsYANGGoStruct ensures that Top_Ekm implements the yang.GoStruct +// interface. This allows functions that need to handle this struct to +// identify it as being generated by ygen. +func (*Top_Ekm) IsYANGGoStruct() {} + +// SetK1 sets the value of the leaf K1 in the Top_Ekm +// struct. +func (t *Top_Ekm) SetK1(v E_Ekm_K1) { + t.K1 = v +} + +// SetK2 sets the value of the leaf K2 in the Top_Ekm +// struct. +func (t *Top_Ekm) SetK2(v E_OpenconfigListEnumKey_FooIdentity) { + t.K2 = v +} + +// SetK3 sets the value of the leaf K3 in the Top_Ekm +// struct. +func (t *Top_Ekm) SetK3(v Top_Ekm_K3_Union) { + t.K3 = v +} + +// PopulateDefaults recursively populates unset leaf fields in the Top_Ekm +// with default values as specified in the YANG schema, instantiating any nil +// container fields. +func (t *Top_Ekm) PopulateDefaults() { + if (t == nil) { + return + } + ygot.BuildEmptyTree(t) + if t.K2 == 0 { + t.K2 = OpenconfigListEnumKey_FooIdentity_BAZ + } + if t.K3 == nil { + t.K3 = OpenconfigListEnumKey_FooIdentity_BAR + } +} + +// ΛListKeyMap returns the keys of the Top_Ekm struct, which is a YANG list entry. +func (t *Top_Ekm) ΛListKeyMap() (map[string]interface{}, error) { + + + return map[string]interface{}{ + "k1": t.K1, + "k2": t.K2, + }, nil +} + +// ΛBelongingModule returns the name of the module that defines the namespace +// of Top_Ekm. +func (*Top_Ekm) ΛBelongingModule() string { + return "openconfig-list-enum-key" +} + +// Top_Ekm_K3_Union is an interface that is implemented by valid types for the union +// for the leaf /openconfig-list-enum-key/top/multi-key/ekm/config/k3 within the YANG schema. +// Union type can be one of [E_OpenconfigListEnumKey_FooIdentity, UnionInt16]. +type Top_Ekm_K3_Union interface { + // Union type can be one of [E_OpenconfigListEnumKey_FooIdentity, UnionInt16] + Documentation_for_Top_Ekm_K3_Union() +} + +// Documentation_for_Top_Ekm_K3_Union ensures that E_OpenconfigListEnumKey_FooIdentity +// implements the Top_Ekm_K3_Union interface. +func (E_OpenconfigListEnumKey_FooIdentity) Documentation_for_Top_Ekm_K3_Union() {} + +// Documentation_for_Top_Ekm_K3_Union ensures that UnionInt16 +// implements the Top_Ekm_K3_Union interface. +func (UnionInt16) Documentation_for_Top_Ekm_K3_Union() {} + +// To_Top_Ekm_K3_Union takes an input interface{} and attempts to convert it to a struct +// which implements the Top_Ekm_K3_Union union. It returns an error if the interface{} supplied +// cannot be converted to a type within the union. +func (t *Top_Ekm) To_Top_Ekm_K3_Union(i interface{}) (Top_Ekm_K3_Union, error) { + if v, ok := i.(Top_Ekm_K3_Union); ok { + return v, nil + } + switch v := i.(type) { + case int16: + return UnionInt16(v), nil + } + return nil, fmt.Errorf("cannot convert %v to Top_Ekm_K3_Union, unknown union type, got: %T, want any of [E_OpenconfigListEnumKey_FooIdentity, int16]", i, i) +} + +// Top_Eks represents the /openconfig-list-enum-key/top/single-key/eks YANG schema element. +type Top_Eks struct { + K E_Eks_K `path:"config/k|k" module:"openconfig-list-enum-key/openconfig-list-enum-key|openconfig-list-enum-key"` +} + +// IsYANGGoStruct ensures that Top_Eks implements the yang.GoStruct +// interface. This allows functions that need to handle this struct to +// identify it as being generated by ygen. +func (*Top_Eks) IsYANGGoStruct() {} + +// SetK sets the value of the leaf K in the Top_Eks +// struct. +func (t *Top_Eks) SetK(v E_Eks_K) { + t.K = v +} + +// PopulateDefaults recursively populates unset leaf fields in the Top_Eks +// with default values as specified in the YANG schema, instantiating any nil +// container fields. +func (t *Top_Eks) PopulateDefaults() { + if (t == nil) { + return + } + ygot.BuildEmptyTree(t) +} + +// ΛListKeyMap returns the keys of the Top_Eks struct, which is a YANG list entry. +func (t *Top_Eks) ΛListKeyMap() (map[string]interface{}, error) { + + return map[string]interface{}{ + "k": t.K, + }, nil +} + +// ΛBelongingModule returns the name of the module that defines the namespace +// of Top_Eks. +func (*Top_Eks) ΛBelongingModule() string { + return "openconfig-list-enum-key" +} + +// E_Ekm_K1 is a derived int64 type which is used to represent +// the enumerated node Ekm_K1. An additional value named +// Ekm_K1_UNSET is added to the enumeration which is used as +// the nil value, indicating that the enumeration was not explicitly set by +// the program importing the generated structures. +type E_Ekm_K1 int64 + +// IsYANGGoEnum ensures that Ekm_K1 implements the yang.GoEnum +// interface. This ensures that Ekm_K1 can be identified as a +// mapped type for a YANG enumeration. +func (E_Ekm_K1) IsYANGGoEnum() {} + +// ΛMap returns the value lookup map associated with Ekm_K1. +func (E_Ekm_K1) ΛMap() map[string]map[int64]ygot.EnumDefinition { return ΛEnum; } + +// String returns a logging-friendly string for E_Ekm_K1. +func (e E_Ekm_K1) String() string { + return ygot.EnumLogString(e, int64(e), "E_Ekm_K1") +} + +const ( + // Ekm_K1_UNSET corresponds to the value UNSET of Ekm_K1 + Ekm_K1_UNSET E_Ekm_K1 = 0 + // Ekm_K1_A corresponds to the value A of Ekm_K1 + Ekm_K1_A E_Ekm_K1 = 1 + // Ekm_K1_B corresponds to the value B of Ekm_K1 + Ekm_K1_B E_Ekm_K1 = 2 +) + +// E_Eks_K is a derived int64 type which is used to represent +// the enumerated node Eks_K. An additional value named +// Eks_K_UNSET is added to the enumeration which is used as +// the nil value, indicating that the enumeration was not explicitly set by +// the program importing the generated structures. +type E_Eks_K int64 + +// IsYANGGoEnum ensures that Eks_K implements the yang.GoEnum +// interface. This ensures that Eks_K can be identified as a +// mapped type for a YANG enumeration. +func (E_Eks_K) IsYANGGoEnum() {} + +// ΛMap returns the value lookup map associated with Eks_K. +func (E_Eks_K) ΛMap() map[string]map[int64]ygot.EnumDefinition { return ΛEnum; } + +// String returns a logging-friendly string for E_Eks_K. +func (e E_Eks_K) String() string { + return ygot.EnumLogString(e, int64(e), "E_Eks_K") +} + +const ( + // Eks_K_UNSET corresponds to the value UNSET of Eks_K + Eks_K_UNSET E_Eks_K = 0 + // Eks_K_A corresponds to the value A of Eks_K + Eks_K_A E_Eks_K = 1 + // Eks_K_B corresponds to the value B of Eks_K + Eks_K_B E_Eks_K = 2 +) + +// E_OpenconfigListEnumKey_FooIdentity is a derived int64 type which is used to represent +// the enumerated node OpenconfigListEnumKey_FooIdentity. An additional value named +// OpenconfigListEnumKey_FooIdentity_UNSET is added to the enumeration which is used as +// the nil value, indicating that the enumeration was not explicitly set by +// the program importing the generated structures. +type E_OpenconfigListEnumKey_FooIdentity int64 + +// IsYANGGoEnum ensures that OpenconfigListEnumKey_FooIdentity implements the yang.GoEnum +// interface. This ensures that OpenconfigListEnumKey_FooIdentity can be identified as a +// mapped type for a YANG enumeration. +func (E_OpenconfigListEnumKey_FooIdentity) IsYANGGoEnum() {} + +// ΛMap returns the value lookup map associated with OpenconfigListEnumKey_FooIdentity. +func (E_OpenconfigListEnumKey_FooIdentity) ΛMap() map[string]map[int64]ygot.EnumDefinition { return ΛEnum; } + +// String returns a logging-friendly string for E_OpenconfigListEnumKey_FooIdentity. +func (e E_OpenconfigListEnumKey_FooIdentity) String() string { + return ygot.EnumLogString(e, int64(e), "E_OpenconfigListEnumKey_FooIdentity") +} + +const ( + // OpenconfigListEnumKey_FooIdentity_UNSET corresponds to the value UNSET of OpenconfigListEnumKey_FooIdentity + OpenconfigListEnumKey_FooIdentity_UNSET E_OpenconfigListEnumKey_FooIdentity = 0 + // OpenconfigListEnumKey_FooIdentity_BAR corresponds to the value BAR of OpenconfigListEnumKey_FooIdentity + OpenconfigListEnumKey_FooIdentity_BAR E_OpenconfigListEnumKey_FooIdentity = 1 + // OpenconfigListEnumKey_FooIdentity_BAZ corresponds to the value BAZ of OpenconfigListEnumKey_FooIdentity + OpenconfigListEnumKey_FooIdentity_BAZ E_OpenconfigListEnumKey_FooIdentity = 2 +) + +// ΛEnum is a map, keyed by the name of the type defined for each enum in the +// generated Go code, which provides a mapping between the constant int64 value +// of each value of the enumeration, and the string that is used to represent it +// in the YANG schema. The map is named ΛEnum in order to avoid clash with any +// valid YANG identifier. +var ΛEnum = map[string]map[int64]ygot.EnumDefinition{ + "E_Ekm_K1": { + 1: {Name: "A"}, + 2: {Name: "B"}, + }, + "E_Eks_K": { + 1: {Name: "A"}, + 2: {Name: "B"}, + }, + "E_OpenconfigListEnumKey_FooIdentity": { + 1: {Name: "BAR", DefiningModule: "openconfig-list-enum-key"}, + 2: {Name: "BAZ", DefiningModule: "openconfig-list-enum-key"}, + }, +} diff --git a/gogen/testdata/structs/openconfig-simple.formatted-txt b/gogen/testdata/structs/openconfig-simple.formatted-txt index 522319b76..4befeb741 100644 --- a/gogen/testdata/structs/openconfig-simple.formatted-txt +++ b/gogen/testdata/structs/openconfig-simple.formatted-txt @@ -173,6 +173,30 @@ func (t *Parent_Child) GetTwo() string { return *t.Two } +// SetFour sets the value of the leaf Four in the Parent_Child +// struct. +func (t *Parent_Child) SetFour(v Binary) { + t.Four = v +} + +// SetOne sets the value of the leaf One in the Parent_Child +// struct. +func (t *Parent_Child) SetOne(v string) { + t.One = &v +} + +// SetThree sets the value of the leaf Three in the Parent_Child +// struct. +func (t *Parent_Child) SetThree(v E_Child_Three) { + t.Three = v +} + +// SetTwo sets the value of the leaf Two in the Parent_Child +// struct. +func (t *Parent_Child) SetTwo(v string) { + t.Two = &v +} + // PopulateDefaults recursively populates unset leaf fields in the Parent_Child // with default values as specified in the YANG schema, instantiating any nil // container fields. @@ -215,6 +239,12 @@ func (t *RemoteContainer) GetALeaf() string { return *t.ALeaf } +// SetALeaf sets the value of the leaf ALeaf in the RemoteContainer +// struct. +func (t *RemoteContainer) SetALeaf(v string) { + t.ALeaf = &v +} + // PopulateDefaults recursively populates unset leaf fields in the RemoteContainer // with default values as specified in the YANG schema, instantiating any nil // container fields.