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  }