primitive.go raw

   1  // Copyright (C) MongoDB, Inc. 2017-present.
   2  //
   3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
   4  // not use this file except in compliance with the License. You may obtain
   5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
   6  
   7  // Package primitive contains types similar to Go primitives for BSON types that do not have direct
   8  // Go primitive representations.
   9  package primitive // import "go.mongodb.org/mongo-driver/bson/primitive"
  10  
  11  import (
  12  	"bytes"
  13  	"encoding/json"
  14  	"fmt"
  15  	"time"
  16  )
  17  
  18  // Binary represents a BSON binary value.
  19  type Binary struct {
  20  	Subtype byte
  21  	Data    []byte
  22  }
  23  
  24  // Equal compares bp to bp2 and returns true if they are equal.
  25  func (bp Binary) Equal(bp2 Binary) bool {
  26  	if bp.Subtype != bp2.Subtype {
  27  		return false
  28  	}
  29  	return bytes.Equal(bp.Data, bp2.Data)
  30  }
  31  
  32  // IsZero returns if bp is the empty Binary.
  33  func (bp Binary) IsZero() bool {
  34  	return bp.Subtype == 0 && len(bp.Data) == 0
  35  }
  36  
  37  // Undefined represents the BSON undefined value type.
  38  type Undefined struct{}
  39  
  40  // DateTime represents the BSON datetime value.
  41  type DateTime int64
  42  
  43  var _ json.Marshaler = DateTime(0)
  44  var _ json.Unmarshaler = (*DateTime)(nil)
  45  
  46  // MarshalJSON marshal to time type.
  47  func (d DateTime) MarshalJSON() ([]byte, error) {
  48  	return json.Marshal(d.Time().UTC())
  49  }
  50  
  51  // UnmarshalJSON creates a primitive.DateTime from a JSON string.
  52  func (d *DateTime) UnmarshalJSON(data []byte) error {
  53  	// Ignore "null" to keep parity with the time.Time type and the standard library. Decoding "null" into a non-pointer
  54  	// DateTime field will leave the field unchanged. For pointer values, the encoding/json will set the pointer to nil
  55  	// and will not defer to the UnmarshalJSON hook.
  56  	if string(data) == "null" {
  57  		return nil
  58  	}
  59  
  60  	var tempTime time.Time
  61  	if err := json.Unmarshal(data, &tempTime); err != nil {
  62  		return err
  63  	}
  64  
  65  	*d = NewDateTimeFromTime(tempTime)
  66  	return nil
  67  }
  68  
  69  // Time returns the date as a time type.
  70  func (d DateTime) Time() time.Time {
  71  	return time.Unix(int64(d)/1000, int64(d)%1000*1000000)
  72  }
  73  
  74  // NewDateTimeFromTime creates a new DateTime from a Time.
  75  func NewDateTimeFromTime(t time.Time) DateTime {
  76  	return DateTime(t.Unix()*1e3 + int64(t.Nanosecond())/1e6)
  77  }
  78  
  79  // Null represents the BSON null value.
  80  type Null struct{}
  81  
  82  // Regex represents a BSON regex value.
  83  type Regex struct {
  84  	Pattern string
  85  	Options string
  86  }
  87  
  88  func (rp Regex) String() string {
  89  	return fmt.Sprintf(`{"pattern": "%s", "options": "%s"}`, rp.Pattern, rp.Options)
  90  }
  91  
  92  // Equal compares rp to rp2 and returns true if they are equal.
  93  func (rp Regex) Equal(rp2 Regex) bool {
  94  	return rp.Pattern == rp2.Pattern && rp.Options == rp2.Options
  95  }
  96  
  97  // IsZero returns if rp is the empty Regex.
  98  func (rp Regex) IsZero() bool {
  99  	return rp.Pattern == "" && rp.Options == ""
 100  }
 101  
 102  // DBPointer represents a BSON dbpointer value.
 103  type DBPointer struct {
 104  	DB      string
 105  	Pointer ObjectID
 106  }
 107  
 108  func (d DBPointer) String() string {
 109  	return fmt.Sprintf(`{"db": "%s", "pointer": "%s"}`, d.DB, d.Pointer)
 110  }
 111  
 112  // Equal compares d to d2 and returns true if they are equal.
 113  func (d DBPointer) Equal(d2 DBPointer) bool {
 114  	return d == d2
 115  }
 116  
 117  // IsZero returns if d is the empty DBPointer.
 118  func (d DBPointer) IsZero() bool {
 119  	return d.DB == "" && d.Pointer.IsZero()
 120  }
 121  
 122  // JavaScript represents a BSON JavaScript code value.
 123  type JavaScript string
 124  
 125  // Symbol represents a BSON symbol value.
 126  type Symbol string
 127  
 128  // CodeWithScope represents a BSON JavaScript code with scope value.
 129  type CodeWithScope struct {
 130  	Code  JavaScript
 131  	Scope interface{}
 132  }
 133  
 134  func (cws CodeWithScope) String() string {
 135  	return fmt.Sprintf(`{"code": "%s", "scope": %v}`, cws.Code, cws.Scope)
 136  }
 137  
 138  // Timestamp represents a BSON timestamp value.
 139  type Timestamp struct {
 140  	T uint32
 141  	I uint32
 142  }
 143  
 144  // After reports whether the time instant tp is after tp2.
 145  func (tp Timestamp) After(tp2 Timestamp) bool {
 146  	return tp.T > tp2.T || (tp.T == tp2.T && tp.I > tp2.I)
 147  }
 148  
 149  // Before reports whether the time instant tp is before tp2.
 150  func (tp Timestamp) Before(tp2 Timestamp) bool {
 151  	return tp.T < tp2.T || (tp.T == tp2.T && tp.I < tp2.I)
 152  }
 153  
 154  // Equal compares tp to tp2 and returns true if they are equal.
 155  func (tp Timestamp) Equal(tp2 Timestamp) bool {
 156  	return tp.T == tp2.T && tp.I == tp2.I
 157  }
 158  
 159  // IsZero returns if tp is the zero Timestamp.
 160  func (tp Timestamp) IsZero() bool {
 161  	return tp.T == 0 && tp.I == 0
 162  }
 163  
 164  // Compare compares the time instant tp with tp2. If tp is before tp2, it returns -1; if tp is after
 165  // tp2, it returns +1; if they're the same, it returns 0.
 166  func (tp Timestamp) Compare(tp2 Timestamp) int {
 167  	switch {
 168  	case tp.Equal(tp2):
 169  		return 0
 170  	case tp.Before(tp2):
 171  		return -1
 172  	default:
 173  		return +1
 174  	}
 175  }
 176  
 177  // CompareTimestamp compares the time instant tp with tp2. If tp is before tp2, it returns -1; if tp is after
 178  // tp2, it returns +1; if they're the same, it returns 0.
 179  //
 180  // Deprecated: Use Timestamp.Compare instead.
 181  func CompareTimestamp(tp, tp2 Timestamp) int {
 182  	return tp.Compare(tp2)
 183  }
 184  
 185  // MinKey represents the BSON minkey value.
 186  type MinKey struct{}
 187  
 188  // MaxKey represents the BSON maxkey value.
 189  type MaxKey struct{}
 190  
 191  // D is an ordered representation of a BSON document. This type should be used when the order of the elements matters,
 192  // such as MongoDB command documents. If the order of the elements does not matter, an M should be used instead.
 193  //
 194  // Example usage:
 195  //
 196  //	bson.D{{"foo", "bar"}, {"hello", "world"}, {"pi", 3.14159}}
 197  type D []E
 198  
 199  // Map creates a map from the elements of the D.
 200  //
 201  // Deprecated: Converting directly from a D to an M will not be supported in Go Driver 2.0. Instead,
 202  // users should marshal the D to BSON using bson.Marshal and unmarshal it to M using bson.Unmarshal.
 203  func (d D) Map() M {
 204  	m := make(M, len(d))
 205  	for _, e := range d {
 206  		m[e.Key] = e.Value
 207  	}
 208  	return m
 209  }
 210  
 211  // E represents a BSON element for a D. It is usually used inside a D.
 212  type E struct {
 213  	Key   string
 214  	Value interface{}
 215  }
 216  
 217  // M is an unordered representation of a BSON document. This type should be used when the order of the elements does not
 218  // matter. This type is handled as a regular map[string]interface{} when encoding and decoding. Elements will be
 219  // serialized in an undefined, random order. If the order of the elements matters, a D should be used instead.
 220  //
 221  // Example usage:
 222  //
 223  //	bson.M{"foo": "bar", "hello": "world", "pi": 3.14159}
 224  type M map[string]interface{}
 225  
 226  // An A is an ordered representation of a BSON array.
 227  //
 228  // Example usage:
 229  //
 230  //	bson.A{"bar", "world", 3.14159, bson.D{{"qux", 12345}}}
 231  type A []interface{}
 232