github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/tinyint.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 "math" 19 "strconv" 20 21 "github.com/datastax/go-cassandra-native-protocol/datatype" 22 "github.com/datastax/go-cassandra-native-protocol/primitive" 23 ) 24 25 // Tinyint is a codec for the CQL tinyint type. Its preferred Go type is int8, but it can encode from and decode 26 // to most numeric types. 27 var Tinyint Codec = &tinyintCodec{} 28 29 type tinyintCodec struct{} 30 31 func (c *tinyintCodec) DataType() datatype.DataType { 32 return datatype.Tinyint 33 } 34 35 func (c *tinyintCodec) Encode(source interface{}, version primitive.ProtocolVersion) (dest []byte, err error) { 36 if !version.SupportsDataType(c.DataType().Code()) { 37 err = errDataTypeNotSupported(c.DataType(), version) 38 } else { 39 var val int8 40 var wasNil bool 41 if val, wasNil, err = convertToInt8(source); err == nil && !wasNil { 42 dest = writeInt8(val) 43 } 44 } 45 if err != nil { 46 err = errCannotEncode(source, c.DataType(), version, err) 47 } 48 return 49 } 50 51 func (c *tinyintCodec) Decode(source []byte, dest interface{}, version primitive.ProtocolVersion) (wasNull bool, err error) { 52 if !version.SupportsDataType(c.DataType().Code()) { 53 wasNull = len(source) == 0 54 err = errDataTypeNotSupported(c.DataType(), version) 55 } else { 56 var val int8 57 if val, wasNull, err = readInt8(source); err == nil { 58 err = convertFromInt8(val, wasNull, dest) 59 } 60 } 61 if err != nil { 62 err = errCannotDecode(dest, c.DataType(), version, err) 63 } 64 return 65 } 66 67 func convertToInt8(source interface{}) (val int8, wasNil bool, err error) { 68 switch s := source.(type) { 69 case int64: 70 val, err = int64ToInt8(s) 71 case int: 72 val, err = intToInt8(s) 73 case int32: 74 val, err = int32ToInt8(s) 75 case int16: 76 val, err = int16ToInt8(s) 77 case int8: 78 val = s 79 case uint64: 80 val, err = uint64ToInt8(s) 81 case uint: 82 val, err = uintToInt8(s) 83 case uint32: 84 val, err = uint32ToInt8(s) 85 case uint16: 86 val, err = uint16ToInt8(s) 87 case uint8: 88 val, err = uint8ToInt8(s) 89 case string: 90 val, err = stringToInt8(s) 91 case *int64: 92 if wasNil = s == nil; !wasNil { 93 val, err = int64ToInt8(*s) 94 if *s < math.MinInt8 || *s > math.MaxInt8 { 95 err = errValueOutOfRange(*s) 96 } else { 97 val = int8(*s) 98 } 99 } 100 case *int: 101 if wasNil = s == nil; !wasNil { 102 val, err = intToInt8(*s) 103 } 104 case *int32: 105 if wasNil = s == nil; !wasNil { 106 val, err = int32ToInt8(*s) 107 } 108 case *int16: 109 if wasNil = s == nil; !wasNil { 110 val, err = int16ToInt8(*s) 111 } 112 case *int8: 113 if wasNil = s == nil; !wasNil { 114 val = *s 115 } 116 case *uint64: 117 if wasNil = s == nil; !wasNil { 118 val, err = uint64ToInt8(*s) 119 } 120 case *uint: 121 if wasNil = s == nil; !wasNil { 122 val, err = uintToInt8(*s) 123 } 124 case *uint32: 125 if wasNil = s == nil; !wasNil { 126 val, err = uint32ToInt8(*s) 127 } 128 case *uint16: 129 if wasNil = s == nil; !wasNil { 130 val, err = uint16ToInt8(*s) 131 } 132 case *uint8: 133 if wasNil = s == nil; !wasNil { 134 val, err = uint8ToInt8(*s) 135 } 136 case *string: 137 if wasNil = s == nil; !wasNil { 138 val, err = stringToInt8(*s) 139 } 140 case nil: 141 wasNil = true 142 default: 143 err = ErrConversionNotSupported 144 } 145 if err != nil { 146 err = errSourceConversionFailed(source, val, err) 147 } 148 return 149 } 150 151 func convertFromInt8(val int8, wasNull bool, dest interface{}) (err error) { 152 switch d := dest.(type) { 153 case *interface{}: 154 if d == nil { 155 err = ErrNilDestination 156 } else if wasNull { 157 *d = nil 158 } else { 159 *d = val 160 } 161 case *int64: 162 if d == nil { 163 err = ErrNilDestination 164 } else if wasNull { 165 *d = 0 166 } else { 167 *d = int64(val) 168 } 169 case *int: 170 if d == nil { 171 err = ErrNilDestination 172 } else if wasNull { 173 *d = 0 174 } else { 175 *d = int(val) 176 } 177 case *int32: 178 if d == nil { 179 err = ErrNilDestination 180 } else if wasNull { 181 *d = 0 182 } else { 183 *d = int32(val) 184 } 185 case *int16: 186 if d == nil { 187 err = ErrNilDestination 188 } else if wasNull { 189 *d = 0 190 } else { 191 *d = int16(val) 192 } 193 case *int8: 194 if d == nil { 195 err = ErrNilDestination 196 } else if wasNull { 197 *d = 0 198 } else { 199 *d = val 200 } 201 case *uint64: 202 if d == nil { 203 err = ErrNilDestination 204 } else if wasNull { 205 *d = 0 206 } else { 207 *d, err = int8ToUint64(val) 208 } 209 case *uint: 210 if d == nil { 211 err = ErrNilDestination 212 } else if wasNull { 213 *d = 0 214 } else { 215 *d, err = int8ToUint(val) 216 } 217 case *uint32: 218 if d == nil { 219 err = ErrNilDestination 220 } else if wasNull { 221 *d = 0 222 } else { 223 *d, err = int8ToUint32(val) 224 } 225 case *uint16: 226 if d == nil { 227 err = ErrNilDestination 228 } else if wasNull { 229 *d = 0 230 } else { 231 *d, err = int8ToUint16(val) 232 } 233 case *uint8: 234 if d == nil { 235 err = ErrNilDestination 236 } else if wasNull { 237 *d = 0 238 } else { 239 *d, err = int8ToUint8(val) 240 } 241 case *string: 242 if d == nil { 243 err = ErrNilDestination 244 } else if wasNull { 245 *d = "" 246 } else { 247 *d = strconv.FormatInt(int64(val), 10) 248 } 249 default: 250 err = errDestinationInvalid(dest) 251 } 252 if err != nil { 253 err = errDestinationConversionFailed(val, dest, err) 254 } 255 return 256 } 257 258 func writeInt8(val int8) (dest []byte) { 259 return []byte{byte(val)} 260 } 261 262 func readInt8(source []byte) (val int8, wasNull bool, err error) { 263 length := len(source) 264 if length == 0 { 265 wasNull = true 266 } else if length != primitive.LengthOfByte { 267 err = errWrongFixedLength(primitive.LengthOfByte, length) 268 } else { 269 val = int8(source[0]) 270 } 271 if err != nil { 272 err = errCannotRead(val, err) 273 } 274 return 275 }