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  }