github.com/seeker-insurance/kit@v0.0.13/db/null/int.go (about) 1 package null 2 3 import ( 4 "database/sql" 5 "encoding/json" 6 "fmt" 7 "reflect" 8 "strconv" 9 ) 10 11 // Int is an nullable int64. 12 // It does not consider zero values to be null. 13 // It will decode to null, not zero, if null. 14 type Int struct { 15 sql.NullInt64 16 } 17 18 // NewInt creates a new Int 19 func NewInt(i int64, valid bool) Int { 20 return Int{ 21 NullInt64: sql.NullInt64{ 22 Int64: i, 23 Valid: valid, 24 }, 25 } 26 } 27 28 // NewTimeAuto creates a new Int setting valid to false if i is zero 29 func NewIntAuto(i int64) Int { 30 return NewInt(i, i != 0) 31 } 32 33 // IntFrom creates a new Int that will always be valid. 34 func IntFrom(i int64) Int { 35 return NewInt(i, true) 36 } 37 38 // IntFromPtr creates a new Int that be null if i is nil. 39 func IntFromPtr(i *int64) Int { 40 if i == nil { 41 return NewInt(0, false) 42 } 43 return NewInt(*i, true) 44 } 45 46 // ValueOrZero returns the inner value if valid, otherwise zero. 47 func (i Int) ValueOrZero() int64 { 48 if !i.Valid { 49 return 0 50 } 51 return i.Int64 52 } 53 54 // UnmarshalJSON implements json.Unmarshaler. 55 // It supports number and null input. 56 // 0 will not be considered a null Int. 57 // It also supports unmarshalling a sql.NullInt64. 58 func (i *Int) UnmarshalJSON(data []byte) error { 59 var err error 60 var v interface{} 61 if err = json.Unmarshal(data, &v); err != nil { 62 return err 63 } 64 switch x := v.(type) { 65 case float64: 66 // Unmarshal again, directly to int64, to avoid intermediate float64 67 err = json.Unmarshal(data, &i.Int64) 68 case string: 69 str := string(x) 70 if len(str) == 0 { 71 i.Valid = false 72 return nil 73 } 74 i.Int64, err = strconv.ParseInt(str, 10, 64) 75 case map[string]interface{}: 76 err = json.Unmarshal(data, &i.NullInt64) 77 case nil: 78 i.Valid = false 79 return nil 80 default: 81 err = fmt.Errorf("json: cannot unmarshal %v into Go value of type null.Int", reflect.TypeOf(v).Name()) 82 } 83 i.Valid = err == nil 84 return err 85 } 86 87 // UnmarshalText implements encoding.TextUnmarshaler. 88 // It will unmarshal to a null Int if the input is a blank or not an integer. 89 // It will return an error if the input is not an integer, blank, or "null". 90 func (i *Int) UnmarshalText(text []byte) error { 91 str := string(text) 92 if str == "" || str == "null" { 93 i.Valid = false 94 return nil 95 } 96 var err error 97 i.Int64, err = strconv.ParseInt(string(text), 10, 64) 98 i.Valid = err == nil 99 return err 100 } 101 102 // MarshalJSON implements json.Marshaler. 103 // It will encode null if this Int is null. 104 func (i Int) MarshalJSON() ([]byte, error) { 105 if !i.Valid { 106 return []byte("null"), nil 107 } 108 return []byte(strconv.FormatInt(i.Int64, 10)), nil 109 } 110 111 // MarshalText implements encoding.TextMarshaler. 112 // It will encode a blank string if this Int is null. 113 func (i Int) MarshalText() ([]byte, error) { 114 if !i.Valid { 115 return []byte{}, nil 116 } 117 return []byte(strconv.FormatInt(i.Int64, 10)), nil 118 } 119 120 // SetValid changes this Int's value and also sets it to be non-null. 121 func (i *Int) SetValid(n int64) { 122 i.Int64 = n 123 i.Valid = true 124 } 125 126 // Ptr returns a pointer to this Int's value, or a nil pointer if this Int is null. 127 func (i Int) Ptr() *int64 { 128 if !i.Valid { 129 return nil 130 } 131 return &i.Int64 132 } 133 134 // IsZero returns true for invalid Ints, for future omitempty support (Go 1.4?) 135 // A non-null Int with a 0 value will not be considered zero. 136 func (i Int) IsZero() bool { 137 return !i.Valid 138 }