github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/int.go (about)

     1  // Copyright 2020 DataStax
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package datacodec
    16  
    17  import (
    18  	"encoding/binary"
    19  	"strconv"
    20  
    21  	"github.com/datastax/go-cassandra-native-protocol/datatype"
    22  	"github.com/datastax/go-cassandra-native-protocol/primitive"
    23  )
    24  
    25  // Int is a codec for the CQL int type. Its preferred Go type is int32, but it can encode from and decode to
    26  // most numeric types.
    27  var Int Codec = &intCodec{}
    28  
    29  type intCodec struct{}
    30  
    31  func (c *intCodec) DataType() datatype.DataType {
    32  	return datatype.Int
    33  }
    34  
    35  func (c *intCodec) Encode(source interface{}, version primitive.ProtocolVersion) (dest []byte, err error) {
    36  	var val int32
    37  	var wasNil bool
    38  	if val, wasNil, err = convertToInt32(source); err == nil && !wasNil {
    39  		dest = writeInt32(val)
    40  	}
    41  	if err != nil {
    42  		err = errCannotEncode(source, c.DataType(), version, err)
    43  	}
    44  	return
    45  }
    46  
    47  func (c *intCodec) Decode(source []byte, dest interface{}, version primitive.ProtocolVersion) (wasNull bool, err error) {
    48  	var val int32
    49  	if val, wasNull, err = readInt32(source); err == nil {
    50  		err = convertFromInt32(val, wasNull, dest)
    51  	}
    52  	if err != nil {
    53  		err = errCannotDecode(dest, c.DataType(), version, err)
    54  	}
    55  	return
    56  }
    57  
    58  func convertToInt32(source interface{}) (val int32, wasNil bool, err error) {
    59  	switch s := source.(type) {
    60  	case int:
    61  		val, err = intToInt32(s)
    62  	case int64:
    63  		val, err = int64ToInt32(s)
    64  	case int32:
    65  		val = s
    66  	case int16:
    67  		val = int32(s)
    68  	case int8:
    69  		val = int32(s)
    70  	case uint:
    71  		val, err = uintToInt32(s)
    72  	case uint64:
    73  		val, err = uint64ToInt32(s)
    74  	case uint32:
    75  		val, err = uint32ToInt32(s)
    76  	case uint16:
    77  		val = int32(s)
    78  	case uint8:
    79  		val = int32(s)
    80  	case string:
    81  		val, err = stringToInt32(s)
    82  	case *int:
    83  		if wasNil = s == nil; !wasNil {
    84  			val, err = intToInt32(*s)
    85  		}
    86  	case *int64:
    87  		if wasNil = s == nil; !wasNil {
    88  			val, err = int64ToInt32(*s)
    89  		}
    90  	case *int32:
    91  		if wasNil = s == nil; !wasNil {
    92  			val = *s
    93  		}
    94  	case *int16:
    95  		if wasNil = s == nil; !wasNil {
    96  			val = int32(*s)
    97  		}
    98  	case *int8:
    99  		if wasNil = s == nil; !wasNil {
   100  			val = int32(*s)
   101  		}
   102  	case *uint:
   103  		if wasNil = s == nil; !wasNil {
   104  			val, err = uintToInt32(*s)
   105  		}
   106  	case *uint64:
   107  		if wasNil = s == nil; !wasNil {
   108  			val, err = uint64ToInt32(*s)
   109  		}
   110  	case *uint32:
   111  		if wasNil = s == nil; !wasNil {
   112  			val, err = uint32ToInt32(*s)
   113  		}
   114  	case *uint16:
   115  		if wasNil = s == nil; !wasNil {
   116  			val = int32(*s)
   117  		}
   118  	case *uint8:
   119  		if wasNil = s == nil; !wasNil {
   120  			val = int32(*s)
   121  		}
   122  	case *string:
   123  		if wasNil = s == nil; !wasNil {
   124  			val, err = stringToInt32(*s)
   125  		}
   126  	case nil:
   127  		wasNil = true
   128  	default:
   129  		err = ErrConversionNotSupported
   130  	}
   131  	if err != nil {
   132  		err = errSourceConversionFailed(source, val, err)
   133  	}
   134  	return
   135  }
   136  
   137  func convertFromInt32(val int32, wasNull bool, dest interface{}) (err error) {
   138  	switch d := dest.(type) {
   139  	case *interface{}:
   140  		if d == nil {
   141  			err = ErrNilDestination
   142  		} else if wasNull {
   143  			*d = nil
   144  		} else {
   145  			*d = val
   146  		}
   147  	case *int:
   148  		if d == nil {
   149  			err = ErrNilDestination
   150  		} else if wasNull {
   151  			*d = 0
   152  		} else {
   153  			*d = int(val)
   154  		}
   155  	case *int64:
   156  		if d == nil {
   157  			err = ErrNilDestination
   158  		} else if wasNull {
   159  			*d = 0
   160  		} else {
   161  			*d = int64(val)
   162  		}
   163  	case *int32:
   164  		if d == nil {
   165  			err = ErrNilDestination
   166  		} else if wasNull {
   167  			*d = 0
   168  		} else {
   169  			*d = val
   170  		}
   171  	case *int16:
   172  		if d == nil {
   173  			err = ErrNilDestination
   174  		} else if wasNull {
   175  			*d = 0
   176  		} else {
   177  			*d, err = int32ToInt16(val)
   178  		}
   179  	case *int8:
   180  		if d == nil {
   181  			err = ErrNilDestination
   182  		} else if wasNull {
   183  			*d = 0
   184  		} else {
   185  			*d, err = int32ToInt8(val)
   186  		}
   187  	case *uint:
   188  		if d == nil {
   189  			err = ErrNilDestination
   190  		} else if wasNull {
   191  			*d = 0
   192  		} else {
   193  			*d, err = int32ToUint(val)
   194  		}
   195  	case *uint64:
   196  		if d == nil {
   197  			err = ErrNilDestination
   198  		} else if wasNull {
   199  			*d = 0
   200  		} else {
   201  			*d, err = int32ToUint64(val)
   202  		}
   203  	case *uint32:
   204  		if d == nil {
   205  			err = ErrNilDestination
   206  		} else if wasNull {
   207  			*d = 0
   208  		} else {
   209  			*d, err = int32ToUint32(val)
   210  		}
   211  	case *uint16:
   212  		if d == nil {
   213  			err = ErrNilDestination
   214  		} else if wasNull {
   215  			*d = 0
   216  		} else {
   217  			*d, err = int32ToUint16(val)
   218  		}
   219  	case *uint8:
   220  		if d == nil {
   221  			err = ErrNilDestination
   222  		} else if wasNull {
   223  			*d = 0
   224  		} else {
   225  			*d, err = int32ToUint8(val)
   226  		}
   227  	case *string:
   228  		if d == nil {
   229  			err = ErrNilDestination
   230  		} else if wasNull {
   231  			*d = ""
   232  		} else {
   233  			*d = strconv.FormatInt(int64(val), 10)
   234  		}
   235  	default:
   236  		err = errDestinationInvalid(dest)
   237  	}
   238  	if err != nil {
   239  		err = errDestinationConversionFailed(val, dest, err)
   240  	}
   241  	return
   242  }
   243  
   244  func writeInt32(val int32) (dest []byte) {
   245  	dest = make([]byte, primitive.LengthOfInt)
   246  	binary.BigEndian.PutUint32(dest, uint32(val))
   247  	return
   248  }
   249  
   250  func readInt32(source []byte) (val int32, wasNull bool, err error) {
   251  	length := len(source)
   252  	if length == 0 {
   253  		wasNull = true
   254  	} else if length != primitive.LengthOfInt {
   255  		err = errWrongFixedLength(primitive.LengthOfInt, length)
   256  	} else {
   257  		val = int32(binary.BigEndian.Uint32(source))
   258  	}
   259  	if err != nil {
   260  		err = errCannotRead(val, err)
   261  	}
   262  	return
   263  }