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