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 "bytes" 26 "database/sql/driver" 27 "encoding/json" 28 "fmt" 29 ) 30 31 // Value implements the driver.Valuer interface. 32 func (u UUID) Value() (driver.Value, error) { 33 return u.String(), nil 34 } 35 36 // Scan implements the sql.Scanner interface. 37 // A 16-byte slice will be handled by UnmarshalBinary, while 38 // a longer byte slice or a string will be handled by UnmarshalText. 39 func (u *UUID) Scan(src interface{}) error { 40 switch src := src.(type) { 41 case UUID: // support gorm convert from UUID to NullUUID 42 *u = src 43 return nil 44 45 case []byte: 46 if len(src) == Size { 47 return u.UnmarshalBinary(src) 48 } 49 return u.UnmarshalText(src) 50 51 case string: 52 return u.UnmarshalText([]byte(src)) 53 } 54 55 return fmt.Errorf("uuid: cannot convert %T to UUID", src) 56 } 57 58 // NullUUID can be used with the standard sql package to represent a 59 // UUID value that can be NULL in the database. 60 type NullUUID struct { 61 UUID UUID 62 Valid bool 63 } 64 65 // Value implements the driver.Valuer interface. 66 func (u NullUUID) Value() (driver.Value, error) { 67 if !u.Valid { 68 return nil, nil 69 } 70 // Delegate to UUID Value function 71 return u.UUID.Value() 72 } 73 74 // Scan implements the sql.Scanner interface. 75 func (u *NullUUID) Scan(src interface{}) error { 76 if src == nil { 77 u.UUID, u.Valid = Nil, false 78 return nil 79 } 80 81 // Delegate to UUID Scan function 82 u.Valid = true 83 return u.UUID.Scan(src) 84 } 85 86 // MarshalJSON marshals the NullUUID as null or the nested UUID 87 func (u NullUUID) MarshalJSON() ([]byte, error) { 88 if !u.Valid { 89 return json.Marshal(nil) 90 } 91 92 return json.Marshal(u.UUID) 93 } 94 95 // UnmarshalJSON unmarshals a NullUUID 96 func (u *NullUUID) UnmarshalJSON(b []byte) error { 97 if bytes.Equal(b, []byte("null")) { 98 u.UUID, u.Valid = Nil, false 99 return nil 100 } 101 102 if err := json.Unmarshal(b, &u.UUID); err != nil { 103 return err 104 } 105 106 u.Valid = true 107 108 return nil 109 } 110