Add bson clone
This commit is contained in:
50
struct.go
50
struct.go
@@ -76,7 +76,7 @@ func MapMerge[T ~map[string]any](maps...T) T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// StructMustTomap given any struct return the equivalent map[string]any or nil.
|
// StructMustTomap given any struct return the equivalent map[string]any or nil.
|
||||||
// Will never throw.
|
// Will never throw. Will also work for map[string]any.
|
||||||
func StructMustToMap(data any) map[string]any {
|
func StructMustToMap(data any) map[string]any {
|
||||||
b, err := json.Marshal(data)
|
b, err := json.Marshal(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -164,6 +164,54 @@ func StructToMapRecursive(obj any) any {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BsonClone(m map[string]any) map[string]any {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
out := make(map[string]any, len(m))
|
||||||
|
|
||||||
|
for k, v := range m {
|
||||||
|
out[k] = deepCopy(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func deepCopy(v any) any {
|
||||||
|
switch val := v.(type) {
|
||||||
|
case bson.M:
|
||||||
|
return BsonClone(map[string]any(val))
|
||||||
|
case bson.A:
|
||||||
|
arr := make([]any, len(val))
|
||||||
|
for i, item := range val {
|
||||||
|
arr[i] = deepCopy(item)
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
case bson.D:
|
||||||
|
d := make(bson.D, len(val))
|
||||||
|
for i, elem := range val {
|
||||||
|
d[i] = bson.E{
|
||||||
|
Key: elem.Key,
|
||||||
|
Value: deepCopy(elem.Value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
case map[string]any: // bson.M
|
||||||
|
return BsonClone(val)
|
||||||
|
case []any: // bson.A
|
||||||
|
arr := make([]any, len(val))
|
||||||
|
for i, item := range val {
|
||||||
|
arr[i] = deepCopy(item)
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
|
||||||
|
default:
|
||||||
|
// primitives (string, int, bool, etc.)
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BsonDGetAny(d bson.D, key string) (any, bool) {
|
func BsonDGetAny(d bson.D, key string) (any, bool) {
|
||||||
for _, e := range d {
|
for _, e := range d {
|
||||||
if e.Key == key {
|
if e.Key == key {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package commons
|
package commons
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -307,4 +308,31 @@ func TestMapMerge(t *testing.T) {
|
|||||||
if len(m) != 4 {
|
if len(m) != 4 {
|
||||||
t.Fatalf("Merged map should have lenght 4 not %d", len(m))
|
t.Fatalf("Merged map should have lenght 4 not %d", len(m))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBsonClone(t *testing.T) {
|
||||||
|
orig := map[string]any{
|
||||||
|
"name": "Kolias",
|
||||||
|
"age": int32(56),
|
||||||
|
"salary": int64(100000000),
|
||||||
|
"meta": map[string]any{
|
||||||
|
"num1": int32(110),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
clone := BsonClone(orig)
|
||||||
|
|
||||||
|
if "int32" != fmt.Sprintf("%T", clone["age"]) {
|
||||||
|
t.Fatalf("int32 should map to int32")
|
||||||
|
}
|
||||||
|
|
||||||
|
if "int64" != fmt.Sprintf("%T", clone["salary"]) {
|
||||||
|
t.Fatalf("int64 should map to int64")
|
||||||
|
}
|
||||||
|
|
||||||
|
meta := clone["meta"].(map[string]any)
|
||||||
|
|
||||||
|
if "int32" != fmt.Sprintf("%T", meta["num1"]) {
|
||||||
|
t.Fatalf("netsted type should have been int32")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user