github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/common/null/convert.go (about) 1 // This file is part of the Smart Home 2 // Program complex distribution https://github.com/e154/smart-home 3 // Copyright (C) 2016-2023, Filippov Alex 4 // 5 // This library is free software: you can redistribute it and/or 6 // modify it under the terms of the GNU Lesser General Public 7 // License as published by the Free Software Foundation; either 8 // version 3 of the License, or (at your option) any later version. 9 // 10 // This library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 // Library General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with this library. If not, see 17 // <https://www.gnu.org/licenses/>. 18 19 package null 20 21 import ( 22 "errors" 23 "fmt" 24 "reflect" 25 "strconv" 26 ) 27 28 // Value ... 29 type Value interface{} 30 31 var ( 32 // ErrDestinationPointerIsNil ... 33 ErrDestinationPointerIsNil = errors.New("destination pointer is nil") 34 // ErrDestinationNotAPointer ... 35 ErrDestinationNotAPointer = errors.New("destination not a pointer") 36 ) 37 38 func cloneBytes(b []byte) []byte { 39 if b == nil { 40 return nil 41 } else { 42 c := make([]byte, len(b)) 43 copy(c, b) 44 return c 45 } 46 } 47 48 func convertAssign(dest, src interface{}) error { 49 50 //switch v := src.(type) { 51 //case string: 52 // if v == "null" { 53 // dest = nil 54 // } 55 //} 56 57 dpv := reflect.ValueOf(dest) 58 if dpv.Kind() != reflect.Ptr { 59 return ErrDestinationNotAPointer 60 } 61 if dpv.IsNil() { 62 return ErrDestinationPointerIsNil 63 } 64 65 var sv reflect.Value 66 67 dv := reflect.Indirect(dpv) 68 if sv.IsValid() && sv.Type().AssignableTo(dv.Type()) { 69 switch b := src.(type) { 70 case []byte: 71 dv.Set(reflect.ValueOf(cloneBytes(b))) 72 default: 73 dv.Set(sv) 74 } 75 return nil 76 } 77 78 if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) { 79 dv.Set(sv.Convert(dv.Type())) 80 return nil 81 } 82 83 switch dv.Kind() { 84 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 85 rv := reflect.ValueOf(src) 86 s := strconv.FormatInt(rv.Int(), 10) 87 i64, err := strconv.ParseInt(s, 10, dv.Type().Bits()) 88 if err != nil { 89 return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err) 90 } 91 dv.SetInt(i64) 92 return nil 93 } 94 95 return nil 96 }