package unique
import (
"internal/abi"
"internal/stringslite"
"unsafe"
)
func clone[T comparable ](value T , seq *cloneSeq ) T {
for _ , offset := range seq .stringOffsets {
ps := (*string )(unsafe .Pointer (uintptr (unsafe .Pointer (&value )) + offset ))
*ps = stringslite .Clone (*ps )
}
return value
}
var singleStringClone = cloneSeq {stringOffsets : []uintptr {0 }}
type cloneSeq struct {
stringOffsets []uintptr
}
func makeCloneSeq(typ *abi .Type ) cloneSeq {
if typ == nil {
return cloneSeq {}
}
if typ .Kind () == abi .String {
return singleStringClone
}
var seq cloneSeq
switch typ .Kind () {
case abi .Struct :
buildStructCloneSeq (typ , &seq , 0 )
case abi .Array :
buildArrayCloneSeq (typ , &seq , 0 )
}
return seq
}
func buildStructCloneSeq(typ *abi .Type , seq *cloneSeq , baseOffset uintptr ) {
styp := typ .StructType ()
for i := range styp .Fields {
f := &styp .Fields [i ]
switch f .Typ .Kind () {
case abi .String :
seq .stringOffsets = append (seq .stringOffsets , baseOffset +f .Offset )
case abi .Struct :
buildStructCloneSeq (f .Typ , seq , baseOffset +f .Offset )
case abi .Array :
buildArrayCloneSeq (f .Typ , seq , baseOffset +f .Offset )
}
}
}
func buildArrayCloneSeq(typ *abi .Type , seq *cloneSeq , baseOffset uintptr ) {
atyp := typ .ArrayType ()
etyp := atyp .Elem
offset := baseOffset
for range atyp .Len {
switch etyp .Kind () {
case abi .String :
seq .stringOffsets = append (seq .stringOffsets , offset )
case abi .Struct :
buildStructCloneSeq (etyp , seq , offset )
case abi .Array :
buildArrayCloneSeq (etyp , seq , offset )
}
offset += etyp .Size ()
align := uintptr (etyp .FieldAlign ())
offset = (offset + align - 1 ) &^ (align - 1 )
}
}
The pages are generated with Golds v0.7.0-preview . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .