1use crate::error::TypesError;
2use crate::value::Scalar;
3
4fn u64be(v: u64) -> [u8; 8] {
5 v.to_be_bytes()
6}
7
8fn int_encode(i: i64) -> [u8; 8] {
10 u64be(u64::from_ne_bytes(i.to_ne_bytes()) ^ 0x8000_0000_0000_0000)
11}
12
13fn int_decode(b: &[u8]) -> i64 {
14 let raw = u64::from_be_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]);
15 i64::from_ne_bytes((raw ^ 0x8000_0000_0000_0000).to_ne_bytes())
16}
17
18fn float_encode(f: f64) -> [u8; 8] {
21 let bits = f.to_bits();
22 let transformed = if bits & 0x8000_0000_0000_0000 == 0 {
23 bits | 0x8000_0000_0000_0000
24 } else {
25 !bits
26 };
27 u64be(transformed)
28}
29
30fn float_decode(b: &[u8]) -> f64 {
31 let raw = u64::from_be_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]);
32 let original = if raw & 0x8000_0000_0000_0000 == 0 {
33 !raw
34 } else {
35 raw & !0x8000_0000_0000_0000
36 };
37 f64::from_bits(original)
38}
39
40#[must_use]
42pub fn logical_tag(ty: crate::model::LogicalType) -> u8 {
43 use crate::model::LogicalType::{Boolean, DateTime, Float64, Int64, Utf8};
44 match ty {
45 Boolean => 1,
46 Int64 => 2,
47 Float64 => 3,
48 Utf8 => 4,
49 DateTime => 5,
50 }
51}
52
53pub fn logical_from_tag(tag: u8) -> Result<crate::model::LogicalType, TypesError> {
59 use crate::model::LogicalType::{Boolean, DateTime, Float64, Int64, Utf8};
60 Ok(match tag {
61 1 => Boolean,
62 2 => Int64,
63 3 => Float64,
64 4 => Utf8,
65 5 => DateTime,
66 other => return Err(TypesError::UnknownTypeTag(other)),
67 })
68}
69
70#[must_use]
77pub fn encode_value_with_prefix(ty: crate::model::LogicalType, s: &Scalar) -> Vec<u8> {
78 let mut out = vec![logical_tag(ty)];
79 out.extend_from_slice(&encode_order_preserving(ty, s).expect("encodable"));
80 out
81}
82
83pub fn encode_order_preserving(
89 ty: crate::model::LogicalType,
90 s: &Scalar,
91) -> Result<Vec<u8>, TypesError> {
92 use crate::model::LogicalType::{Boolean, DateTime, Float64, Int64, Utf8};
93 let err = || TypesError::Unencodable("scalar/type mismatch");
94 Ok(match ty {
95 Boolean => match s {
96 Scalar::Boolean(true) => vec![1],
97 Scalar::Boolean(false) => vec![0],
98 _ => return Err(err()),
99 },
100 Int64 => match s {
101 Scalar::Int64(i) => int_encode(*i).to_vec(),
102 _ => return Err(err()),
103 },
104 DateTime => match s {
105 Scalar::DateTime(ms) => int_encode(*ms).to_vec(),
106 _ => return Err(err()),
107 },
108 Float64 => match s {
109 Scalar::Float64(f) if !f.is_nan() => float_encode(*f).to_vec(),
110 _ => return Err(err()),
111 },
112 Utf8 => match s {
113 Scalar::Utf8(st) => {
114 let mut b = st.as_bytes().to_vec();
115 b.push(0x00);
116 b
117 }
118 _ => return Err(err()),
119 },
120 })
121}
122
123pub fn decode_order_preserving(
131 ty: crate::model::LogicalType,
132 b: &[u8],
133) -> Result<Scalar, TypesError> {
134 use crate::model::LogicalType::{Boolean, DateTime, Float64, Int64, Utf8};
135 Ok(match ty {
136 Boolean => match b {
137 [0] => Scalar::Boolean(false),
138 [1] => Scalar::Boolean(true),
139 _ => return Err(TypesError::MalformedKey),
140 },
141 Int64 => {
142 let raw: [u8; 8] = b.try_into().map_err(|_| TypesError::MalformedKey)?;
143 Scalar::Int64(int_decode(&raw))
144 }
145 DateTime => {
146 let raw: [u8; 8] = b.try_into().map_err(|_| TypesError::MalformedKey)?;
147 Scalar::DateTime(int_decode(&raw))
148 }
149 Float64 => {
150 let raw: [u8; 8] = b.try_into().map_err(|_| TypesError::MalformedKey)?;
151 let value = float_decode(&raw);
152 if value.is_nan() {
153 return Err(TypesError::MalformedKey);
154 }
155 Scalar::Float64(value)
156 }
157 Utf8 => {
158 let trimmed = b.strip_suffix(&[0x00]).ok_or(TypesError::MalformedKey)?;
159 Scalar::Utf8(String::from_utf8(trimmed.to_vec()).map_err(|_| TypesError::MalformedKey)?)
160 }
161 })
162}
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167 use crate::model::LogicalType;
168
169 #[test]
170 fn order_preserving_decoder_rejects_invalid_fixed_widths() {
171 for ty in [
172 LogicalType::Int64,
173 LogicalType::DateTime,
174 LogicalType::Float64,
175 ] {
176 assert!(matches!(
177 decode_order_preserving(ty, &[]),
178 Err(TypesError::MalformedKey)
179 ));
180 assert!(matches!(
181 decode_order_preserving(ty, &[0; 9]),
182 Err(TypesError::MalformedKey)
183 ));
184 }
185 assert!(matches!(
186 decode_order_preserving(LogicalType::Boolean, &[0, 0]),
187 Err(TypesError::MalformedKey)
188 ));
189 }
190
191 #[test]
192 fn float_order_encoding_rejects_nan() {
193 assert!(matches!(
194 encode_order_preserving(LogicalType::Float64, &Scalar::Float64(f64::NAN)),
195 Err(TypesError::Unencodable(_))
196 ));
197 assert!(matches!(
198 decode_order_preserving(LogicalType::Float64, &float_encode(f64::NAN)),
199 Err(TypesError::MalformedKey)
200 ));
201 }
202}