-
Notifications
You must be signed in to change notification settings - Fork 2
/
bsonproto.go
155 lines (144 loc) · 3.65 KB
/
bsonproto.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Package bsonproto provides primitives for encoding and decoding of BSON.
package bsonproto
import (
"errors"
"fmt"
"time"
)
// ScalarType represents a BSON scalar type.
//
// CString is not included as it is not a real BSON type.
type ScalarType interface {
float64 | string | Binary | ObjectID | bool | time.Time | NullType | Regex | int32 | Timestamp | int64 | Decimal128
}
// Size returns a size of the encoding of value v in bytes.
func Size[T ScalarType](v T) int {
return SizeAny(v)
}
// SizeAny returns a size of the encoding of value v in bytes.
//
// It panics if v is not a [ScalarType] (including CString).
func SizeAny(v any) int {
switch v := v.(type) {
case float64:
return SizeFloat64
case string:
return SizeString(v)
case Binary:
return SizeBinary(v)
case ObjectID:
return SizeObjectID
case bool:
return SizeBool
case time.Time:
return SizeTime
case NullType:
return 0
case Regex:
return SizeRegex(v)
case int32:
return SizeInt32
case Timestamp:
return SizeTimestamp
case int64:
return SizeInt64
case Decimal128:
return SizeDecimal128
default:
panic(fmt.Sprintf("unsupported type %T", v))
}
}
// Encode encodes value v into b.
//
// b must be at least Size(v) bytes long; otherwise, Encode will panic.
// Only b[0:Size(v)] bytes are modified.
func Encode[T ScalarType](b []byte, v T) {
EncodeAny(b, v)
}
// EncodeAny encodes value v into b.
//
// b must be at least Size(v) bytes long; otherwise, EncodeAny will panic.
// Only b[0:Size(v)] bytes are modified.
//
// It panics if v is not a [ScalarType] (including CString).
func EncodeAny(b []byte, v any) {
switch v := v.(type) {
case float64:
EncodeFloat64(b, v)
case string:
EncodeString(b, v)
case Binary:
EncodeBinary(b, v)
case ObjectID:
EncodeObjectID(b, v)
case bool:
EncodeBool(b, v)
case time.Time:
EncodeTime(b, v)
case NullType:
// nothing
case Regex:
EncodeRegex(b, v)
case int32:
EncodeInt32(b, v)
case Timestamp:
EncodeTimestamp(b, v)
case int64:
EncodeInt64(b, v)
case Decimal128:
EncodeDecimal128(b, v)
default:
panic(fmt.Sprintf("unsupported type %T", v))
}
}
// Decode decodes value from b into v.
//
// If there is not enough bytes, Decode will return a wrapped [ErrDecodeShortInput].
// If the input is otherwise invalid, a wrapped [ErrDecodeInvalidInput] is returned.
func Decode[T ScalarType](b []byte, v *T) error {
return DecodeAny(b, v)
}
// DecodeAny decodes value from b into v.
//
// If there is not enough bytes, DecodeAny will return a wrapped [ErrDecodeShortInput].
// If the input is otherwise invalid, a wrapped [ErrDecodeInvalidInput] is returned.
//
// It panics if v is not a pointer to [ScalarType] (including CString).
func DecodeAny(b []byte, v any) error {
var err error
switch v := v.(type) {
case *float64:
*v, err = DecodeFloat64(b)
case *string:
*v, err = DecodeString(b)
case *Binary:
*v, err = DecodeBinary(b)
case *ObjectID:
*v, err = DecodeObjectID(b)
case *bool:
*v, err = DecodeBool(b)
case *time.Time:
*v, err = DecodeTime(b)
case *NullType:
// nothing
case *Regex:
*v, err = DecodeRegex(b)
case *int32:
*v, err = DecodeInt32(b)
case *Timestamp:
*v, err = DecodeTimestamp(b)
case *int64:
*v, err = DecodeInt64(b)
case *Decimal128:
*v, err = DecodeDecimal128(b)
default:
panic(fmt.Sprintf("unsupported type %T", v))
}
return err
}
var (
// ErrDecodeShortInput is returned wrapped by Decode functions if the input bytes slice is too short.
ErrDecodeShortInput = errors.New("bsonproto: short input")
// ErrDecodeInvalidInput is returned wrapped by Decode functions if the input bytes slice is invalid.
ErrDecodeInvalidInput = errors.New("bsonproto: invalid input")
)