cmd/{cloner,viewer}: add support for map values with pointers

Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
Maisem Ali 2022-07-12 23:52:44 -07:00 committed by Maisem Ali
parent 26f103473c
commit 95d43c54bf
5 changed files with 34 additions and 8 deletions

View File

@ -153,18 +153,25 @@ func gen(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named) {
}
writef("}")
case *types.Map:
elem := ft.Elem()
writef("if dst.%s != nil {", fname)
writef("\tdst.%s = map[%s]%s{}", fname, it.QualifiedName(ft.Key()), it.QualifiedName(ft.Elem()))
if sliceType, isSlice := ft.Elem().(*types.Slice); isSlice {
writef("\tdst.%s = map[%s]%s{}", fname, it.QualifiedName(ft.Key()), it.QualifiedName(elem))
if sliceType, isSlice := elem.(*types.Slice); isSlice {
n := it.QualifiedName(sliceType.Elem())
writef("\tfor k := range src.%s {", fname)
// use zero-length slice instead of nil to ensure
// the key is always copied.
writef("\t\tdst.%s[k] = append([]%s{}, src.%s[k]...)", fname, n, fname)
writef("\t}")
} else if codegen.ContainsPointers(ft.Elem()) {
} else if codegen.ContainsPointers(elem) {
writef("\tfor k, v := range src.%s {", fname)
writef("\t\tdst.%s[k] = v.Clone()", fname)
switch elem.(type) {
case *types.Pointer:
writef("\t\tdst.%s[k] = v.Clone()", fname)
default:
writef("\t\tv2 := v.Clone()")
writef("\t\tdst.%s[k] = *v2", fname)
}
writef("\t}")
} else {
writef("\tfor k, v := range src.%s {", fname)

View File

@ -31,6 +31,7 @@ type Map struct {
SliceIntPtr map[string][]*int
PointerKey map[*string]int `json:"-"`
StructWithPtrKey map[StructWithPtrs]int `json:"-"`
StructWithPtr map[string]StructWithPtrs
}
type StructWithPtrs struct {

View File

@ -127,6 +127,13 @@ func (src *Map) Clone() *Map {
dst.StructWithPtrKey[k] = v
}
}
if dst.StructWithPtr != nil {
dst.StructWithPtr = map[string]StructWithPtrs{}
for k, v := range src.StructWithPtr {
v2 := v.Clone()
dst.StructWithPtr[k] = *v2
}
}
return dst
}
@ -143,6 +150,7 @@ func (src *Map) Clone() *Map {
SliceIntPtr map[string][]*int
PointerKey map[*string]int
StructWithPtrKey map[StructWithPtrs]int
StructWithPtr map[string]StructWithPtrs
}{})
// Clone makes a deep copy of StructWithSlices.

View File

@ -231,6 +231,12 @@ func (v MapView) SliceIntPtr() map[string][]*int { panic("unsupported"
func (v MapView) PointerKey() map[*string]int { panic("unsupported") }
func (v MapView) StructWithPtrKey() map[StructWithPtrs]int { panic("unsupported") }
func (v MapView) StructWithPtr() views.MapFn[string, StructWithPtrs, StructWithPtrsView] {
return views.MapFnOf(v.ж.StructWithPtr, func(t StructWithPtrs) StructWithPtrsView {
return t.View()
})
}
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _MapViewNeedsRegeneration = Map(struct {
Int map[string]int
@ -244,6 +250,7 @@ func (v MapView) StructWithPtrKey() map[StructWithPtrs]int { panic("unsupported"
SliceIntPtr map[string][]*int
PointerKey map[*string]int
StructWithPtrKey map[StructWithPtrs]int
StructWithPtr map[string]StructWithPtrs
}{})
// View returns a readonly view of StructWithSlices.

View File

@ -228,11 +228,14 @@ func genView(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named, thi
strucT := u
args.FieldType = it.QualifiedName(fieldType)
if codegen.ContainsPointers(strucT) {
writeTemplate("unsupportedField")
continue
args.MapFn = "t.View()"
template = "mapFnField"
args.MapValueType = it.QualifiedName(mElem)
args.MapValueView = args.MapValueType + "View"
} else {
template = "mapField"
args.MapValueType = it.QualifiedName(mElem)
}
template = "mapField"
args.MapValueType = it.QualifiedName(mElem)
case *types.Basic:
template = "mapField"
args.MapValueType = it.QualifiedName(mElem)