Add bson clone

This commit is contained in:
George Suntres
2026-04-23 15:37:20 -04:00
parent 0ce3f3b5eb
commit 28dcfb9e4c
2 changed files with 77 additions and 1 deletions

View File

@@ -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.
// Will never throw.
// Will never throw. Will also work for map[string]any.
func StructMustToMap(data any) map[string]any {
b, err := json.Marshal(data)
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) {
for _, e := range d {
if e.Key == key {

View File

@@ -1,6 +1,7 @@
package commons
import (
"fmt"
"testing"
)
@@ -308,3 +309,30 @@ func TestMapMerge(t *testing.T) {
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")
}
}