-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8237093
commit a06e714
Showing
4 changed files
with
117 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package bson | ||
|
||
import ( | ||
"crypto/rand" | ||
"encoding/hex" | ||
"errors" | ||
"fmt" | ||
mathrand "math/rand" | ||
"sync/atomic" | ||
"time" | ||
) | ||
|
||
var ( | ||
_ Marshaler = &ObjectID{} | ||
_ Unmarshaler = &ObjectID{} | ||
) | ||
|
||
var ErrBadObjectID = errors.New("provided input is not a valid ObjectID") | ||
|
||
// ObjectID represents BSON object ID. | ||
type ObjectID [12]byte | ||
|
||
// NewObjectID returns a new ObjectID. | ||
func NewObjectID() ObjectID { | ||
return NewObjectIDWithTime(time.Now()) | ||
} | ||
|
||
// NewObjectIDWithTime returns a new ObjectID. | ||
func NewObjectIDWithTime(t time.Time) ObjectID { | ||
ts := uint32(t.UTC().Unix()) | ||
c := objectIDCounter.Add(1) | ||
|
||
var oid ObjectID | ||
oid[0] = byte(ts >> 24) | ||
oid[1] = byte(ts >> 16) | ||
oid[2] = byte(ts >> 8) | ||
oid[3] = byte(ts) | ||
|
||
oid[4] = procUniqueID[0] | ||
oid[5] = procUniqueID[1] | ||
oid[6] = procUniqueID[2] | ||
oid[7] = procUniqueID[3] | ||
oid[8] = procUniqueID[4] | ||
|
||
oid[9] = byte(c >> 16) | ||
oid[10] = byte(c >> 8) | ||
oid[11] = byte(c) | ||
return oid | ||
} | ||
|
||
// String returns a hex string representation of the id. | ||
// Example: ObjectIdHex('64d526fa37931c1e97eea90f'). | ||
func (oid ObjectID) String() string { | ||
return fmt.Sprintf(`ObjectIdHex('%x')`, string(oid[:])) | ||
} | ||
|
||
func (oid *ObjectID) MarshalBSON() ([]byte, error) { | ||
b := make([]byte, len(oid)) | ||
copy(b, oid[:]) | ||
return b, nil | ||
} | ||
|
||
func (oid *ObjectID) UnmarshalBSON(b []byte) error { | ||
switch len(b) { | ||
case 12: | ||
copy(oid[:], b) | ||
return nil | ||
case 24: | ||
n, err := hex.Decode(oid[:], b) | ||
if n != 24 { | ||
panic("unreachable") | ||
} | ||
return err | ||
default: | ||
return ErrBadObjectID | ||
} | ||
} | ||
|
||
var ( | ||
procUniqueID [5]byte | ||
objectIDCounter atomic.Uint32 | ||
) | ||
|
||
func init() { | ||
must(rand.Read(procUniqueID[:])) | ||
objectIDCounter.Store(mathrand.Uint32()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package bson | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func TestObjectID(t *testing.T) { | ||
oid := ObjectID([12]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}) | ||
|
||
mustEqual(t, oid.String(), "ObjectIdHex('0102030405060708090a0b0c')") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package bson | ||
|
||
func must[T any](v T, err error) T { | ||
if err != nil { | ||
panic(err) | ||
} | ||
return v | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package bson | ||
|
||
import "testing" | ||
|
||
func mustEqual[T comparable](tb testing.TB, have, want T) { | ||
tb.Helper() | ||
|
||
if have != want { | ||
tb.Fatalf("\nhave: %+v\nwant: %+v\n", have, want) | ||
} | ||
} |