github.com/anthropics/anthropic-sdk-go@v1.70.1/internal/apiquery/encoder.go (about) 1 package apiquery 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "reflect" 7 "strconv" 8 "strings" 9 "sync" 10 "time" 11 12 "github.com/anthropics/anthropic-sdk-go/packages/param" 13 ) 14 15 var encoders sync.Map // map[reflect.Type]encoderFunc 16 17 type encoder struct { 18 dateFormat string 19 root bool 20 settings QuerySettings 21 } 22 23 type encoderFunc func(key string, value reflect.Value) ([]Pair, error) 24 25 type encoderField struct { 26 tag parsedStructTag 27 fn encoderFunc 28 idx []int 29 } 30 31 type encoderEntry struct { 32 typ reflect.Type 33 dateFormat string 34 root bool 35 settings QuerySettings 36 } 37 38 type Pair struct { 39 key string 40 value string 41 } 42 43 func (e *encoder) typeEncoder(t reflect.Type) encoderFunc { 44 entry := encoderEntry{ 45 typ: t, 46 dateFormat: e.dateFormat, 47 root: e.root, 48 settings: e.settings, 49 } 50 51 if fi, ok := encoders.Load(entry); ok { 52 return fi.(encoderFunc) 53 } 54 55 // To deal with recursive types, populate the map with an 56 // indirect func before we build it. This type waits on the 57 // real func (f) to be ready and then calls it. This indirect 58 // func is only used for recursive types. 59 var ( 60 wg sync.WaitGroup 61 f encoderFunc 62 ) 63 wg.Add(1) 64 fi, loaded := encoders.LoadOrStore(entry, encoderFunc(func(key string, v reflect.Value) ([]Pair, error) { 65 wg.Wait() 66 return f(key, v) 67 })) 68 if loaded { 69 return fi.(encoderFunc) 70 } 71 72 // Compute the real encoder and replace the indirect func with it. 73 f = e.newTypeEncoder(t) 74 wg.Done() 75 encoders.Store(entry, f) 76 return f 77 } 78 79 func marshalerEncoder(key string, value reflect.Value) ([]Pair, error) { 80 s, err := value.Interface().(json.Marshaler).MarshalJSON() 81 if err != nil { 82 return nil, fmt.Errorf("apiquery: json fallback marshal error %s", err) 83 } 84 return []Pair{{key, string(s)}}, nil 85 } 86 87 func (e *encoder) newTypeEncoder(t reflect.Type) encoderFunc { 88 if t.ConvertibleTo(reflect.TypeOf(time.Time{})) { 89 return e.newTimeTypeEncoder(t) 90 } 91 92 if t.Implements(reflect.TypeOf((*param.Optional)(nil)).Elem()) { 93 return e.newRichFieldTypeEncoder(t) 94 } 95 96 if !e.root && t.Implements(reflect.TypeOf((*json.Marshaler)(nil)).Elem()) { 97 return marshalerEncoder 98 } 99 100 e.root = false 101 switch t.Kind() { 102 case reflect.Pointer: 103 encoder := e.typeEncoder(t.Elem()) 104 return func(key string, value reflect.Value) (pairs []Pair, err error) { 105 if !value.IsValid() || value.IsNil() { 106 return pairs, err 107 } 108 return encoder(key, value.Elem()) 109 } 110 case reflect.Struct: 111 return e.newStructTypeEncoder(t) 112 case reflect.Array: 113 fallthrough 114 case reflect.Slice: 115 return e.newArrayTypeEncoder(t) 116 case reflect.Map: 117 return e.newMapEncoder(t) 118 case reflect.Interface: 119 return e.newInterfaceEncoder() 120 default: 121 return e.newPrimitiveTypeEncoder(t) 122 } 123 } 124 125 func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc { 126 if t.Implements(reflect.TypeOf((*param.Optional)(nil)).Elem()) { 127 return e.newRichFieldTypeEncoder(t) 128 } 129 130 for i := 0; i < t.NumField(); i++ { 131 if t.Field(i).Type == paramUnionType && t.Field(i).Anonymous { 132 return e.newStructUnionTypeEncoder(t) 133 } 134 } 135 136 encoderFields := []encoderField{} 137 138 // This helper allows us to recursively collect field encoders into a flat 139 // array. The parameter `index` keeps track of the access patterns necessary 140 // to get to some field. 141 var collectEncoderFields func(r reflect.Type, index []int) 142 collectEncoderFields = func(r reflect.Type, index []int) { 143 for i := 0; i < r.NumField(); i++ { 144 idx := append(index, i) 145 field := t.FieldByIndex(idx) 146 if !field.IsExported() { 147 continue 148 } 149 // If this is an embedded struct, traverse one level deeper to extract 150 // the field and get their encoders as well. 151 if field.Anonymous { 152 collectEncoderFields(field.Type, idx) 153 continue 154 } 155 // If query tag is not present, then we skip, which is intentionally 156 // different behavior from the stdlib. 157 ptag, ok := parseQueryStructTag(field) 158 if !ok { 159 continue 160 } 161 162 if (ptag.name == "-" || ptag.name == "") && !ptag.inline { 163 continue 164 } 165 166 dateFormat, ok := parseFormatStructTag(field) 167 oldFormat := e.dateFormat 168 if ok { 169 switch dateFormat { 170 case "date-time": 171 e.dateFormat = time.RFC3339 172 case "date": 173 e.dateFormat = "2006-01-02" 174 } 175 } 176 var encoderFn encoderFunc 177 if ptag.omitzero { 178 typeEncoderFn := e.typeEncoder(field.Type) 179 encoderFn = func(key string, value reflect.Value) ([]Pair, error) { 180 if value.IsZero() { 181 return nil, nil 182 } 183 return typeEncoderFn(key, value) 184 } 185 } else { 186 encoderFn = e.typeEncoder(field.Type) 187 } 188 encoderFields = append(encoderFields, encoderField{ptag, encoderFn, idx}) 189 e.dateFormat = oldFormat 190 } 191 } 192 collectEncoderFields(t, []int{}) 193 194 return func(key string, value reflect.Value) (pairs []Pair, err error) { 195 for _, ef := range encoderFields { 196 subkey := e.renderKeyPath(key, ef.tag.name) 197 if ef.tag.inline { 198 subkey = key 199 } 200 201 field := value.FieldByIndex(ef.idx) 202 subpairs, suberr := ef.fn(subkey, field) 203 if suberr != nil { 204 err = suberr 205 } 206 pairs = append(pairs, subpairs...) 207 } 208 return pairs, err 209 } 210 } 211 212 var paramUnionType = reflect.TypeOf((*param.APIUnion)(nil)).Elem() 213 214 func (e *encoder) newStructUnionTypeEncoder(t reflect.Type) encoderFunc { 215 var fieldEncoders []encoderFunc 216 for i := 0; i < t.NumField(); i++ { 217 field := t.Field(i) 218 if field.Type == paramUnionType && field.Anonymous { 219 fieldEncoders = append(fieldEncoders, nil) 220 continue 221 } 222 fieldEncoders = append(fieldEncoders, e.typeEncoder(field.Type)) 223 } 224 225 return func(key string, value reflect.Value) (pairs []Pair, err error) { 226 for i := 0; i < t.NumField(); i++ { 227 if value.Field(i).Type() == paramUnionType { 228 continue 229 } 230 if !value.Field(i).IsZero() { 231 return fieldEncoders[i](key, value.Field(i)) 232 } 233 } 234 return nil, fmt.Errorf("apiquery: union %s has no field set", t.String()) 235 } 236 } 237 238 func (e *encoder) newMapEncoder(t reflect.Type) encoderFunc { 239 keyEncoder := e.typeEncoder(t.Key()) 240 elementEncoder := e.typeEncoder(t.Elem()) 241 return func(key string, value reflect.Value) (pairs []Pair, err error) { 242 iter := value.MapRange() 243 for iter.Next() { 244 encodedKey, err := keyEncoder("", iter.Key()) 245 if err != nil { 246 return nil, err 247 } 248 if len(encodedKey) != 1 { 249 return nil, fmt.Errorf("apiquery: unexpected number of parts for encoded map key, map may contain non-primitive") 250 } 251 subkey := encodedKey[0].value 252 keyPath := e.renderKeyPath(key, subkey) 253 subpairs, suberr := elementEncoder(keyPath, iter.Value()) 254 if suberr != nil { 255 err = suberr 256 } 257 pairs = append(pairs, subpairs...) 258 } 259 return pairs, err 260 } 261 } 262 263 func (e *encoder) renderKeyPath(key string, subkey string) string { 264 if len(key) == 0 { 265 return subkey 266 } 267 if e.settings.NestedFormat == NestedQueryFormatDots { 268 return fmt.Sprintf("%s.%s", key, subkey) 269 } 270 return fmt.Sprintf("%s[%s]", key, subkey) 271 } 272 273 func (e *encoder) newArrayTypeEncoder(t reflect.Type) encoderFunc { 274 switch e.settings.ArrayFormat { 275 case ArrayQueryFormatComma: 276 innerEncoder := e.typeEncoder(t.Elem()) 277 return func(key string, v reflect.Value) ([]Pair, error) { 278 elements := []string{} 279 for i := 0; i < v.Len(); i++ { 280 innerPairs, err := innerEncoder("", v.Index(i)) 281 if err != nil { 282 return nil, err 283 } 284 for _, pair := range innerPairs { 285 elements = append(elements, pair.value) 286 } 287 } 288 if len(elements) == 0 { 289 return []Pair{}, nil 290 } 291 return []Pair{{key, strings.Join(elements, ",")}}, nil 292 } 293 case ArrayQueryFormatRepeat: 294 innerEncoder := e.typeEncoder(t.Elem()) 295 return func(key string, value reflect.Value) (pairs []Pair, err error) { 296 for i := 0; i < value.Len(); i++ { 297 subpairs, suberr := innerEncoder(key, value.Index(i)) 298 if suberr != nil { 299 err = suberr 300 } 301 pairs = append(pairs, subpairs...) 302 } 303 return pairs, err 304 } 305 case ArrayQueryFormatIndices: 306 panic("The array indices format is not supported yet") 307 case ArrayQueryFormatBrackets: 308 innerEncoder := e.typeEncoder(t.Elem()) 309 return func(key string, value reflect.Value) (pairs []Pair, err error) { 310 pairs = []Pair{} 311 for i := 0; i < value.Len(); i++ { 312 subpairs, suberr := innerEncoder(key+"[]", value.Index(i)) 313 if suberr != nil { 314 err = suberr 315 } 316 pairs = append(pairs, subpairs...) 317 } 318 return pairs, err 319 } 320 default: 321 panic(fmt.Sprintf("Unknown ArrayFormat value: %d", e.settings.ArrayFormat)) 322 } 323 } 324 325 func (e *encoder) newPrimitiveTypeEncoder(t reflect.Type) encoderFunc { 326 switch t.Kind() { 327 case reflect.Pointer: 328 inner := t.Elem() 329 330 innerEncoder := e.newPrimitiveTypeEncoder(inner) 331 return func(key string, v reflect.Value) ([]Pair, error) { 332 if !v.IsValid() || v.IsNil() { 333 return nil, nil 334 } 335 return innerEncoder(key, v.Elem()) 336 } 337 case reflect.String: 338 return func(key string, v reflect.Value) ([]Pair, error) { 339 return []Pair{{key, v.String()}}, nil 340 } 341 case reflect.Bool: 342 return func(key string, v reflect.Value) ([]Pair, error) { 343 if v.Bool() { 344 return []Pair{{key, "true"}}, nil 345 } 346 return []Pair{{key, "false"}}, nil 347 } 348 case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64: 349 return func(key string, v reflect.Value) ([]Pair, error) { 350 return []Pair{{key, strconv.FormatInt(v.Int(), 10)}}, nil 351 } 352 case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: 353 return func(key string, v reflect.Value) ([]Pair, error) { 354 return []Pair{{key, strconv.FormatUint(v.Uint(), 10)}}, nil 355 } 356 case reflect.Float32, reflect.Float64: 357 return func(key string, v reflect.Value) ([]Pair, error) { 358 return []Pair{{key, strconv.FormatFloat(v.Float(), 'f', -1, 64)}}, nil 359 } 360 case reflect.Complex64, reflect.Complex128: 361 bitSize := 64 362 if t.Kind() == reflect.Complex128 { 363 bitSize = 128 364 } 365 return func(key string, v reflect.Value) ([]Pair, error) { 366 return []Pair{{key, strconv.FormatComplex(v.Complex(), 'f', -1, bitSize)}}, nil 367 } 368 default: 369 return func(key string, v reflect.Value) ([]Pair, error) { 370 return nil, nil 371 } 372 } 373 } 374 375 func (e *encoder) newTimeTypeEncoder(_ reflect.Type) encoderFunc { 376 format := e.dateFormat 377 return func(key string, value reflect.Value) ([]Pair, error) { 378 return []Pair{{ 379 key, 380 value.Convert(reflect.TypeOf(time.Time{})).Interface().(time.Time).Format(format), 381 }}, nil 382 } 383 } 384 385 func (e encoder) newInterfaceEncoder() encoderFunc { 386 return func(key string, value reflect.Value) ([]Pair, error) { 387 value = value.Elem() 388 if !value.IsValid() { 389 return nil, nil 390 } 391 return e.typeEncoder(value.Type())(key, value) 392 } 393 394 }