1 // Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 22 package uuid
23 24 import (
25 "database/sql"
26 "database/sql/driver"
27 "fmt"
28 )
29 30 var _ driver.Valuer = UUID{}
31 var _ sql.Scanner = (*UUID)(nil)
32 33 // Value implements the driver.Valuer interface.
34 func (u UUID) Value() (driver.Value, error) {
35 return u.String(), nil
36 }
37 38 // Scan implements the sql.Scanner interface.
39 // A 16-byte slice will be handled by UnmarshalBinary, while
40 // a longer byte slice or a string will be handled by UnmarshalText.
41 func (u *UUID) Scan(src interface{}) error {
42 switch src := src.(type) {
43 case UUID: // support gorm convert from UUID to NullUUID
44 *u = src
45 return nil
46 47 case []byte:
48 if len(src) == Size {
49 return u.UnmarshalBinary(src)
50 }
51 return u.UnmarshalText(src)
52 53 case string:
54 uu, err := FromString(src)
55 *u = uu
56 return err
57 }
58 59 return fmt.Errorf("uuid: cannot convert %T to UUID", src)
60 }
61 62 // NullUUID can be used with the standard sql package to represent a
63 // UUID value that can be NULL in the database.
64 type NullUUID struct {
65 UUID UUID
66 Valid bool
67 }
68 69 // Value implements the driver.Valuer interface.
70 func (u NullUUID) Value() (driver.Value, error) {
71 if !u.Valid {
72 return nil, nil
73 }
74 // Delegate to UUID Value function
75 return u.UUID.Value()
76 }
77 78 // Scan implements the sql.Scanner interface.
79 func (u *NullUUID) Scan(src interface{}) error {
80 if src == nil {
81 u.UUID, u.Valid = Nil, false
82 return nil
83 }
84 85 // Delegate to UUID Scan function
86 u.Valid = true
87 return u.UUID.Scan(src)
88 }
89 90 var nullJSON = []byte("null")
91 92 // MarshalJSON marshals the NullUUID as null or the nested UUID
93 func (u NullUUID) MarshalJSON() ([]byte, error) {
94 if !u.Valid {
95 return nullJSON, nil
96 }
97 var buf [38]byte
98 buf[0] = '"'
99 encodeCanonical(buf[1:37], u.UUID)
100 buf[37] = '"'
101 return buf[:], nil
102 }
103 104 // UnmarshalJSON unmarshals a NullUUID
105 func (u *NullUUID) UnmarshalJSON(b []byte) error {
106 if string(b) == "null" {
107 u.UUID, u.Valid = Nil, false
108 return nil
109 }
110 if n := len(b); n >= 2 && b[0] == '"' {
111 b = b[1 : n-1]
112 }
113 err := u.UUID.UnmarshalText(b)
114 u.Valid = (err == nil)
115 return err
116 }
117