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