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  }