github.com/dolthub/go-mysql-server@v0.18.0/sql/values/encoding.go (about) 1 // Copyright 2022 Dolthub, Inc. 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 values 16 17 import ( 18 "bytes" 19 "encoding/binary" 20 "math" 21 ) 22 23 type Type struct { 24 Enc Encoding 25 Coll Collation 26 Nullable bool 27 } 28 29 type ByteSize uint16 30 31 const ( 32 Int8Size ByteSize = 1 33 Uint8Size ByteSize = 1 34 Int16Size ByteSize = 2 35 Uint16Size ByteSize = 2 36 Int24Size ByteSize = 3 37 Uint24Size ByteSize = 3 38 Int32Size ByteSize = 4 39 Uint32Size ByteSize = 4 40 Int48Size ByteSize = 6 41 Uint48Size ByteSize = 6 42 Int64Size ByteSize = 8 43 Uint64Size ByteSize = 8 44 Float32Size ByteSize = 4 45 Float64Size ByteSize = 8 46 ) 47 48 const maxUint48 = uint64(1<<48 - 1) 49 const maxUint24 = uint32(1<<24 - 1) 50 51 type Collation uint16 52 53 const ( 54 ByteOrderCollation Collation = 0 55 ) 56 57 type Encoding uint8 58 59 // Constant Size Encodings 60 const ( 61 NullEnc Encoding = 0 62 Int8Enc Encoding = 1 63 Uint8Enc Encoding = 2 64 Int16Enc Encoding = 3 65 Uint16Enc Encoding = 4 66 Int24Enc Encoding = 5 67 Uint24Enc Encoding = 6 68 Int32Enc Encoding = 7 69 Uint32Enc Encoding = 8 70 Int64Enc Encoding = 9 71 Uint64Enc Encoding = 10 72 Float32Enc Encoding = 11 73 Float64Enc Encoding = 12 74 75 // TODO 76 // TimeEnc 77 // TimestampEnc 78 // DateEnc 79 // TimeEnc 80 // DatetimeEnc 81 // YearEnc 82 83 sentinel Encoding = 127 84 ) 85 86 // Variable Size Encodings 87 const ( 88 StringEnc Encoding = 128 89 BytesEnc Encoding = 129 90 91 // TODO 92 // DecimalEnc 93 // BitEnc 94 // CharEnc 95 // VarCharEnc 96 // TextEnc 97 // BinaryEnc 98 // VarBinaryEnc 99 // BlobEnc 100 // JSONEnc 101 // EnumEnc 102 // SetEnc 103 // ExpressionEnc 104 // GeometryEnc 105 ) 106 107 func ReadBool(val []byte) bool { 108 expectSize(val, Int8Size) 109 return val[0] == 1 110 } 111 func ReadInt8(val []byte) int8 { 112 expectSize(val, Int8Size) 113 return int8(val[0]) 114 } 115 116 func ReadUint8(val []byte) uint8 { 117 expectSize(val, Uint8Size) 118 return val[0] 119 } 120 121 func ReadInt16(val []byte) int16 { 122 expectSize(val, Int16Size) 123 return int16(binary.LittleEndian.Uint16(val)) 124 } 125 126 func ReadUint16(val []byte) uint16 { 127 expectSize(val, Uint16Size) 128 return binary.LittleEndian.Uint16(val) 129 } 130 131 func ReadInt24(val []byte) (i int32) { 132 expectSize(val, Int24Size) 133 var tmp [4]byte 134 // copy |val| to |tmp| 135 tmp[3], tmp[2] = val[3], val[2] 136 tmp[1], tmp[0] = val[1], val[0] 137 i = int32(binary.LittleEndian.Uint32(tmp[:])) 138 return 139 } 140 141 func ReadUint24(val []byte) (u uint32) { 142 expectSize(val, Int24Size) 143 var tmp [4]byte 144 // copy |val| to |tmp| 145 tmp[3], tmp[2] = val[3], val[2] 146 tmp[1], tmp[0] = val[1], val[0] 147 u = binary.LittleEndian.Uint32(tmp[:]) 148 return 149 } 150 151 func ReadInt32(val []byte) int32 { 152 expectSize(val, Int32Size) 153 return int32(binary.LittleEndian.Uint32(val)) 154 } 155 156 func ReadUint32(val []byte) uint32 { 157 expectSize(val, Uint32Size) 158 return binary.LittleEndian.Uint32(val) 159 } 160 161 func ReadInt48(val []byte) (i int64) { 162 expectSize(val, Int48Size) 163 var tmp [8]byte 164 // copy |val| to |tmp| 165 tmp[5], tmp[4] = val[5], val[4] 166 tmp[3], tmp[2] = val[3], val[2] 167 tmp[1], tmp[0] = val[1], val[0] 168 i = int64(binary.LittleEndian.Uint64(tmp[:])) 169 return 170 } 171 172 func ReadUint48(val []byte) (u uint64) { 173 expectSize(val, Uint48Size) 174 var tmp [8]byte 175 // copy |val| to |tmp| 176 tmp[5], tmp[4] = val[5], val[4] 177 tmp[3], tmp[2] = val[3], val[2] 178 tmp[1], tmp[0] = val[1], val[0] 179 u = binary.LittleEndian.Uint64(tmp[:]) 180 return 181 } 182 183 func ReadInt64(val []byte) int64 { 184 expectSize(val, Int64Size) 185 return int64(binary.LittleEndian.Uint64(val)) 186 } 187 188 func ReadUint64(val []byte) uint64 { 189 expectSize(val, Uint64Size) 190 return binary.LittleEndian.Uint64(val) 191 } 192 193 func ReadFloat32(val []byte) float32 { 194 expectSize(val, Float32Size) 195 return math.Float32frombits(ReadUint32(val)) 196 } 197 198 func ReadFloat64(val []byte) float64 { 199 expectSize(val, Float64Size) 200 return math.Float64frombits(ReadUint64(val)) 201 } 202 203 func ReadString(val []byte, coll Collation) string { 204 // todo: fix allocation 205 return string(val) 206 } 207 208 func ReadBytes(val []byte, coll Collation) []byte { 209 // todo: fix collation 210 return val 211 } 212 213 func writeBool(buf []byte, val bool) { 214 expectSize(buf, 1) 215 if val { 216 buf[0] = byte(1) 217 } else { 218 buf[0] = byte(0) 219 } 220 } 221 222 func WriteInt8(buf []byte, val int8) []byte { 223 expectSize(buf, Int8Size) 224 buf[0] = byte(val) 225 return buf 226 } 227 228 func WriteUint8(buf []byte, val uint8) []byte { 229 expectSize(buf, Uint8Size) 230 buf[0] = byte(val) 231 return buf 232 } 233 234 func WriteInt16(buf []byte, val int16) []byte { 235 expectSize(buf, Int16Size) 236 binary.LittleEndian.PutUint16(buf, uint16(val)) 237 return buf 238 } 239 240 func WriteUint16(buf []byte, val uint16) []byte { 241 expectSize(buf, Uint16Size) 242 binary.LittleEndian.PutUint16(buf, val) 243 return buf 244 } 245 246 func WriteInt24(buf []byte, val int32) []byte { 247 expectSize(buf, Int24Size) 248 249 var tmp [4]byte 250 binary.LittleEndian.PutUint32(tmp[:], uint32(val)) 251 // copy |tmp| to |buf| 252 buf[2], buf[1], buf[0] = tmp[2], tmp[1], tmp[0] 253 return buf 254 255 binary.LittleEndian.PutUint16(buf, uint16(val)) 256 return buf 257 } 258 259 func WriteUint24(buf []byte, val uint32) []byte { 260 expectSize(buf, Uint24Size) 261 if val > maxUint24 { 262 panic("uint is greater than max uint24") 263 } 264 265 var tmp [4]byte 266 binary.LittleEndian.PutUint32(tmp[:], uint32(val)) 267 // copy |tmp| to |buf| 268 buf[2], buf[1], buf[0] = tmp[2], tmp[1], tmp[0] 269 return buf 270 271 binary.LittleEndian.PutUint16(buf, uint16(val)) 272 return buf 273 } 274 275 func WriteInt32(buf []byte, val int32) []byte { 276 expectSize(buf, Int32Size) 277 binary.LittleEndian.PutUint32(buf, uint32(val)) 278 return buf 279 } 280 281 func WriteUint32(buf []byte, val uint32) []byte { 282 expectSize(buf, Uint32Size) 283 binary.LittleEndian.PutUint32(buf, val) 284 return buf 285 } 286 287 func WriteUint48(buf []byte, u uint64) []byte { 288 expectSize(buf, Uint48Size) 289 if u > maxUint48 { 290 panic("uint is greater than max uint48") 291 } 292 var tmp [8]byte 293 binary.LittleEndian.PutUint64(tmp[:], u) 294 // copy |tmp| to |buf| 295 buf[5], buf[4] = tmp[5], tmp[4] 296 buf[3], buf[2] = tmp[3], tmp[2] 297 buf[1], buf[0] = tmp[1], tmp[0] 298 return buf 299 } 300 301 func WriteInt64(buf []byte, val int64) []byte { 302 expectSize(buf, Int64Size) 303 binary.LittleEndian.PutUint64(buf, uint64(val)) 304 return buf 305 } 306 307 func WriteUint64(buf []byte, val uint64) []byte { 308 expectSize(buf, Uint64Size) 309 binary.LittleEndian.PutUint64(buf, val) 310 return buf 311 } 312 313 func WriteFloat32(buf []byte, val float32) []byte { 314 expectSize(buf, Float32Size) 315 binary.LittleEndian.PutUint32(buf, math.Float32bits(val)) 316 return buf 317 } 318 319 func WriteFloat64(buf []byte, val float64) []byte { 320 expectSize(buf, Float64Size) 321 binary.LittleEndian.PutUint64(buf, math.Float64bits(val)) 322 return buf 323 } 324 325 func WriteString(buf []byte, val string, coll Collation) []byte { 326 // todo: fix collation 327 expectSize(buf, ByteSize(len(val))) 328 copy(buf, val) 329 return buf 330 } 331 332 func WriteBytes(buf, val []byte, coll Collation) []byte { 333 // todo: fix collation 334 expectSize(buf, ByteSize(len(val))) 335 copy(buf, val) 336 return buf 337 } 338 339 func expectSize(buf []byte, sz ByteSize) { 340 if ByteSize(len(buf)) != sz { 341 panic("byte slice is not of expected size") 342 } 343 } 344 345 func compare(typ Type, left, right []byte) int { 346 // order NULLs last 347 if left == nil { 348 if right == nil { 349 return 0 350 } else { 351 return 1 352 } 353 } else if right == nil { 354 if left == nil { 355 return 0 356 } else { 357 return -1 358 } 359 } 360 361 switch typ.Enc { 362 case Int8Enc: 363 return compareInt8(ReadInt8(left), ReadInt8(right)) 364 case Uint8Enc: 365 return compareUint8(ReadUint8(left), ReadUint8(right)) 366 case Int16Enc: 367 return compareInt16(ReadInt16(left), ReadInt16(right)) 368 case Uint16Enc: 369 return compareUint16(ReadUint16(left), ReadUint16(right)) 370 case Int24Enc: 371 panic("24 bit") 372 case Uint24Enc: 373 panic("24 bit") 374 case Int32Enc: 375 return compareInt32(ReadInt32(left), ReadInt32(right)) 376 case Uint32Enc: 377 return compareUint32(ReadUint32(left), ReadUint32(right)) 378 case Int64Enc: 379 return compareInt64(ReadInt64(left), ReadInt64(right)) 380 case Uint64Enc: 381 return compareUint64(ReadUint64(left), ReadUint64(right)) 382 case Float32Enc: 383 return compareFloat32(ReadFloat32(left), ReadFloat32(right)) 384 case Float64Enc: 385 return compareFloat64(ReadFloat64(left), ReadFloat64(right)) 386 case StringEnc: 387 return compareString(ReadString(left, typ.Coll), ReadString(right, typ.Coll), typ.Coll) 388 case BytesEnc: 389 return compareBytes(ReadBytes(left, typ.Coll), ReadBytes(right, typ.Coll), typ.Coll) 390 default: 391 panic("unknown encoding") 392 } 393 } 394 395 // false is less than true 396 func compareBool(l, r bool) int { 397 if l == r { 398 return 0 399 } 400 if !l && r { 401 return -1 402 } 403 return 1 404 } 405 406 func compareInt8(l, r int8) int { 407 if l == r { 408 return 0 409 } else if l < r { 410 return -1 411 } else { 412 return 1 413 } 414 } 415 416 func compareUint8(l, r uint8) int { 417 if l == r { 418 return 0 419 } else if l < r { 420 return -1 421 } else { 422 return 1 423 } 424 } 425 426 func compareInt16(l, r int16) int { 427 if l == r { 428 return 0 429 } else if l < r { 430 return -1 431 } else { 432 return 1 433 } 434 } 435 436 func compareUint16(l, r uint16) int { 437 if l == r { 438 return 0 439 } else if l < r { 440 return -1 441 } else { 442 return 1 443 } 444 } 445 446 func compareInt32(l, r int32) int { 447 if l == r { 448 return 0 449 } else if l < r { 450 return -1 451 } else { 452 return 1 453 } 454 } 455 456 func compareUint32(l, r uint32) int { 457 if l == r { 458 return 0 459 } else if l < r { 460 return -1 461 } else { 462 return 1 463 } 464 } 465 466 func compareInt64(l, r int64) int { 467 if l == r { 468 return 0 469 } else if l < r { 470 return -1 471 } else { 472 return 1 473 } 474 } 475 476 func compareUint64(l, r uint64) int { 477 if l == r { 478 return 0 479 } else if l < r { 480 return -1 481 } else { 482 return 1 483 } 484 } 485 486 func compareFloat32(l, r float32) int { 487 if l == r { 488 return 0 489 } else if l < r { 490 return -1 491 } else { 492 return 1 493 } 494 } 495 496 func compareFloat64(l, r float64) int { 497 if l == r { 498 return 0 499 } else if l < r { 500 return -1 501 } else { 502 return 1 503 } 504 } 505 506 func compareString(l, r string, coll Collation) int { 507 return bytes.Compare([]byte(l), []byte(r)) 508 } 509 510 func compareBytes(l, r []byte, coll Collation) int { 511 return bytes.Compare(l, r) 512 }