null.go

  1// Copyright 2021 Google Inc.  All rights reserved.
  2// Use of this source code is governed by a BSD-style
  3// license that can be found in the LICENSE file.
  4
  5package uuid
  6
  7import (
  8	"bytes"
  9	"database/sql/driver"
 10	"encoding/json"
 11	"fmt"
 12)
 13
 14var jsonNull = []byte("null")
 15
 16// NullUUID represents a UUID that may be null.
 17// NullUUID implements the SQL driver.Scanner interface so
 18// it can be used as a scan destination:
 19//
 20//  var u uuid.NullUUID
 21//  err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u)
 22//  ...
 23//  if u.Valid {
 24//     // use u.UUID
 25//  } else {
 26//     // NULL value
 27//  }
 28//
 29type NullUUID struct {
 30	UUID  UUID
 31	Valid bool // Valid is true if UUID is not NULL
 32}
 33
 34// Scan implements the SQL driver.Scanner interface.
 35func (nu *NullUUID) Scan(value interface{}) error {
 36	if value == nil {
 37		nu.UUID, nu.Valid = Nil, false
 38		return nil
 39	}
 40
 41	err := nu.UUID.Scan(value)
 42	if err != nil {
 43		nu.Valid = false
 44		return err
 45	}
 46
 47	nu.Valid = true
 48	return nil
 49}
 50
 51// Value implements the driver Valuer interface.
 52func (nu NullUUID) Value() (driver.Value, error) {
 53	if !nu.Valid {
 54		return nil, nil
 55	}
 56	// Delegate to UUID Value function
 57	return nu.UUID.Value()
 58}
 59
 60// MarshalBinary implements encoding.BinaryMarshaler.
 61func (nu NullUUID) MarshalBinary() ([]byte, error) {
 62	if nu.Valid {
 63		return nu.UUID[:], nil
 64	}
 65
 66	return []byte(nil), nil
 67}
 68
 69// UnmarshalBinary implements encoding.BinaryUnmarshaler.
 70func (nu *NullUUID) UnmarshalBinary(data []byte) error {
 71	if len(data) != 16 {
 72		return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
 73	}
 74	copy(nu.UUID[:], data)
 75	nu.Valid = true
 76	return nil
 77}
 78
 79// MarshalText implements encoding.TextMarshaler.
 80func (nu NullUUID) MarshalText() ([]byte, error) {
 81	if nu.Valid {
 82		return nu.UUID.MarshalText()
 83	}
 84
 85	return jsonNull, nil
 86}
 87
 88// UnmarshalText implements encoding.TextUnmarshaler.
 89func (nu *NullUUID) UnmarshalText(data []byte) error {
 90	id, err := ParseBytes(data)
 91	if err != nil {
 92		nu.Valid = false
 93		return err
 94	}
 95	nu.UUID = id
 96	nu.Valid = true
 97	return nil
 98}
 99
100// MarshalJSON implements json.Marshaler.
101func (nu NullUUID) MarshalJSON() ([]byte, error) {
102	if nu.Valid {
103		return json.Marshal(nu.UUID)
104	}
105
106	return jsonNull, nil
107}
108
109// UnmarshalJSON implements json.Unmarshaler.
110func (nu *NullUUID) UnmarshalJSON(data []byte) error {
111	if bytes.Equal(data, jsonNull) {
112		*nu = NullUUID{}
113		return nil // valid null UUID
114	}
115	err := json.Unmarshal(data, &nu.UUID)
116	nu.Valid = err == nil
117	return err
118}