aboutsummaryrefslogtreecommitdiff
path: root/null.go
blob: 95bb632880917bf57071f18fb6eaded87f3da6d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright 2021 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
	"bytes"
	"database/sql/driver"
	"encoding/json"
	"fmt"
)

// NullUUID represents a UUID that may be null.
// NullUUID implements the Scanner interface so
// it can be used as a scan destination:
//
//  var u uuid.NullUUID
//  err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u)
//  ...
//  if u.Valid {
//     // use u.UUID
//  } else {
//     // NULL value
//  }
//
type NullUUID struct {
	UUID  UUID
	Valid bool // Valid is true if UUID is not NULL
}

// Scan implements the Scanner interface.
func (nu *NullUUID) Scan(value interface{}) error {
	if value == nil {
		nu.UUID, nu.Valid = Nil, false
		return nil
	}

	err := nu.UUID.Scan(value)
	if err != nil {
		nu.Valid = false
		return err
	}

	nu.Valid = true
	return nil
}

// Value implements the driver Valuer interface.
func (nu NullUUID) Value() (driver.Value, error) {
	if !nu.Valid {
		return nil, nil
	}
	// Delegate to UUID Value function
	return nu.UUID.Value()
}

// MarshalBinary implements encoding.BinaryMarshaler.
func (nu NullUUID) MarshalBinary() ([]byte, error) {
	if nu.Valid {
		return nu.UUID[:], nil
	}

	return []byte(nil), nil
}

// UnmarshalBinary implements encoding.BinaryUnmarshaler.
func (nu *NullUUID) UnmarshalBinary(data []byte) error {
	if len(data) != 16 {
		return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
	}
	copy(nu.UUID[:], data)
	nu.Valid = true
	return nil
}

// MarshalText implements encoding.TextMarshaler.
func (nu NullUUID) MarshalText() ([]byte, error) {
	if nu.Valid {
		return nu.UUID.MarshalText()
	}

	return []byte{110, 117, 108, 108}, nil
}

// UnmarshalText implements encoding.TextUnmarshaler.
func (nu *NullUUID) UnmarshalText(data []byte) error {
	id, err := ParseBytes(data)
	if err != nil {
		nu.Valid = false
		return err
	}
	nu.UUID = id
	nu.Valid = true
	return nil
}

// MarshalJSON implements json.Marshaler.
func (nu NullUUID) MarshalJSON() ([]byte, error) {
	if nu.Valid {
		return json.Marshal(nu.UUID)
	}

	return json.Marshal(nil)
}

// UnmarshalJSON implements json.Unmarshaler.
func (nu *NullUUID) UnmarshalJSON(data []byte) error {
	null := []byte{110, 117, 108, 108}
	if bytes.Equal(data, null) {
		return nil // valid null UUID
	}

	var u UUID
	// tossing as we know u is valid
	_ = json.Unmarshal(data, &u)
	nu.Valid = true
	nu.UUID = u
	return nil
}