github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/thrift/generic/value.go (about) 1 /** 2 * Copyright 2023 CloudWeGo Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package generic 18 19 import ( 20 "fmt" 21 "unsafe" 22 23 "github.com/cloudwego/dynamicgo/internal/rt" 24 "github.com/cloudwego/dynamicgo/meta" 25 "github.com/cloudwego/dynamicgo/thrift" 26 ) 27 28 // Value is a generic API wrapper for operations on thrift data. 29 // Node is the underlying raw bytes. 30 // Desc is the corresponding type descriptor. 31 type Value struct { 32 Node 33 Desc *thrift.TypeDescriptor 34 } 35 36 // NewValue creates a new Value from a raw byte slice. 37 func NewValue(desc *thrift.TypeDescriptor, src []byte) Value { 38 return Value{ 39 Node: NewNode(desc.Type(), src), 40 Desc: desc, 41 } 42 } 43 44 // NewValueFromNode copy both Node and TypeDescriptor from another Value. 45 func (self Value) Fork() Value { 46 ret := self 47 ret.Node = self.Node.Fork() 48 return ret 49 } 50 51 func (self Value) slice(s int, e int, desc *thrift.TypeDescriptor) Value { 52 t := desc.Type() 53 ret := Value{ 54 Node: Node{ 55 t: t, 56 l: (e - s), 57 v: rt.AddPtr(self.v, uintptr(s)), 58 }, 59 Desc: desc, 60 } 61 if t == thrift.LIST || t == thrift.SET { 62 ret.et = desc.Elem().Type() 63 } else if t == thrift.MAP { 64 ret.kt = desc.Key().Type() 65 ret.et = desc.Elem().Type() 66 } 67 return ret 68 } 69 70 func searchFieldName(p *thrift.BinaryProtocol, id string, f *thrift.FieldDescriptor) (tt thrift.Type, start int, err error) { 71 // if _, err := p.ReadStructBegin(); err != nil { 72 // return 0, start, wrapError(meta.ErrReadInput, "", err) 73 // } 74 for { 75 _, t, i, err := p.ReadFieldBegin() 76 if err != nil { 77 return 0, start, wrapError(meta.ErrRead, "", err) 78 } 79 if t == thrift.STOP { 80 return thrift.STRUCT, start, errNotFound 81 } 82 if f.ID() == thrift.FieldID(i) { 83 // if t != f.Type().Type() { 84 // return 0, start, wrapError(meta.ErrDismatchType, fmt.Sprintf("field '%s' expects type %s, buf got type %s", f.Name(), f.Type().Type(), t), nil) 85 // } 86 start = p.Read 87 tt = t 88 break 89 } 90 if err := p.Skip(t, UseNativeSkipForGet); err != nil { 91 return thrift.STRUCT, start, wrapError(meta.ErrRead, "", err) 92 } 93 } 94 return 95 } 96 97 // GetByPath searches longitudinally and return a sub value at the given path from the value. 98 // 99 // The path is a list of PathFieldId, PathFieldName, PathIndex, PathStrKey, PathBinKey, PathIntKey, 100 // Each path MUST be a valid path type for current layer (e.g. PathFieldId is only valid for STRUCT). 101 // Empty path will return the current value. 102 func (self Value) GetByPath(pathes ...Path) Value { 103 if self.Error() != "" { 104 return self 105 } 106 107 p := thrift.BinaryProtocol{ 108 Buf: self.raw(), 109 } 110 start := 0 111 desc := self.Desc 112 tt := self.t 113 isList := tt == thrift.LIST 114 var err error 115 116 for i, path := range pathes { 117 switch path.t { 118 case PathFieldId: 119 id := path.id() 120 tt, start, err = searchFieldId(&p, id) 121 desc = desc.Struct().FieldById(id).Type() 122 isList = tt == thrift.LIST 123 case PathFieldName: 124 id := path.str() 125 f := desc.Struct().FieldByKey(id) 126 if f == nil { 127 return errValue(meta.ErrUnknownField, fmt.Sprintf("field name '%s' is not defined in IDL", id), nil) 128 } 129 tt, start, err = searchFieldName(&p, id, f) 130 desc = f.Type() 131 isList = tt == thrift.LIST 132 case PathIndex: 133 tt, start, err = searchIndex(&p, path.int(), isList) 134 desc = desc.Elem() 135 case PathStrKey: 136 tt, start, err = searchStrKey(&p, path.str()) 137 desc = desc.Elem() 138 case PathIntKey: 139 tt, start, err = searchIntKey(&p, path.int()) 140 desc = desc.Elem() 141 case PathBinKey: 142 tt, start, err = searchBinKey(&p, path.bin()) 143 desc = desc.Elem() 144 default: 145 return errValue(meta.ErrUnsupportedType, fmt.Sprintf("invalid %dth path: %#v", i, p), nil) 146 } 147 if err != nil { 148 // the last one not foud, return start pointer for subsequently inserting operation on `SetByPath()` 149 if i == len(pathes)-1 && err == errNotFound { 150 return Value{errNotFoundLast(unsafe.Pointer(uintptr(self.v)+uintptr(start)), tt), nil} 151 } 152 en := err.(Node) 153 return errValue(en.ErrCode().Behavior(), "", err) 154 } 155 } 156 157 if err := p.Skip(desc.Type(), UseNativeSkipForGet); err != nil { 158 return errValue(meta.ErrRead, "", err) 159 } 160 return self.slice(start, p.Read, desc) 161 } 162 163 // Field returns a sub node at the given field id from a STRUCT value. 164 func (self Value) Field(id thrift.FieldID) (v Value) { 165 n := self.Node.Field(id) 166 if n.IsError() { 167 return wrapValue(n, nil) 168 } 169 170 f := self.Desc.Struct().FieldById(id) 171 if f == nil { 172 return errValue(meta.ErrUnknownField, fmt.Sprintf("field id %d is not defined in IDL", id), nil) 173 } 174 175 return wrapValue(n, f.Type()) 176 } 177 178 // func (self Value) Fields(ids []PathNode, opts *Options) (err error) { 179 // if err := self.should("Fields", thrift.STRUCT); err != "" { 180 // return errValue(meta.ErrUnsupportedType, err, nil) 181 // } 182 183 // it := self.iterFields() 184 // if it.Err != nil { 185 // return errValue(meta.ErrReadInput, "", it.Err) 186 // } 187 188 // need := len(ids) 189 // for count := 0; it.HasNext() && count < need; { 190 // var p *PathNode 191 // i, t, s, e := it.Next(opts.UseNativeSkip) 192 // if it.Err != nil { 193 // err = errValue(meta.ErrReadInput, "", it.Err) 194 // goto ret 195 // } 196 // f := self.Desc.Struct().FieldById(i) 197 // if f == nil { 198 // if opts.DisallowUnknow { 199 // err = errValue(meta.ErrUnknownField, fmt.Sprintf("field id %d is not defined in IDL", i), nil) 200 // goto ret 201 // } 202 // continue 203 204 // } 205 // if t != f.Type().Type() { 206 // err = errValue(meta.ErrDismatchType, fmt.Sprintf("field '%s' expects type %s, buf got type %s", f.Name(), f.Type().Type(), t), nil) 207 // goto ret 208 // } 209 // //TODO: use bitmap to avoid repeatedly scan 210 // for j, id := range ids { 211 // if (id.Path.t == PathFieldId && id.Path.Id() == i) || (id.Path.t == PathFieldName && id.Path.Str() == f.Name()) { 212 // p = &ids[j] 213 // count += 1 214 // break 215 // } 216 // } 217 // if p == nil { 218 // continue 219 // } 220 // p.Node = self.Node.slice(s, e, f.Type().Type()) 221 // } 222 223 // ret: 224 // // it.Recycle() 225 // return 226 // } 227 228 // FieldByName returns a sub node at the given field name from a STRUCT value. 229 func (self Value) FieldByName(name string) (v Value) { 230 if err := self.should("FieldByName", thrift.STRUCT); err != "" { 231 return errValue(meta.ErrUnsupportedType, err, nil) 232 } 233 234 f := self.Desc.Struct().FieldByKey(name) 235 if f == nil { 236 return errValue(meta.ErrUnknownField, fmt.Sprintf("field '%s' is not defined in IDL", name), nil) 237 } 238 239 // not found, try to scan the whole bytes 240 it := self.iterFields() 241 if it.Err != nil { 242 return errValue(meta.ErrRead, "", it.Err) 243 } 244 for it.HasNext() { 245 i, t, s, e := it.Next(UseNativeSkipForGet) 246 if i == f.ID() { 247 if t != f.Type().Type() { 248 v = errValue(meta.ErrDismatchType, fmt.Sprintf("field '%s' expects type %s, buf got type %s", f.Name(), f.Type().Type(), t), nil) 249 goto ret 250 } 251 v = self.slice(s, e, f.Type()) 252 goto ret 253 } else if it.Err != nil { 254 v = errValue(meta.ErrRead, "", it.Err) 255 goto ret 256 } 257 } 258 259 v = errValue(meta.ErrNotFound, fmt.Sprintf("field '%s' is not found in this value", name), errNotFound) 260 ret: 261 // it.Recycle() 262 return 263 } 264 265 // Index returns a sub node at the given index from a LIST value. 266 func (self Value) Index(i int) (v Value) { 267 n := self.Node.Index(i) 268 if n.IsError() { 269 return wrapValue(n, nil) 270 } 271 return wrapValue(n, self.Desc.Elem()) 272 } 273 274 // GetByStr returns a sub node at the given string key from a MAP value. 275 func (self Value) GetByStr(key string) (v Value) { 276 n := self.Node.GetByStr(key) 277 if n.IsError() { 278 return wrapValue(n, nil) 279 } 280 return wrapValue(n, self.Desc.Elem()) 281 } 282 283 // GetByInt returns a sub node at the given int key from a MAP value. 284 func (self Value) GetByInt(key int) (v Value) { 285 n := self.Node.GetByInt(key) 286 if n.IsError() { 287 return wrapValue(n, nil) 288 } 289 return wrapValue(n, self.Desc.Elem()) 290 } 291 292 // func (self Value) GetMany(pathes []PathNode, opts *Options) error { 293 // if len(pathes) == 0 { 294 // return nil 295 // } 296 // p := pathes[0] 297 // switch p.Path.t { 298 // case PathFieldId, PathFieldName: 299 // return self.Fields(pathes, opts) 300 // case PathIndex: 301 // return self.Indexes(pathes, opts) 302 // case PathStrKey, PathIntKey: 303 // return self.Gets(pathes, opts) 304 // case PathObjKey: 305 // panic("not implement yet") 306 // default: 307 // return errValue(meta.ErrUnsupportedType, fmt.Sprintf("invalid path: %#v", p), nil) 308 // } 309 // } 310 311 // SetByPath searches longitudinally and sets a sub value at the given path from the value. 312 // exist tells whether the node is already exists. 313 func (self *Value) SetByPath(sub Value, path ...Path) (exist bool, err error) { 314 l := len(path) 315 if l == 0 { 316 *self = sub 317 return true, nil 318 } 319 if err := self.Check(); err != nil { 320 return false, err 321 } 322 if sub.Error() != "" { 323 return false, meta.NewError(meta.ErrInvalidParam, "given node is invalid", sub) 324 } 325 326 // search source node by path 327 v := self.GetByPath(path...) 328 if v.IsError() { 329 if !v.isErrNotFoundLast() { 330 return false, v 331 } 332 p := path[l-1] 333 if p.t == PathFieldName { 334 desc, err := GetDescByPath(self.Desc, path[:l-1]...) 335 if err != nil { 336 return false, err 337 } 338 f := desc.Struct().FieldByKey(p.str()) 339 p = NewPathFieldId(f.ID()) 340 } 341 if err := v.setNotFound(p, &sub.Node); err != nil { 342 return false, err 343 } 344 } else { 345 exist = true 346 } 347 err = self.replace(v.Node, sub.Node) 348 return 349 } 350 351 // UnsetByPath searches longitudinally and unsets a sub value at the given path from the value. 352 func (self *Value) UnsetByPath(path ...Path) error { 353 l := len(path) 354 if l == 0 { 355 *self = Value{} 356 return nil 357 } 358 if err := self.Check(); err != nil { 359 return err 360 } 361 // search parent node by path 362 var v = self.GetByPath(path[:l-1]...) 363 if v.IsError() { 364 if v.IsErrNotFound() { 365 return nil 366 } 367 return v 368 } 369 p := path[l-1] 370 if p.t == PathFieldName { 371 desc, err := GetDescByPath(self.Desc, path[:l-1]...) 372 if err != nil { 373 return err 374 } 375 f := desc.Struct().FieldByKey(p.str()) 376 p = NewPathFieldId(f.ID()) 377 } 378 ret := v.deleteChild(p) 379 if ret.IsError() { 380 return ret 381 } 382 return self.replace(ret, Node{t: ret.t}) 383 } 384 385 // var pathesPool = sync.Pool{ 386 // New: func() interface{} { 387 // return &pathSlice{ 388 // a: make([]PathNode, 0, defaultNodeSliceCap), 389 // } 390 // }, 391 // } 392 393 // func (self *Value) SetMany(pathes []PathNode, opts *Options) (err error) { 394 // if len(pathes) == 0 { 395 // return nil 396 // } 397 // if err := self.Check(); err != nil { 398 // return err 399 // } 400 401 // // copy original pathes 402 // ps := pnsPool.Get().(*pnSlice) 403 // if cap(ps.a) < len(pathes) { 404 // ps.a = make([]PathNode, len(pathes)) 405 // } else { 406 // ps.a = ps.a[:len(pathes)] 407 // } 408 // copy(ps.a, pathes) 409 // ps.b = pathes 410 411 // // get original values 412 // if err = self.GetMany(ps.a, opts); err != nil { 413 // goto ret 414 // } 415 416 // err = self.replaceMany(ps) 417 // ret: 418 // ps.b = nil 419 // pnsPool.Put(ps) 420 // return 421 // } 422 423 // MarshalTo marshals self value into a sub value descripted by the to descriptor, alse called as "Cutting". 424 // Usually, the to descriptor is a subset of self descriptor. 425 func (self Value) MarshalTo(to *thrift.TypeDescriptor, opts *Options) ([]byte, error) { 426 var w = thrift.NewBinaryProtocolBuffer() 427 var r = thrift.BinaryProtocol{} 428 r.Buf = self.raw() 429 var from = self.Desc 430 if from.Type() != to.Type() { 431 return nil, wrapError(meta.ErrDismatchType, "to descriptor dismatches from descriptor", nil) 432 } 433 if err := marshalTo(&r, w, from, to, opts); err != nil { 434 return nil, err 435 } 436 ret := make([]byte, len(w.Buf)) 437 copy(ret, w.Buf) 438 thrift.FreeBinaryProtocolBuffer(w) 439 return ret, nil 440 } 441 442 func marshalTo(read *thrift.BinaryProtocol, write *thrift.BinaryProtocol, from *thrift.TypeDescriptor, to *thrift.TypeDescriptor, opts *Options) error { 443 switch t := to.Type(); t { 444 case thrift.STRUCT: 445 if from == to { 446 return nil 447 } 448 var req *thrift.RequiresBitmap 449 if !opts.NotCheckRequireNess { 450 req = thrift.NewRequiresBitmap() 451 to.Struct().Requires().CopyTo(req) 452 } 453 454 for { 455 _, tt, i, err := read.ReadFieldBegin() 456 if err != nil { 457 return wrapError(meta.ErrRead, "", err) 458 } 459 460 if tt == thrift.STOP { 461 if !opts.NotCheckRequireNess { 462 if err := handleUnsets(*req, to.Struct(), write, opts.WriteDefault); err != nil { 463 return err 464 } 465 } 466 if err := write.WriteStructEnd(); err != nil { 467 return wrapError(meta.ErrWrite, "", err) 468 } 469 break 470 } 471 472 ff := from.Struct().FieldById(thrift.FieldID(i)) 473 if ff == nil { 474 if opts.DisallowUnknow { 475 return wrapError(meta.ErrUnknownField, fmt.Sprintf("unknown field %d", i), nil) 476 } else { 477 // if not set, skip to the next field 478 if err := read.Skip(tt, opts.UseNativeSkip); err != nil { 479 return wrapError(meta.ErrRead, "", err) 480 } 481 continue 482 } 483 } 484 485 if tt != ff.Type().Type() { 486 return wrapError(meta.ErrDismatchType, fmt.Sprintf("field %d expects type %s, buf got type %s", ff.ID(), ff.Type().Type(), thrift.Type(tt)), nil) 487 } 488 // find corresponding field in the 'to' descriptor 489 // TODO: use field name to find the field 490 // var tf *thrift.FieldDescriptor 491 // if opts.FieldByName { 492 // tf = to.Struct().FieldByKey(ff.Name()) 493 // } else { 494 tf := to.Struct().FieldById(thrift.FieldID(i)) 495 // } 496 if tf == nil { 497 // if not set, skip to the next field 498 if err := read.Skip(tt, opts.UseNativeSkip); err != nil { 499 return wrapError(meta.ErrRead, "", err) 500 } 501 continue 502 } 503 // if tt != tf.Type().Type() { 504 // return wrapError(meta.ErrDismatchType, fmt.Sprintf("field %d expects type %s, buf got type %s", tf.ID(), tf.Type().Type(), thrift.Type(tt)), nil) 505 // } 506 if err := write.WriteFieldBegin(tf.Name(), tt, i); err != nil { 507 return wrapError(meta.ErrWrite, "", err) 508 } 509 510 if !opts.NotCheckRequireNess { 511 req.Set(tf.ID(), thrift.OptionalRequireness) 512 } 513 514 if err := marshalTo(read, write, ff.Type(), tf.Type(), opts); err != nil { 515 return err 516 } 517 } 518 if !opts.NotCheckRequireNess { 519 thrift.FreeRequiresBitmap(req) 520 } 521 return nil 522 case thrift.LIST, thrift.SET: 523 if from.Type() != thrift.LIST && from.Type() != thrift.SET { 524 return wrapError(meta.ErrDismatchType, fmt.Sprintf("expect type LIST or SET, buf got type %s", from.Type()), nil) 525 } 526 if to.Elem() == from.Elem() { 527 goto skip_val 528 } 529 et, size, err := read.ReadListBegin() 530 if err != nil { 531 return wrapError(meta.ErrRead, "", err) 532 } 533 // if et != to.Elem().Type() || et != from.Elem().Type() { 534 // return wrapError(meta.ErrDismatchType, fmt.Sprintf("expect elem type %s, buf got type %s", from.Elem().Type(), et), nil) 535 // } 536 if err := write.WriteListBegin(et, size); err != nil { 537 return wrapError(meta.ErrWrite, "", err) 538 } 539 if size == 0 { 540 return nil 541 } 542 for i := 0; i < size; i++ { 543 if err := marshalTo(read, write, from.Elem(), to.Elem(), opts); err != nil { 544 return err 545 } 546 } 547 return nil 548 case thrift.MAP: 549 if from.Type() != thrift.MAP { 550 return wrapError(meta.ErrDismatchType, fmt.Sprintf("expect type MAP, buf got type %s", from.Type()), nil) 551 } 552 if to.Elem() == from.Elem() && to.Key() == from.Key() { 553 goto skip_val 554 } 555 kt, et, size, err := read.ReadMapBegin() 556 if err != nil { 557 return wrapError(meta.ErrRead, "", err) 558 } 559 // if et != to.Elem().Type() || et != from.Elem().Type() { 560 // return wrapError(meta.ErrDismatchType, fmt.Sprintf("expect elem type %s, buf got type %s", from.Elem().Type(), et), nil) 561 // } 562 // if kt != to.Key().Type() || kt != from.Key().Type() { 563 // return wrapError(meta.ErrDismatchType, fmt.Sprintf("expect key type %s, buf got type %s", from.Key().Type(), kt), nil) 564 // } 565 if err := write.WriteMapBegin(kt, et, size); err != nil { 566 return wrapError(meta.ErrWrite, "", err) 567 } 568 if size == 0 { 569 return nil 570 } 571 for i := 0; i < size; i++ { 572 if err := marshalTo(read, write, from.Key(), to.Key(), opts); err != nil { 573 return err 574 } 575 if err := marshalTo(read, write, from.Elem(), to.Elem(), opts); err != nil { 576 return err 577 } 578 } 579 return nil 580 } 581 582 skip_val: 583 if to.Type() != from.Type() { 584 return meta.NewError(meta.ErrDismatchType, "to descriptor dismatches from descriptor", nil) 585 } 586 e := read.Read 587 if err := read.Skip(to.Type(), opts.UseNativeSkip); err != nil { 588 return wrapError(meta.ErrRead, "", err) 589 } 590 s := read.Read 591 write.Buf = append(write.Buf, read.Buf[e:s]...) 592 return nil 593 } 594 595 func handleUnsets(req thrift.RequiresBitmap, desc *thrift.StructDescriptor, p *thrift.BinaryProtocol, writeDefault bool) error { 596 return req.CheckRequires(desc, writeDefault, func(f *thrift.FieldDescriptor) error { 597 if e := p.WriteFieldBegin(f.Name(), f.Type().Type(), (f.ID())); e != nil { 598 return e 599 } 600 return p.WriteEmpty(f.Type()) 601 }) 602 }