1use crate::{
7 bitpack,
8 error::{Result, TurboQuantError},
9 polar::PolarCode,
10 qjl::QjlSketch,
11 rotation::RotationKind,
12 turbo::{TurboCode, TurboMode, TurboQuantizer},
13};
14
15pub const TURBO_CODE_WIRE_MAGIC: &[u8; 4] = b"TQW1";
17
18const VERSION: u16 = 1;
19const VARIANT_TURBO_CODE: u8 = 1;
20
21pub struct TurboCodeWireV1;
23
24impl TurboCodeWireV1 {
25 pub fn encode(code: &TurboCode, profile: &TurboQuantizer) -> Result<Vec<u8>> {
27 code.validate_for(
28 profile.dim(),
29 profile.bits(),
30 profile.projections(),
31 profile.mode(),
32 )?;
33
34 let dim = checked_u32(profile.dim(), "dimension")?;
35 let polar_bits = code.polar_code.bits;
36 let qjl_projections = checked_u32(profile.projections(), "projection count")?;
37 let polar_block_count = checked_u32(code.polar_code.radii.len(), "polar block count")?;
38 let qjl_sign_count = checked_u32(
39 match profile.mode() {
40 TurboMode::PolarOnly => 0,
41 TurboMode::PolarWithQjl => code.residual_sketch.projections,
42 },
43 "qjl sign count",
44 )?;
45 let packed_angle_indices =
46 bitpack::pack_indices(&code.polar_code.angle_indices, polar_bits)?;
47 let packed_signs = match profile.mode() {
48 TurboMode::PolarOnly => Vec::new(),
49 TurboMode::PolarWithQjl => bitpack::pack_signs(&code.residual_sketch.signs)?,
50 };
51 let payload_len = checked_u64(
52 code.polar_code.radii.len() * 4 + packed_angle_indices.len() + packed_signs.len(),
53 "payload length",
54 )?;
55
56 let mut bytes = Vec::with_capacity(42 + payload_len as usize);
57 bytes.extend_from_slice(TURBO_CODE_WIRE_MAGIC);
58 bytes.extend_from_slice(&VERSION.to_le_bytes());
59 bytes.extend_from_slice(&rotation_flag(profile.rotation_kind()).to_le_bytes());
60 bytes.push(VARIANT_TURBO_CODE);
61 bytes.push(0);
62 bytes.extend_from_slice(&dim.to_le_bytes());
63 bytes.push(polar_bits);
64 bytes.extend_from_slice(&[0, 0, 0]);
65 bytes.extend_from_slice(&qjl_projections.to_le_bytes());
66 bytes.extend_from_slice(&profile.seed().to_le_bytes());
67 bytes.extend_from_slice(&polar_block_count.to_le_bytes());
68 bytes.extend_from_slice(&qjl_sign_count.to_le_bytes());
69 bytes.extend_from_slice(&payload_len.to_le_bytes());
70
71 for radius in &code.polar_code.radii {
72 bytes.extend_from_slice(&radius.to_le_bytes());
73 }
74 bytes.extend_from_slice(&packed_angle_indices);
75 bytes.extend_from_slice(&packed_signs);
76 Ok(bytes)
77 }
78
79 pub fn decode(bytes: &[u8], profile: &TurboQuantizer) -> Result<TurboCode> {
81 let mut cursor = WireCursor::new(bytes);
82 if cursor.read_exact(TURBO_CODE_WIRE_MAGIC.len())? != TURBO_CODE_WIRE_MAGIC {
83 return Err(TurboQuantError::MalformedCode {
84 reason: "wrong TurboQuant wire magic".into(),
85 });
86 }
87 let version = cursor.read_u16()?;
88 if version != VERSION {
89 return Err(TurboQuantError::MalformedCode {
90 reason: format!("unsupported TurboQuant wire version {version}"),
91 });
92 }
93 let wire_rotation_flag = cursor.read_u16()?;
94 let expected_rotation_flag = rotation_flag(profile.rotation_kind());
95 if wire_rotation_flag != expected_rotation_flag {
96 return Err(TurboQuantError::MalformedCode {
97 reason: format!(
98 "wire rotation flag {wire_rotation_flag} does not match quantizer profile flag {expected_rotation_flag}"
99 ),
100 });
101 }
102 let variant = cursor.read_u8()?;
103 if variant != VARIANT_TURBO_CODE {
104 return Err(TurboQuantError::MalformedCode {
105 reason: format!("unsupported TurboQuant wire variant {variant}"),
106 });
107 }
108 let reserved = cursor.read_u8()?;
109 if reserved != 0 {
110 return Err(TurboQuantError::MalformedCode {
111 reason: "nonzero TurboQuant wire reserved byte".into(),
112 });
113 }
114
115 let dim = cursor.read_u32()? as usize;
116 let polar_bits = cursor.read_u8()?;
117 let reserved2 = cursor.read_exact(3)?;
118 if reserved2 != [0, 0, 0] {
119 return Err(TurboQuantError::MalformedCode {
120 reason: "nonzero TurboQuant wire reserved bytes".into(),
121 });
122 }
123 let qjl_projections = cursor.read_u32()? as usize;
124 let seed = cursor.read_u64()?;
125 let polar_block_count = cursor.read_u32()? as usize;
126 let qjl_sign_count = cursor.read_u32()? as usize;
127 let payload_len = cursor.read_u64()?;
128 let payload_start = cursor.offset();
129
130 let expected_polar_bits = match profile.mode() {
131 TurboMode::PolarOnly => profile.bits(),
132 TurboMode::PolarWithQjl => profile.bits() - 1,
133 };
134 if dim != profile.dim()
135 || polar_bits != expected_polar_bits
136 || qjl_projections != profile.projections()
137 {
138 return Err(TurboQuantError::MalformedCode {
139 reason: "wire header does not match quantizer profile".into(),
140 });
141 }
142 if seed != profile.seed() {
143 return Err(TurboQuantError::MalformedCode {
144 reason: format!(
145 "wire seed {seed} does not match quantizer profile seed {}",
146 profile.seed()
147 ),
148 });
149 }
150 if polar_block_count != profile.dim() / 2 {
151 return Err(TurboQuantError::MalformedCode {
152 reason: format!(
153 "wire polar block count {polar_block_count} does not match dimension {}",
154 profile.dim()
155 ),
156 });
157 }
158 let expected_qjl_sign_count = match profile.mode() {
159 TurboMode::PolarOnly => 0,
160 TurboMode::PolarWithQjl => profile.projections(),
161 };
162 if qjl_sign_count != expected_qjl_sign_count {
163 return Err(TurboQuantError::MalformedCode {
164 reason: format!(
165 "wire sign count {qjl_sign_count} does not match expected {expected_qjl_sign_count}"
166 ),
167 });
168 }
169 let angle_bytes = bitpack::packed_len(polar_block_count, polar_bits)?;
170 let sign_bytes = match profile.mode() {
171 TurboMode::PolarOnly => 0,
172 TurboMode::PolarWithQjl => profile.projections().div_ceil(8),
173 };
174 let residual_bytes = sign_bytes;
175 let expected_payload_len = checked_u64(
176 polar_block_count * 4 + angle_bytes + residual_bytes,
177 "expected payload length",
178 )?;
179 if payload_len != expected_payload_len {
180 return Err(TurboQuantError::MalformedCode {
181 reason: format!(
182 "TurboQuant wire payload length {payload_len} does not match expected {expected_payload_len}"
183 ),
184 });
185 }
186 if payload_len > cursor.remaining_len() as u64 {
187 return Err(TurboQuantError::MalformedCode {
188 reason: "TurboQuant wire payload length exceeds remaining bytes".into(),
189 });
190 }
191
192 let mut radii = Vec::with_capacity(polar_block_count);
193 for _ in 0..polar_block_count {
194 radii.push(cursor.read_f32()?);
195 }
196 let packed_angle_indices = cursor.read_exact(angle_bytes)?.to_vec();
197 let angle_indices =
198 bitpack::unpack_indices(&packed_angle_indices, polar_block_count, polar_bits)?;
199 let residual_sketch = match profile.mode() {
200 TurboMode::PolarOnly => QjlSketch {
201 dim: profile.dim(),
202 projections: 0,
203 signs: Vec::new(),
204 },
205 TurboMode::PolarWithQjl => {
206 let packed_signs = cursor.read_exact(sign_bytes)?.to_vec();
207 let signs = bitpack::unpack_signs(&packed_signs, profile.projections())?;
208 QjlSketch {
209 dim: profile.dim(),
210 projections: profile.projections(),
211 signs,
212 }
213 }
214 };
215 if cursor.offset() - payload_start != payload_len as usize {
216 return Err(TurboQuantError::MalformedCode {
217 reason: "TurboQuant wire payload length mismatch".into(),
218 });
219 }
220 cursor.finish()?;
221
222 let code = TurboCode {
223 polar_code: PolarCode {
224 dim: profile.dim(),
225 bits: polar_bits,
226 radii,
227 angle_indices,
228 },
229 residual_sketch,
230 };
231 code.validate_for(
232 profile.dim(),
233 profile.bits(),
234 profile.projections(),
235 profile.mode(),
236 )?;
237 Ok(code)
238 }
239}
240
241fn checked_u32(value: usize, field: &str) -> Result<u32> {
242 u32::try_from(value).map_err(|_| TurboQuantError::MalformedCode {
243 reason: format!("{field} {value} does not fit u32 wire field"),
244 })
245}
246
247fn checked_u64(value: usize, field: &str) -> Result<u64> {
248 u64::try_from(value).map_err(|_| TurboQuantError::MalformedCode {
249 reason: format!("{field} {value} does not fit u64 wire field"),
250 })
251}
252
253fn rotation_flag(kind: RotationKind) -> u16 {
254 match kind {
255 RotationKind::Auto => 0,
256 RotationKind::FastHadamard => 1,
257 RotationKind::StoredQr => 2,
258 }
259}
260
261struct WireCursor<'a> {
262 bytes: &'a [u8],
263 offset: usize,
264}
265
266#[derive(Debug, Clone, PartialEq, Eq)]
271pub struct TurboCodeWireHeader {
272 pub dim: usize,
274 pub polar_bits: u8,
276 pub qjl_projections: usize,
278 pub seed: u64,
280 pub polar_block_count: usize,
282 pub qjl_sign_count: usize,
284 pub payload_len: u64,
286 pub rotation_kind: RotationKind,
288}
289
290impl TurboCodeWireV1 {
291 pub fn parse_header(bytes: &[u8]) -> Result<TurboCodeWireHeader> {
295 if bytes.len() < 44 {
296 return Err(TurboQuantError::MalformedCode {
297 reason: format!("TurboQuant wire header is {} bytes, need 44", bytes.len()),
298 });
299 }
300 if &bytes[0..4] != TURBO_CODE_WIRE_MAGIC {
301 return Err(TurboQuantError::MalformedCode {
302 reason: "wrong TurboQuant wire magic".into(),
303 });
304 }
305 let version = u16::from_le_bytes(bytes[4..6].try_into().unwrap());
306 if version != VERSION {
307 return Err(TurboQuantError::MalformedCode {
308 reason: format!("unsupported TurboQuant wire version {version}"),
309 });
310 }
311 let wire_rotation_flag = u16::from_le_bytes(bytes[6..8].try_into().unwrap());
312 let rotation_kind = match wire_rotation_flag {
313 0 => RotationKind::Auto,
314 1 => RotationKind::FastHadamard,
315 2 => RotationKind::StoredQr,
316 _ => {
317 return Err(TurboQuantError::MalformedCode {
318 reason: format!("unknown TurboQuant rotation flag {wire_rotation_flag}"),
319 })
320 }
321 };
322 let variant = bytes[8];
323 if variant != VARIANT_TURBO_CODE {
324 return Err(TurboQuantError::MalformedCode {
325 reason: format!("unsupported TurboQuant wire variant {variant}"),
326 });
327 }
328 let reserved = bytes[9];
329 if reserved != 0 {
330 return Err(TurboQuantError::MalformedCode {
331 reason: "nonzero TurboQuant wire reserved byte".into(),
332 });
333 }
334 let dim = u32::from_le_bytes(bytes[10..14].try_into().unwrap()) as usize;
335 let polar_bits = bytes[14];
336 let reserved2: [u8; 3] = bytes[15..18].try_into().unwrap();
337 if reserved2 != [0, 0, 0] {
338 return Err(TurboQuantError::MalformedCode {
339 reason: "nonzero TurboQuant wire reserved bytes".into(),
340 });
341 }
342 let qjl_projections = u32::from_le_bytes(bytes[18..22].try_into().unwrap()) as usize;
343 let seed = u64::from_le_bytes(bytes[22..30].try_into().unwrap());
344 let polar_block_count = u32::from_le_bytes(bytes[30..34].try_into().unwrap()) as usize;
345 let qjl_sign_count = u32::from_le_bytes(bytes[34..38].try_into().unwrap()) as usize;
346 let payload_len = u64::from_le_bytes(bytes[38..46].try_into().unwrap());
347 Ok(TurboCodeWireHeader {
348 dim,
349 polar_bits,
350 qjl_projections,
351 seed,
352 polar_block_count,
353 qjl_sign_count,
354 payload_len,
355 rotation_kind,
356 })
357 }
358}
359
360impl<'a> WireCursor<'a> {
361 fn new(bytes: &'a [u8]) -> Self {
362 Self { bytes, offset: 0 }
363 }
364
365 fn offset(&self) -> usize {
366 self.offset
367 }
368
369 fn remaining_len(&self) -> usize {
370 self.bytes.len().saturating_sub(self.offset)
371 }
372
373 fn read_exact(&mut self, len: usize) -> Result<&'a [u8]> {
374 let end = self
375 .offset
376 .checked_add(len)
377 .ok_or_else(|| TurboQuantError::MalformedCode {
378 reason: "wire offset overflow".into(),
379 })?;
380 if end > self.bytes.len() {
381 return Err(TurboQuantError::MalformedCode {
382 reason: "truncated TurboQuant wire artifact".into(),
383 });
384 }
385 let out = &self.bytes[self.offset..end];
386 self.offset = end;
387 Ok(out)
388 }
389
390 fn read_u8(&mut self) -> Result<u8> {
391 Ok(self.read_exact(1)?[0])
392 }
393
394 fn read_u16(&mut self) -> Result<u16> {
395 let bytes = self.read_exact(2)?;
396 Ok(u16::from_le_bytes([bytes[0], bytes[1]]))
397 }
398
399 fn read_u32(&mut self) -> Result<u32> {
400 let bytes = self.read_exact(4)?;
401 Ok(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
402 }
403
404 fn read_u64(&mut self) -> Result<u64> {
405 let bytes = self.read_exact(8)?;
406 Ok(u64::from_le_bytes([
407 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
408 ]))
409 }
410
411 fn read_f32(&mut self) -> Result<f32> {
412 let bytes = self.read_exact(4)?;
413 Ok(f32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
414 }
415
416 fn finish(&self) -> Result<()> {
417 if self.offset != self.bytes.len() {
418 return Err(TurboQuantError::MalformedCode {
419 reason: "trailing bytes in TurboQuant wire artifact".into(),
420 });
421 }
422 Ok(())
423 }
424}
425
426#[cfg(test)]
427mod tests {
428 use super::*;
429
430 fn make_quantizer(dim: usize, seed: u64) -> TurboQuantizer {
431 TurboQuantizer::new(dim, 8, 32, seed).expect("quantizer build")
433 }
434
435 #[test]
436 fn parse_header_round_trips_encoded_code() {
437 let q = make_quantizer(128, 42);
438 let vector: Vec<f32> = (0..128).map(|i| (i as f32 / 128.0) - 0.5).collect();
439 let code = q.encode(&vector).expect("encode");
440 let wire = TurboCodeWireV1::encode(&code, &q).expect("wire encode");
441
442 let header = TurboCodeWireV1::parse_header(&wire).expect("parse header");
443 assert_eq!(header.dim, 128);
444 assert_eq!(header.qjl_projections, 32);
445 assert_eq!(header.seed, 42);
446 assert!(header.polar_block_count > 0);
447 assert!(header.payload_len > 0);
448 }
449
450 #[test]
451 fn parse_header_rejects_short_buffer() {
452 let bytes = vec![0u8; 10];
453 let result = TurboCodeWireV1::parse_header(&bytes);
454 assert!(result.is_err());
455 }
456
457 #[test]
458 fn parse_header_rejects_bad_magic() {
459 let mut bytes = vec![0u8; 44];
460 bytes[0..4].copy_from_slice(b"XXXX");
461 let result = TurboCodeWireV1::parse_header(&bytes);
462 assert!(result.is_err());
463 }
464
465 #[test]
466 fn parse_header_rejects_unsupported_version() {
467 let mut bytes = vec![0u8; 44];
468 bytes[0..4].copy_from_slice(TURBO_CODE_WIRE_MAGIC);
469 bytes[4..6].copy_from_slice(&99u16.to_le_bytes());
471 let result = TurboCodeWireV1::parse_header(&bytes);
472 assert!(result.is_err());
473 }
474}