/// The dispatch layer: one entry point per direction, keyed by the neutral
/// `ColBuf` model. Encoders stay independent and testable; this file only
/// routes between them.
///
/// v1 decode is page-granular: RLE and DELTA are sequential encodings, so
/// callers split pages themselves. No IO happens here, and no consumer types
/// appear in the signatures.
///|
/// Encode a column with the requested family, appending to `out`. The returned
/// statistics describe this call only, so repeated encodes can be summed.
pub fn encode_column(
column : @types.ColBuf,
encoding : @types.Encoding,
out : @buffer.Buffer,
) -> @types.EncodingStats raise @types.EncodingError {
let start = out.length()
match encoding {
Plain =>
match column {
Int32s(values) => @encoders.encode_int32(values, out)
Int64s(values) => @encoders.encode_int64(values, out)
Floats(values) => @encoders.encode_float(values, out)
Doubles(values) => @encoders.encode_double(values, out)
ByteArrays(values) => @encoders.encode_byte_arrays(values, out)
Bools(values) => @encoders.encode_bool(values, out)
}
Rle =>
match column {
Bools(values) => @encoders.encode_bool_rle(values, out)
_ =>
raise @types.EncodingError::TypeMismatch(column.physical_type(), Rle)
}
DeltaBinaryPacked =>
match column {
Int32s(values) => @encoders.encode_delta_int32(values[:], out)
Int64s(values) => @encoders.encode_delta_int64(values[:], out)
_ =>
raise @types.EncodingError::TypeMismatch(
column.physical_type(),
DeltaBinaryPacked,
)
}
DeltaLength =>
match column {
ByteArrays(values) =>
@encoders.encode_delta_length_byte_array(values, out)
_ =>
raise @types.EncodingError::TypeMismatch(
column.physical_type(),
DeltaLength,
)
}
DeltaByteArray =>
match column {
ByteArrays(values) => @encoders.encode_delta_byte_array(values, out)
_ =>
raise @types.EncodingError::TypeMismatch(
column.physical_type(),
DeltaByteArray,
)
}
ByteStreamSplit =>
match column {
Floats(values) => @encoders.encode_byte_stream_split_float(values, out)
Doubles(values) =>
@encoders.encode_byte_stream_split_double(values, out)
_ =>
raise @types.EncodingError::TypeMismatch(
column.physical_type(),
ByteStreamSplit,
)
}
Fsst =>
match column {
ByteArrays(values) => @encoders.encode_fsst(values, out)
_ =>
raise @types.EncodingError::TypeMismatch(column.physical_type(), Fsst)
}
other => raise @types.EncodingError::Unsupported(other)
}
{ value_count: column.value_count(), encoded_bytes: out.length() - start, }
}
///|
/// Decode `count` values of physical type `ty`. The input may be longer than
/// needed; trailing bytes belong to the caller.
pub fn decode_column(
data : BytesView,
ty : @types.PhysicalType,
encoding : @types.Encoding,
count : Int32,
) -> @types.ColBuf raise @types.EncodingError {
match encoding {
Plain =>
match ty {
Int32 => @types.ColBuf::Int32s(@encoders.decode_int32(data, count))
Int64 => @types.ColBuf::Int64s(@encoders.decode_int64(data, count))
Float => @types.ColBuf::Floats(@encoders.decode_float(data, count))
Double => @types.ColBuf::Doubles(@encoders.decode_double(data, count))
ByteArray =>
@types.ColBuf::ByteArrays(@encoders.decode_byte_arrays(data, count))
Bool => @types.ColBuf::Bools(@encoders.decode_bool(data, count))
}
Rle =>
match ty {
Bool => @types.ColBuf::Bools(@encoders.decode_bool_rle(data, count))
_ => raise @types.EncodingError::TypeMismatch(ty, Rle)
}
DeltaBinaryPacked =>
match ty {
Int32 =>
@types.ColBuf::Int32s(@encoders.decode_delta_int32(data, count).0)
Int64 =>
@types.ColBuf::Int64s(@encoders.decode_delta_int64(data, count).0)
_ => raise @types.EncodingError::TypeMismatch(ty, DeltaBinaryPacked)
}
DeltaLength =>
match ty {
ByteArray =>
@types.ColBuf::ByteArrays(
@encoders.decode_delta_length_byte_array(data, count).0,
)
_ => raise @types.EncodingError::TypeMismatch(ty, DeltaLength)
}
DeltaByteArray =>
match ty {
ByteArray =>
@types.ColBuf::ByteArrays(
@encoders.decode_delta_byte_array(data, count).0,
)
_ => raise @types.EncodingError::TypeMismatch(ty, DeltaByteArray)
}
ByteStreamSplit =>
match ty {
Float =>
@types.ColBuf::Floats(
@encoders.decode_byte_stream_split_float(data, count),
)
Double =>
@types.ColBuf::Doubles(
@encoders.decode_byte_stream_split_double(data, count),
)
_ => raise @types.EncodingError::TypeMismatch(ty, ByteStreamSplit)
}
Fsst =>
match ty {
ByteArray =>
@types.ColBuf::ByteArrays(@encoders.decode_fsst(data, count).0)
_ => raise @types.EncodingError::TypeMismatch(ty, Fsst)
}
other => raise @types.EncodingError::Unsupported(other)
}
}
///|
/// Build a dictionary encoding for a column. Returns `None` when the PLAIN
/// dictionary payload exceeds `max_dictionary_bytes`, meaning the caller should
/// fall back to PLAIN. Dictionary encoding has two output streams, so it does
/// not go through `encode_column`.
pub fn encode_dictionary(
column : @types.ColBuf,
max_dictionary_bytes~ : Int32 = @encoders.DEFAULT_DICTIONARY_BYTE_LIMIT,
) -> @types.DictionaryEncoding? raise @types.EncodingError {
@encoders.encode_dictionary(column, max_dictionary_bytes~)
}
///|
/// Decode a dictionary page plus its index stream back into values.
pub fn decode_dictionary(
dictionary : BytesView,
indices : BytesView,
ty : @types.PhysicalType,
count : Int32,
dictionary_size : Int32,
) -> @types.ColBuf raise @types.EncodingError {
@encoders.decode_dictionary(dictionary, indices, ty, count, dictionary_size)
}