| 17 | } |
| 18 | |
| 19 | func EnvWithCache(c *Cache, env any) Nature { |
| 20 | if env == nil { |
| 21 | n := c.NatureOf(map[string]any{}) |
| 22 | n.Strict = true |
| 23 | return n |
| 24 | } |
| 25 | |
| 26 | switch env := env.(type) { |
| 27 | case types.Map: |
| 28 | nt := env.Nature() |
| 29 | return nt |
| 30 | } |
| 31 | |
| 32 | v := reflect.ValueOf(env) |
| 33 | t := v.Type() |
| 34 | |
| 35 | switch deref.Value(v).Kind() { |
| 36 | case reflect.Struct: |
| 37 | n := c.FromType(t) |
| 38 | n.Strict = true |
| 39 | return n |
| 40 | |
| 41 | case reflect.Map: |
| 42 | n := c.FromType(v.Type()) |
| 43 | if n.TypeData == nil { |
| 44 | n.TypeData = new(TypeData) |
| 45 | } |
| 46 | n.Strict = true |
| 47 | n.Fields = make(map[string]Nature, v.Len()) |
| 48 | |
| 49 | for _, key := range v.MapKeys() { |
| 50 | elem := v.MapIndex(key) |
| 51 | if !elem.IsValid() || !elem.CanInterface() { |
| 52 | panic(fmt.Sprintf("invalid map value: %s", key)) |
| 53 | } |
| 54 | |
| 55 | face := elem.Interface() |
| 56 | |
| 57 | switch face := face.(type) { |
| 58 | case types.Map: |
| 59 | nt := face.Nature() |
| 60 | n.Fields[key.String()] = nt |
| 61 | |
| 62 | default: |
| 63 | if face == nil { |
| 64 | n.Fields[key.String()] = c.NatureOf(nil) |
| 65 | continue |
| 66 | } |
| 67 | n.Fields[key.String()] = c.NatureOf(face) |
| 68 | } |
| 69 | |
| 70 | } |
| 71 | |
| 72 | return n |
| 73 | } |
| 74 | |
| 75 | panic(fmt.Sprintf("unknown type %T", env)) |
| 76 | } |