/
bsonBigInt.go
123 lines (109 loc) · 3.19 KB
/
bsonBigInt.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
/*******************************************************************************
** @Author: Thomas Bouder <Tbouder>
** @Email: Tbouder@protonmail.com
** @Date: Monday 01 June 2020 - 20:00:19
** @Filename: bsonBigInt.go
**
** @Last modified by: Tbouder
*******************************************************************************/
package bigson
import (
"errors"
"math/big"
"go.mongodb.org/mongo-driver/bson/bsontype"
"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
)
// BigInt is a wrapper over big.Int to implement only unmarshalText
// for json decoding.
type BigInt big.Int
// Int retreive the big.Int value of a BigInt object
func (b *BigInt) Int() *big.Int {
return (*big.Int)(b)
}
// New create a new BigInt from a big.Int
func New(value *big.Int) *BigInt {
b := BigInt(*value)
return &b
}
// NewInt create a new BigInt from a int
func NewInt(value int64) *BigInt {
bigValue := big.NewInt(value)
b := BigInt(*bigValue)
return &b
}
// SetUint64 create a new BigInt from a uint64
func SetUint64(value uint64) *BigInt {
bigValue := big.NewInt(0).SetUint64(value)
b := BigInt(*bigValue)
return &b
}
// SetString create a new BigInt from a string
func SetString(value string, base int) (*BigInt, bool) {
bigValue, ok := big.NewInt(0).SetString(value, base)
if (!ok) {
return nil, false
}
b := BigInt(*bigValue)
return &b, true
}
// Sum returns the sum of old + new
func Sum(old, new *BigInt) *BigInt {
result := big.NewInt(0).Add(old.Int(), new.Int())
return New(result)
}
// Sub returns the sub of old - new
func Sub(old, new *BigInt) *BigInt {
result := big.NewInt(0).Sub(old.Int(), new.Int())
return New(result)
}
// Cmp compare x and y and resolve -1 if x < y || 0 if x == y || +1 if x > y
func Cmp(x, y *BigInt) int {
return x.Int().Cmp(y.Int())
}
// String return a representation of b as a string
func (b *BigInt) String() string {
return b.Int().String()
}
//UnmarshalText implements the text Unmarshal interface
func (b *BigInt) UnmarshalText(text []byte) (err error) {
var bigInt = new(big.Int)
err = bigInt.UnmarshalText(text)
if err != nil {
value := big.NewInt(0)
*b = BigInt(*value)
return err
}
*b = BigInt(*bigInt)
return nil
}
//MarshalText implements the text marshal interface
func (b *BigInt) MarshalText() (text []byte, err error) {
if (b == nil || b.Int().String() == `<nil>`) {
return []byte("0"), nil
}
return []byte(b.Int().String()), nil
}
//MarshalBSONValue implements the bson.ValueMarshaler interface
func (b *BigInt) MarshalBSONValue() (bsontype.Type, []byte, error) {
if (b == nil || b.Int().String() == `<nil>`) {
return bsontype.String, bsoncore.AppendString(nil, "0"), nil
}
return bsontype.String, bsoncore.AppendString(nil, b.Int().String()), nil
}
// UnmarshalBSONValue is an interface implemented that can unmarshal a BSON
// value representation of themselves.
func (b *BigInt) UnmarshalBSONValue(tpe bsontype.Type, data []byte) error {
str, _, ok := bsoncore.ReadString(data)
if !ok {
return errors.New(`impossible to read data as string`)
}
var bigInt = new(big.Int)
bigIntByte, ok := bigInt.SetString(str, 10)
if !ok {
bigIntByte = big.NewInt(0)
*b = BigInt(*bigIntByte)
return nil
}
*b = BigInt(*bigIntByte)
return nil
}