cmd/cloner,*: optimize nillable slice cloner

A wild @josharian appears with a good suggestion for a refactor, thanks
Josh!

Updates #9410
Signed-off-by: James Tucker <james@tailscale.com>
This commit is contained in:
James Tucker 2023-09-29 17:29:17 -07:00 committed by James Tucker
parent e91e96dfa5
commit ee90cd02fd
5 changed files with 34 additions and 58 deletions

View File

@ -122,8 +122,7 @@ func gen(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named) {
case *types.Slice: case *types.Slice:
if codegen.ContainsPointers(ft.Elem()) { if codegen.ContainsPointers(ft.Elem()) {
n := it.QualifiedName(ft.Elem()) n := it.QualifiedName(ft.Elem())
writef("if src.%s != nil {", fname) writef("dst.%s = append([]%s(nil), make([]%s, len(src.%s))...)", fname, n, n, fname)
writef("dst.%s = make([]%s, len(src.%s))", fname, n, fname)
writef("for i := range dst.%s {", fname) writef("for i := range dst.%s {", fname)
if ptr, isPtr := ft.Elem().(*types.Pointer); isPtr { if ptr, isPtr := ft.Elem().(*types.Pointer); isPtr {
if _, isBasic := ptr.Elem().Underlying().(*types.Basic); isBasic { if _, isBasic := ptr.Elem().Underlying().(*types.Basic); isBasic {
@ -138,7 +137,6 @@ func gen(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named) {
writef("\tdst.%s[i] = *src.%s[i].Clone()", fname, fname) writef("\tdst.%s[i] = *src.%s[i].Clone()", fname, fname)
} }
writef("}") writef("}")
writef("}")
} else { } else {
writef("dst.%s = append(src.%s[:0:0], src.%s...)", fname, fname, fname) writef("dst.%s = append(src.%s[:0:0], src.%s...)", fname, fname, fname)
} }

View File

@ -136,30 +136,22 @@ func (src *StructWithSlices) Clone() *StructWithSlices {
dst := new(StructWithSlices) dst := new(StructWithSlices)
*dst = *src *dst = *src
dst.Values = append(src.Values[:0:0], src.Values...) dst.Values = append(src.Values[:0:0], src.Values...)
if src.ValuePointers != nil { dst.ValuePointers = append([]*StructWithoutPtrs(nil), make([]*StructWithoutPtrs, len(src.ValuePointers))...)
dst.ValuePointers = make([]*StructWithoutPtrs, len(src.ValuePointers))
for i := range dst.ValuePointers { for i := range dst.ValuePointers {
dst.ValuePointers[i] = src.ValuePointers[i].Clone() dst.ValuePointers[i] = src.ValuePointers[i].Clone()
} }
} dst.StructPointers = append([]*StructWithPtrs(nil), make([]*StructWithPtrs, len(src.StructPointers))...)
if src.StructPointers != nil {
dst.StructPointers = make([]*StructWithPtrs, len(src.StructPointers))
for i := range dst.StructPointers { for i := range dst.StructPointers {
dst.StructPointers[i] = src.StructPointers[i].Clone() dst.StructPointers[i] = src.StructPointers[i].Clone()
} }
} dst.Structs = append([]StructWithPtrs(nil), make([]StructWithPtrs, len(src.Structs))...)
if src.Structs != nil {
dst.Structs = make([]StructWithPtrs, len(src.Structs))
for i := range dst.Structs { for i := range dst.Structs {
dst.Structs[i] = *src.Structs[i].Clone() dst.Structs[i] = *src.Structs[i].Clone()
} }
} dst.Ints = append([]*int(nil), make([]*int, len(src.Ints))...)
if src.Ints != nil {
dst.Ints = make([]*int, len(src.Ints))
for i := range dst.Ints { for i := range dst.Ints {
dst.Ints[i] = ptr.To(*src.Ints[i]) dst.Ints[i] = ptr.To(*src.Ints[i])
} }
}
dst.Slice = append(src.Slice[:0:0], src.Slice...) dst.Slice = append(src.Slice[:0:0], src.Slice...)
dst.Prefixes = append(src.Prefixes[:0:0], src.Prefixes...) dst.Prefixes = append(src.Prefixes[:0:0], src.Prefixes...)
dst.Data = append(src.Data[:0:0], src.Data...) dst.Data = append(src.Data[:0:0], src.Data...)

View File

@ -74,12 +74,10 @@ func (src *Node) Clone() *Node {
if dst.SelfNodeV6MasqAddrForThisPeer != nil { if dst.SelfNodeV6MasqAddrForThisPeer != nil {
dst.SelfNodeV6MasqAddrForThisPeer = ptr.To(*src.SelfNodeV6MasqAddrForThisPeer) dst.SelfNodeV6MasqAddrForThisPeer = ptr.To(*src.SelfNodeV6MasqAddrForThisPeer)
} }
if src.ExitNodeDNSResolvers != nil { dst.ExitNodeDNSResolvers = append([]*dnstype.Resolver(nil), make([]*dnstype.Resolver, len(src.ExitNodeDNSResolvers))...)
dst.ExitNodeDNSResolvers = make([]*dnstype.Resolver, len(src.ExitNodeDNSResolvers))
for i := range dst.ExitNodeDNSResolvers { for i := range dst.ExitNodeDNSResolvers {
dst.ExitNodeDNSResolvers[i] = src.ExitNodeDNSResolvers[i].Clone() dst.ExitNodeDNSResolvers[i] = src.ExitNodeDNSResolvers[i].Clone()
} }
}
return dst return dst
} }
@ -237,24 +235,20 @@ func (src *DNSConfig) Clone() *DNSConfig {
} }
dst := new(DNSConfig) dst := new(DNSConfig)
*dst = *src *dst = *src
if src.Resolvers != nil { dst.Resolvers = append([]*dnstype.Resolver(nil), make([]*dnstype.Resolver, len(src.Resolvers))...)
dst.Resolvers = make([]*dnstype.Resolver, len(src.Resolvers))
for i := range dst.Resolvers { for i := range dst.Resolvers {
dst.Resolvers[i] = src.Resolvers[i].Clone() dst.Resolvers[i] = src.Resolvers[i].Clone()
} }
}
if dst.Routes != nil { if dst.Routes != nil {
dst.Routes = map[string][]*dnstype.Resolver{} dst.Routes = map[string][]*dnstype.Resolver{}
for k := range src.Routes { for k := range src.Routes {
dst.Routes[k] = append([]*dnstype.Resolver{}, src.Routes[k]...) dst.Routes[k] = append([]*dnstype.Resolver{}, src.Routes[k]...)
} }
} }
if src.FallbackResolvers != nil { dst.FallbackResolvers = append([]*dnstype.Resolver(nil), make([]*dnstype.Resolver, len(src.FallbackResolvers))...)
dst.FallbackResolvers = make([]*dnstype.Resolver, len(src.FallbackResolvers))
for i := range dst.FallbackResolvers { for i := range dst.FallbackResolvers {
dst.FallbackResolvers[i] = src.FallbackResolvers[i].Clone() dst.FallbackResolvers[i] = src.FallbackResolvers[i].Clone()
} }
}
dst.Domains = append(src.Domains[:0:0], src.Domains...) dst.Domains = append(src.Domains[:0:0], src.Domains...)
dst.Nameservers = append(src.Nameservers[:0:0], src.Nameservers...) dst.Nameservers = append(src.Nameservers[:0:0], src.Nameservers...)
dst.CertDomains = append(src.CertDomains[:0:0], src.CertDomains...) dst.CertDomains = append(src.CertDomains[:0:0], src.CertDomains...)
@ -387,12 +381,10 @@ func (src *DERPRegion) Clone() *DERPRegion {
} }
dst := new(DERPRegion) dst := new(DERPRegion)
*dst = *src *dst = *src
if src.Nodes != nil { dst.Nodes = append([]*DERPNode(nil), make([]*DERPNode, len(src.Nodes))...)
dst.Nodes = make([]*DERPNode, len(src.Nodes))
for i := range dst.Nodes { for i := range dst.Nodes {
dst.Nodes[i] = src.Nodes[i].Clone() dst.Nodes[i] = src.Nodes[i].Clone()
} }
}
return dst return dst
} }
@ -468,12 +460,10 @@ func (src *SSHRule) Clone() *SSHRule {
if dst.RuleExpires != nil { if dst.RuleExpires != nil {
dst.RuleExpires = ptr.To(*src.RuleExpires) dst.RuleExpires = ptr.To(*src.RuleExpires)
} }
if src.Principals != nil { dst.Principals = append([]*SSHPrincipal(nil), make([]*SSHPrincipal, len(src.Principals))...)
dst.Principals = make([]*SSHPrincipal, len(src.Principals))
for i := range dst.Principals { for i := range dst.Principals {
dst.Principals[i] = src.Principals[i].Clone() dst.Principals[i] = src.Principals[i].Clone()
} }
}
dst.SSHUsers = maps.Clone(src.SSHUsers) dst.SSHUsers = maps.Clone(src.SSHUsers)
dst.Action = src.Action.Clone() dst.Action = src.Action.Clone()
return dst return dst

View File

@ -23,12 +23,10 @@ func (src *Match) Clone() *Match {
dst.IPProto = append(src.IPProto[:0:0], src.IPProto...) dst.IPProto = append(src.IPProto[:0:0], src.IPProto...)
dst.Srcs = append(src.Srcs[:0:0], src.Srcs...) dst.Srcs = append(src.Srcs[:0:0], src.Srcs...)
dst.Dsts = append(src.Dsts[:0:0], src.Dsts...) dst.Dsts = append(src.Dsts[:0:0], src.Dsts...)
if src.Caps != nil { dst.Caps = append([]CapMatch(nil), make([]CapMatch, len(src.Caps))...)
dst.Caps = make([]CapMatch, len(src.Caps))
for i := range dst.Caps { for i := range dst.Caps {
dst.Caps[i] = *src.Caps[i].Clone() dst.Caps[i] = *src.Caps[i].Clone()
} }
}
return dst return dst
} }

View File

@ -24,12 +24,10 @@ func (src *Config) Clone() *Config {
*dst = *src *dst = *src
dst.Addresses = append(src.Addresses[:0:0], src.Addresses...) dst.Addresses = append(src.Addresses[:0:0], src.Addresses...)
dst.DNS = append(src.DNS[:0:0], src.DNS...) dst.DNS = append(src.DNS[:0:0], src.DNS...)
if src.Peers != nil { dst.Peers = append([]Peer(nil), make([]Peer, len(src.Peers))...)
dst.Peers = make([]Peer, len(src.Peers))
for i := range dst.Peers { for i := range dst.Peers {
dst.Peers[i] = *src.Peers[i].Clone() dst.Peers[i] = *src.Peers[i].Clone()
} }
}
return dst return dst
} }