github.com/lianghucheng/zrddz@v0.0.0-20200923083010-c71f680932e2/src/gopkg.in/mgo.v2/bson/encode.go (about) 1 // BSON library for Go 2 // 3 // Copyright (c) 2010-2012 - Gustavo Niemeyer <gustavo@niemeyer.net> 4 // 5 // All rights reserved. 6 // 7 // Redistribution and use in source and binary forms, with or without 8 // modification, are permitted provided that the following conditions are met: 9 // 10 // 1. Redistributions of source code must retain the above copyright notice, this 11 // list of conditions and the following disclaimer. 12 // 2. Redistributions in binary form must reproduce the above copyright notice, 13 // this list of conditions and the following disclaimer in the documentation 14 // and/or other materials provided with the distribution. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // gobson - BSON library for Go. 27 28 package bson 29 30 import ( 31 "encoding/json" 32 "fmt" 33 "math" 34 "net/url" 35 "reflect" 36 "strconv" 37 "time" 38 ) 39 40 // -------------------------------------------------------------------------- 41 // Some internal infrastructure. 42 43 var ( 44 typeBinary = reflect.TypeOf(Binary{}) 45 typeObjectId = reflect.TypeOf(ObjectId("")) 46 typeDBPointer = reflect.TypeOf(DBPointer{"", ObjectId("")}) 47 typeSymbol = reflect.TypeOf(Symbol("")) 48 typeMongoTimestamp = reflect.TypeOf(MongoTimestamp(0)) 49 typeOrderKey = reflect.TypeOf(MinKey) 50 typeDocElem = reflect.TypeOf(DocElem{}) 51 typeRawDocElem = reflect.TypeOf(RawDocElem{}) 52 typeRaw = reflect.TypeOf(Raw{}) 53 typeURL = reflect.TypeOf(url.URL{}) 54 typeTime = reflect.TypeOf(time.Time{}) 55 typeString = reflect.TypeOf("") 56 typeJSONNumber = reflect.TypeOf(json.Number("")) 57 ) 58 59 const itoaCacheSize = 32 60 61 var itoaCache []string 62 63 func init() { 64 itoaCache = make([]string, itoaCacheSize) 65 for i := 0; i != itoaCacheSize; i++ { 66 itoaCache[i] = strconv.Itoa(i) 67 } 68 } 69 70 func itoa(i int) string { 71 if i < itoaCacheSize { 72 return itoaCache[i] 73 } 74 return strconv.Itoa(i) 75 } 76 77 // -------------------------------------------------------------------------- 78 // Marshaling of the document value itself. 79 80 type encoder struct { 81 out []byte 82 } 83 84 func (e *encoder) addDoc(v reflect.Value) { 85 for { 86 if vi, ok := v.Interface().(Getter); ok { 87 getv, err := vi.GetBSON() 88 if err != nil { 89 panic(err) 90 } 91 v = reflect.ValueOf(getv) 92 continue 93 } 94 if v.Kind() == reflect.Ptr { 95 v = v.Elem() 96 continue 97 } 98 break 99 } 100 101 if v.Type() == typeRaw { 102 raw := v.Interface().(Raw) 103 if raw.Kind != 0x03 && raw.Kind != 0x00 { 104 panic("Attempted to marshal Raw kind " + strconv.Itoa(int(raw.Kind)) + " as a document") 105 } 106 if len(raw.Data) == 0 { 107 panic("Attempted to marshal empty Raw document") 108 } 109 e.addBytes(raw.Data...) 110 return 111 } 112 113 start := e.reserveInt32() 114 115 switch v.Kind() { 116 case reflect.Map: 117 e.addMap(v) 118 case reflect.Struct: 119 e.addStruct(v) 120 case reflect.Array, reflect.Slice: 121 e.addSlice(v) 122 default: 123 panic("Can't marshal " + v.Type().String() + " as a BSON document") 124 } 125 126 e.addBytes(0) 127 e.setInt32(start, int32(len(e.out)-start)) 128 } 129 130 func (e *encoder) addMap(v reflect.Value) { 131 for _, k := range v.MapKeys() { 132 e.addElem(k.String(), v.MapIndex(k), false) 133 } 134 } 135 136 func (e *encoder) addStruct(v reflect.Value) { 137 sinfo, err := getStructInfo(v.Type()) 138 if err != nil { 139 panic(err) 140 } 141 var value reflect.Value 142 if sinfo.InlineMap >= 0 { 143 m := v.Field(sinfo.InlineMap) 144 if m.Len() > 0 { 145 for _, k := range m.MapKeys() { 146 ks := k.String() 147 if _, found := sinfo.FieldsMap[ks]; found { 148 panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", ks)) 149 } 150 e.addElem(ks, m.MapIndex(k), false) 151 } 152 } 153 } 154 for _, info := range sinfo.FieldsList { 155 if info.Inline == nil { 156 value = v.Field(info.Num) 157 } else { 158 value = v.FieldByIndex(info.Inline) 159 } 160 if info.OmitEmpty && isZero(value) { 161 continue 162 } 163 e.addElem(info.Key, value, info.MinSize) 164 } 165 } 166 167 func isZero(v reflect.Value) bool { 168 switch v.Kind() { 169 case reflect.String: 170 return len(v.String()) == 0 171 case reflect.Ptr, reflect.Interface: 172 return v.IsNil() 173 case reflect.Slice: 174 return v.Len() == 0 175 case reflect.Map: 176 return v.Len() == 0 177 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 178 return v.Int() == 0 179 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 180 return v.Uint() == 0 181 case reflect.Float32, reflect.Float64: 182 return v.Float() == 0 183 case reflect.Bool: 184 return !v.Bool() 185 case reflect.Struct: 186 vt := v.Type() 187 if vt == typeTime { 188 return v.Interface().(time.Time).IsZero() 189 } 190 for i := 0; i < v.NumField(); i++ { 191 if vt.Field(i).PkgPath != "" && !vt.Field(i).Anonymous { 192 continue // Private field 193 } 194 if !isZero(v.Field(i)) { 195 return false 196 } 197 } 198 return true 199 } 200 return false 201 } 202 203 func (e *encoder) addSlice(v reflect.Value) { 204 vi := v.Interface() 205 if d, ok := vi.(D); ok { 206 for _, elem := range d { 207 e.addElem(elem.Name, reflect.ValueOf(elem.Value), false) 208 } 209 return 210 } 211 if d, ok := vi.(RawD); ok { 212 for _, elem := range d { 213 e.addElem(elem.Name, reflect.ValueOf(elem.Value), false) 214 } 215 return 216 } 217 l := v.Len() 218 et := v.Type().Elem() 219 if et == typeDocElem { 220 for i := 0; i < l; i++ { 221 elem := v.Index(i).Interface().(DocElem) 222 e.addElem(elem.Name, reflect.ValueOf(elem.Value), false) 223 } 224 return 225 } 226 if et == typeRawDocElem { 227 for i := 0; i < l; i++ { 228 elem := v.Index(i).Interface().(RawDocElem) 229 e.addElem(elem.Name, reflect.ValueOf(elem.Value), false) 230 } 231 return 232 } 233 for i := 0; i < l; i++ { 234 e.addElem(itoa(i), v.Index(i), false) 235 } 236 } 237 238 // -------------------------------------------------------------------------- 239 // Marshaling of elements in a document. 240 241 func (e *encoder) addElemName(kind byte, name string) { 242 e.addBytes(kind) 243 e.addBytes([]byte(name)...) 244 e.addBytes(0) 245 } 246 247 func (e *encoder) addElem(name string, v reflect.Value, minSize bool) { 248 249 if !v.IsValid() { 250 e.addElemName(0x0A, name) 251 return 252 } 253 254 if getter, ok := v.Interface().(Getter); ok { 255 getv, err := getter.GetBSON() 256 if err != nil { 257 panic(err) 258 } 259 e.addElem(name, reflect.ValueOf(getv), minSize) 260 return 261 } 262 263 switch v.Kind() { 264 265 case reflect.Interface: 266 e.addElem(name, v.Elem(), minSize) 267 268 case reflect.Ptr: 269 e.addElem(name, v.Elem(), minSize) 270 271 case reflect.String: 272 s := v.String() 273 switch v.Type() { 274 case typeObjectId: 275 if len(s) != 12 { 276 panic("ObjectIDs must be exactly 12 bytes long (got " + 277 strconv.Itoa(len(s)) + ")") 278 } 279 e.addElemName(0x07, name) 280 e.addBytes([]byte(s)...) 281 case typeSymbol: 282 e.addElemName(0x0E, name) 283 e.addStr(s) 284 case typeJSONNumber: 285 n := v.Interface().(json.Number) 286 if i, err := n.Int64(); err == nil { 287 e.addElemName(0x12, name) 288 e.addInt64(i) 289 } else if f, err := n.Float64(); err == nil { 290 e.addElemName(0x01, name) 291 e.addFloat64(f) 292 } else { 293 panic("failed to convert json.Number to a number: " + s) 294 } 295 default: 296 e.addElemName(0x02, name) 297 e.addStr(s) 298 } 299 300 case reflect.Float32, reflect.Float64: 301 e.addElemName(0x01, name) 302 e.addFloat64(v.Float()) 303 304 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 305 u := v.Uint() 306 if int64(u) < 0 { 307 panic("BSON has no uint64 type, and value is too large to fit correctly in an int64") 308 } else if u <= math.MaxInt32 && (minSize || v.Kind() <= reflect.Uint32) { 309 e.addElemName(0x10, name) 310 e.addInt32(int32(u)) 311 } else { 312 e.addElemName(0x12, name) 313 e.addInt64(int64(u)) 314 } 315 316 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 317 switch v.Type() { 318 case typeMongoTimestamp: 319 e.addElemName(0x11, name) 320 e.addInt64(v.Int()) 321 322 case typeOrderKey: 323 if v.Int() == int64(MaxKey) { 324 e.addElemName(0x7F, name) 325 } else { 326 e.addElemName(0xFF, name) 327 } 328 329 default: 330 i := v.Int() 331 if (minSize || v.Type().Kind() != reflect.Int64) && i >= math.MinInt32 && i <= math.MaxInt32 { 332 // It fits into an int32, encode as such. 333 e.addElemName(0x10, name) 334 e.addInt32(int32(i)) 335 } else { 336 e.addElemName(0x12, name) 337 e.addInt64(i) 338 } 339 } 340 341 case reflect.Bool: 342 e.addElemName(0x08, name) 343 if v.Bool() { 344 e.addBytes(1) 345 } else { 346 e.addBytes(0) 347 } 348 349 case reflect.Map: 350 e.addElemName(0x03, name) 351 e.addDoc(v) 352 353 case reflect.Slice: 354 vt := v.Type() 355 et := vt.Elem() 356 if et.Kind() == reflect.Uint8 { 357 e.addElemName(0x05, name) 358 e.addBinary(0x00, v.Bytes()) 359 } else if et == typeDocElem || et == typeRawDocElem { 360 e.addElemName(0x03, name) 361 e.addDoc(v) 362 } else { 363 e.addElemName(0x04, name) 364 e.addDoc(v) 365 } 366 367 case reflect.Array: 368 et := v.Type().Elem() 369 if et.Kind() == reflect.Uint8 { 370 e.addElemName(0x05, name) 371 if v.CanAddr() { 372 e.addBinary(0x00, v.Slice(0, v.Len()).Interface().([]byte)) 373 } else { 374 n := v.Len() 375 e.addInt32(int32(n)) 376 e.addBytes(0x00) 377 for i := 0; i < n; i++ { 378 el := v.Index(i) 379 e.addBytes(byte(el.Uint())) 380 } 381 } 382 } else { 383 e.addElemName(0x04, name) 384 e.addDoc(v) 385 } 386 387 case reflect.Struct: 388 switch s := v.Interface().(type) { 389 390 case Raw: 391 kind := s.Kind 392 if kind == 0x00 { 393 kind = 0x03 394 } 395 if len(s.Data) == 0 && kind != 0x06 && kind != 0x0A && kind != 0xFF && kind != 0x7F { 396 panic("Attempted to marshal empty Raw document") 397 } 398 e.addElemName(kind, name) 399 e.addBytes(s.Data...) 400 401 case Binary: 402 e.addElemName(0x05, name) 403 e.addBinary(s.Kind, s.Data) 404 405 case Decimal128: 406 e.addElemName(0x13, name) 407 e.addInt64(int64(s.l)) 408 e.addInt64(int64(s.h)) 409 410 case DBPointer: 411 e.addElemName(0x0C, name) 412 e.addStr(s.Namespace) 413 if len(s.Id) != 12 { 414 panic("ObjectIDs must be exactly 12 bytes long (got " + 415 strconv.Itoa(len(s.Id)) + ")") 416 } 417 e.addBytes([]byte(s.Id)...) 418 419 case RegEx: 420 e.addElemName(0x0B, name) 421 e.addCStr(s.Pattern) 422 e.addCStr(s.Options) 423 424 case JavaScript: 425 if s.Scope == nil { 426 e.addElemName(0x0D, name) 427 e.addStr(s.Code) 428 } else { 429 e.addElemName(0x0F, name) 430 start := e.reserveInt32() 431 e.addStr(s.Code) 432 e.addDoc(reflect.ValueOf(s.Scope)) 433 e.setInt32(start, int32(len(e.out)-start)) 434 } 435 436 case time.Time: 437 // MongoDB handles timestamps as milliseconds. 438 e.addElemName(0x09, name) 439 e.addInt64(s.Unix()*1000 + int64(s.Nanosecond()/1e6)) 440 441 case url.URL: 442 e.addElemName(0x02, name) 443 e.addStr(s.String()) 444 445 case undefined: 446 e.addElemName(0x06, name) 447 448 default: 449 e.addElemName(0x03, name) 450 e.addDoc(v) 451 } 452 453 default: 454 panic("Can't marshal " + v.Type().String() + " in a BSON document") 455 } 456 } 457 458 // -------------------------------------------------------------------------- 459 // Marshaling of base types. 460 461 func (e *encoder) addBinary(subtype byte, v []byte) { 462 if subtype == 0x02 { 463 // Wonder how that brilliant idea came to life. Obsolete, luckily. 464 e.addInt32(int32(len(v) + 4)) 465 e.addBytes(subtype) 466 e.addInt32(int32(len(v))) 467 } else { 468 e.addInt32(int32(len(v))) 469 e.addBytes(subtype) 470 } 471 e.addBytes(v...) 472 } 473 474 func (e *encoder) addStr(v string) { 475 e.addInt32(int32(len(v) + 1)) 476 e.addCStr(v) 477 } 478 479 func (e *encoder) addCStr(v string) { 480 e.addBytes([]byte(v)...) 481 e.addBytes(0) 482 } 483 484 func (e *encoder) reserveInt32() (pos int) { 485 pos = len(e.out) 486 e.addBytes(0, 0, 0, 0) 487 return pos 488 } 489 490 func (e *encoder) setInt32(pos int, v int32) { 491 e.out[pos+0] = byte(v) 492 e.out[pos+1] = byte(v >> 8) 493 e.out[pos+2] = byte(v >> 16) 494 e.out[pos+3] = byte(v >> 24) 495 } 496 497 func (e *encoder) addInt32(v int32) { 498 u := uint32(v) 499 e.addBytes(byte(u), byte(u>>8), byte(u>>16), byte(u>>24)) 500 } 501 502 func (e *encoder) addInt64(v int64) { 503 u := uint64(v) 504 e.addBytes(byte(u), byte(u>>8), byte(u>>16), byte(u>>24), 505 byte(u>>32), byte(u>>40), byte(u>>48), byte(u>>56)) 506 } 507 508 func (e *encoder) addFloat64(v float64) { 509 e.addInt64(int64(math.Float64bits(v))) 510 } 511 512 func (e *encoder) addBytes(v ...byte) { 513 e.out = append(e.out, v...) 514 }