| 1 | package session |
| 2 | |
| 3 | import ( |
| 4 | "reflect" |
| 5 | |
| 6 | "reasonix/internal/provider" |
| 7 | ) |
| 8 | |
| 9 | func detachMessages(messages []provider.Message) []provider.Message { |
| 10 | if messages == nil { |
| 11 | return []provider.Message{} |
| 12 | } |
| 13 | return detachValue(reflect.ValueOf(messages)).Interface().([]provider.Message) |
| 14 | } |
| 15 | |
| 16 | // Provider DTOs contain nested slices, pointers, maps and raw JSON. Copy their |
| 17 | // mutable containers, preserving every field without a lossy shadow schema. |
| 18 | func detachValue(value reflect.Value) reflect.Value { |
| 19 | switch value.Kind() { |
| 20 | case reflect.Pointer, reflect.Interface: |
| 21 | if value.IsNil() { |
| 22 | return reflect.Zero(value.Type()) |
| 23 | } |
| 24 | inner := detachValue(value.Elem()) |
| 25 | out := reflect.New(value.Type()).Elem() |
| 26 | if value.Kind() == reflect.Pointer { |
| 27 | out.Set(reflect.New(value.Type().Elem())) |
| 28 | out.Elem().Set(inner) |
| 29 | } else { |
| 30 | out.Set(inner) |
| 31 | } |
| 32 | return out |
| 33 | case reflect.Slice: |
| 34 | if value.IsNil() { |
| 35 | return reflect.Zero(value.Type()) |
| 36 | } |
| 37 | out := reflect.MakeSlice(value.Type(), value.Len(), value.Len()) |
| 38 | for i := range value.Len() { |
| 39 | out.Index(i).Set(detachValue(value.Index(i))) |
| 40 | } |
| 41 | return out |
| 42 | case reflect.Map: |
| 43 | if value.IsNil() { |
| 44 | return reflect.Zero(value.Type()) |
| 45 | } |
| 46 | out := reflect.MakeMapWithSize(value.Type(), value.Len()) |
| 47 | iter := value.MapRange() |
| 48 | for iter.Next() { |
| 49 | out.SetMapIndex(iter.Key(), detachValue(iter.Value())) |
| 50 | } |
| 51 | return out |
| 52 | case reflect.Struct: |
| 53 | out := reflect.New(value.Type()).Elem() |
| 54 | out.Set(value) |
| 55 | for i := range value.NumField() { |
| 56 | if out.Field(i).CanSet() && value.Field(i).CanInterface() { |
| 57 | out.Field(i).Set(detachValue(value.Field(i))) |
| 58 | } |
| 59 | } |
| 60 | return out |
| 61 | default: |
| 62 | return value |
| 63 | } |
| 64 | } |
| 65 |