github.com/seeker-insurance/kit@v0.0.13/db/null/zero/int.go (about)

     1  package zero
     2  
     3  import (
     4  	"database/sql"
     5  	"encoding/json"
     6  	"fmt"
     7  	"reflect"
     8  	"strconv"
     9  )
    10  
    11  // Int is a nullable int64.
    12  // JSON marshals to zero if null.
    13  // Considered null to SQL if zero.
    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  // IntFrom creates a new Int that will be null if zero.
    29  func IntFrom(i int64) Int {
    30  	return NewInt(i, i != 0)
    31  }
    32  
    33  // IntFromPtr creates a new Int that be null if i is nil.
    34  func IntFromPtr(i *int64) Int {
    35  	if i == nil {
    36  		return NewInt(0, false)
    37  	}
    38  	n := NewInt(*i, true)
    39  	return n
    40  }
    41  
    42  // UnmarshalJSON implements json.Unmarshaler.
    43  // It supports number and null input.
    44  // 0 will be considered a null Int.
    45  // It also supports unmarshalling a sql.NullInt64.
    46  func (i *Int) UnmarshalJSON(data []byte) error {
    47  	var err error
    48  	var v interface{}
    49  	if err = json.Unmarshal(data, &v); err != nil {
    50  		return err
    51  	}
    52  	switch x := v.(type) {
    53  	case float64:
    54  		// Unmarshal again, directly to int64, to avoid intermediate float64
    55  		err = json.Unmarshal(data, &i.Int64)
    56  	case string:
    57  		str := string(x)
    58  		if len(str) == 0 {
    59  			i.Valid = false
    60  			return nil
    61  		}
    62  		i.Int64, err = strconv.ParseInt(str, 10, 64)
    63  	case map[string]interface{}:
    64  		err = json.Unmarshal(data, &i.NullInt64)
    65  	case nil:
    66  		i.Valid = false
    67  		return nil
    68  	default:
    69  		err = fmt.Errorf("json: cannot unmarshal %v into Go value of type zero.Int", reflect.TypeOf(v).Name())
    70  	}
    71  	i.Valid = (err == nil) && (i.Int64 != 0)
    72  	return err
    73  }
    74  
    75  // UnmarshalText implements encoding.TextUnmarshaler.
    76  // It will unmarshal to a null Int if the input is a blank, zero, or not an integer.
    77  // It will return an error if the input is not an integer, blank, or "null".
    78  func (i *Int) UnmarshalText(text []byte) error {
    79  	str := string(text)
    80  	if str == "" || str == "null" {
    81  		i.Valid = false
    82  		return nil
    83  	}
    84  	var err error
    85  	i.Int64, err = strconv.ParseInt(string(text), 10, 64)
    86  	i.Valid = (err == nil) && (i.Int64 != 0)
    87  	return err
    88  }
    89  
    90  // MarshalJSON implements json.Marshaler.
    91  // It will encode 0 if this Int is null.
    92  func (i Int) MarshalJSON() ([]byte, error) {
    93  	n := i.Int64
    94  	if !i.Valid {
    95  		n = 0
    96  	}
    97  	return []byte(strconv.FormatInt(n, 10)), nil
    98  }
    99  
   100  // MarshalText implements encoding.TextMarshaler.
   101  // It will encode a zero if this Int is null.
   102  func (i Int) MarshalText() ([]byte, error) {
   103  	n := i.Int64
   104  	if !i.Valid {
   105  		n = 0
   106  	}
   107  	return []byte(strconv.FormatInt(n, 10)), nil
   108  }
   109  
   110  // SetValid changes this Int's value and also sets it to be non-null.
   111  func (i *Int) SetValid(n int64) {
   112  	i.Int64 = n
   113  	i.Valid = true
   114  }
   115  
   116  // Ptr returns a pointer to this Int's value, or a nil pointer if this Int is null.
   117  func (i Int) Ptr() *int64 {
   118  	if !i.Valid {
   119  		return nil
   120  	}
   121  	return &i.Int64
   122  }
   123  
   124  // IsZero returns true for null or zero Ints, for future omitempty support (Go 1.4?)
   125  func (i Int) IsZero() bool {
   126  	return !i.Valid || i.Int64 == 0
   127  }