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 }