Files
realy/json/signed.go

66 lines
1.6 KiB
Go

package json
import (
"golang.org/x/exp/constraints"
"realy.lol/chk"
"realy.lol/ints"
)
// Signed integers can be negative and thus a `-` prefix.
//
// Initialize these values as follows:
//
// num := &json.Signed{}
//
// to get a default value which is zero.
//
// Technically we are supporting negative numbers here but in fact in nostr message encodings
// there is no such thing as any negative integers, nor floating point, but this ensures
// if there is ever need for negative values they are supported. For the most part this will be
// used for timestamps.
//
// There is a NewSigned function that accepts any type of generic signed integer value and
// automatically converts it to the biggest type that is used in runtime.
type Signed struct{ V int64 }
// NewSigned creates a new Signed integer value.
func NewSigned[V constraints.Signed](i V) *Signed { return &Signed{int64(i)} }
// Marshal the Signed into a byte string in standard JSON formatting.
func (s *Signed) Marshal(dst []byte) (b []byte) {
b = dst
v := s.V
// we don't add implicit + to the front, only negative
if v < 0 {
b = append(b, '-')
v = -v
}
b = ints.New(v).Marshal(b)
return
}
// Unmarshal a Signed in JSON form into its value.
func (s *Signed) Unmarshal(dst []byte) (rem []byte, err error) {
rem = dst
var neg bool
// first byte can be `-` or `+`
if rem[0] == '-' {
neg = true
// advance to next
rem = rem[1:]
} else if rem[0] == '+' {
rem = rem[1:]
}
n := &ints.T{}
if rem, err = n.Unmarshal(rem); chk.E(err) {
return
}
s.V = int64(n.N)
// flip sign if neg
if neg {
s.V = -s.V
}
return
}