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  }