1use crate::error::{Error, Result};
8use crate::layout::{align_up, slot_size_align};
9use crate::schema::{Schema, Type};
10use crate::value::Value;
11
12pub const MESSAGE_MAGIC: &[u8; 4] = b"VRT2";
13pub const FLAG_INLINE_SCHEMA: u16 = 1;
14pub const HEADER_LEN: usize = 32;
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18pub enum SchemaMode {
19 Inline,
21 HashOnly,
24}
25
26pub fn encode(schema: &Schema, root: &Value, mode: SchemaMode) -> Result<Vec<u8>> {
27 let root_fields = match root {
28 Value::Struct(fields) => fields,
29 other => {
30 return Err(Error::TypeMismatch {
31 expected: "struct".into(),
32 got: other.kind().into(),
33 })
34 }
35 };
36 let mut enc = Encoder {
37 schema,
38 buf: Vec::with_capacity(256),
39 };
40 enc.buf.extend_from_slice(MESSAGE_MAGIC);
41 let inline = mode == SchemaMode::Inline;
42 let flags: u16 = if inline { FLAG_INLINE_SCHEMA } else { 0 };
43 enc.buf.extend_from_slice(&flags.to_le_bytes());
44 enc.buf.extend_from_slice(&0u16.to_le_bytes()); enc.buf.extend_from_slice(&schema.id().to_le_bytes()); enc.buf.extend_from_slice(&0u32.to_le_bytes()); let schema_len = if inline {
48 schema.canonical_bytes().len()
49 } else {
50 0
51 };
52 let schema_len_u32 = u32::try_from(schema_len).map_err(|_| Error::MessageTooLarge)?;
53 enc.buf.extend_from_slice(&schema_len_u32.to_le_bytes());
54 if inline {
55 enc.buf.extend_from_slice(schema.canonical_bytes());
56 }
57 enc.pad_to(8)?;
58 let root_off = enc.write_struct(schema.root_index(), root_fields)?;
59 enc.buf[24..28].copy_from_slice(&root_off.to_le_bytes());
60 Ok(enc.buf)
61}
62
63enum ElemKind {
64 Scalar,
65 Ref,
66 InlineStruct(u16),
67}
68
69fn elem_info(schema: &Schema, elem: &Type) -> (u32, u32, ElemKind) {
70 match elem {
71 Type::Struct(i) => match schema.layout_unchecked(*i) {
72 crate::layout::StructLayout::Fixed(f) => (f.size, f.align, ElemKind::InlineStruct(*i)),
76 crate::layout::StructLayout::Packed(_) => (4, 4, ElemKind::Ref),
77 },
78 Type::String | Type::Bytes | Type::List(_) | Type::Map(_, _) | Type::Union(_) => {
79 (4, 4, ElemKind::Ref)
80 }
81 other => {
82 let (size, align) = slot_size_align(other);
83 (size, align, ElemKind::Scalar)
84 }
85 }
86}
87
88fn key_cmp(a: &Value, b: &Value) -> std::cmp::Ordering {
94 use std::cmp::Ordering::Equal;
95 use Value::*;
96 match (a, b) {
97 (Bool(x), Bool(y)) => x.cmp(y),
98 (U8(x), U8(y)) => x.cmp(y),
99 (U16(x), U16(y)) => x.cmp(y),
100 (U32(x), U32(y)) => x.cmp(y),
101 (U64(x), U64(y)) => x.cmp(y),
102 (I8(x), I8(y)) => x.cmp(y),
103 (I16(x), I16(y)) => x.cmp(y),
104 (I32(x), I32(y)) => x.cmp(y),
105 (I64(x), I64(y)) => x.cmp(y),
106 (Enum(x), Enum(y)) => x.cmp(y),
107 (Str(x), Str(y)) => x.as_bytes().cmp(y.as_bytes()),
108 _ => Equal,
111 }
112}
113
114fn type_mismatch(schema: &Schema, expected: &Type, got: &Value) -> Error {
115 Error::TypeMismatch {
116 expected: expected.describe(schema),
117 got: got.kind().into(),
118 }
119}
120
121struct Encoder<'s> {
122 schema: &'s Schema,
123 buf: Vec<u8>,
124}
125
126impl<'s> Encoder<'s> {
127 fn pos(&self) -> Result<u32> {
128 u32::try_from(self.buf.len()).map_err(|_| Error::MessageTooLarge)
129 }
130
131 fn pad_to(&mut self, align: u32) -> Result<u32> {
132 let pos = self.pos()?;
133 let target = align_up(pos, align);
134 self.buf.resize(self.buf.len() + (target - pos) as usize, 0);
135 Ok(target)
136 }
137
138 fn patch_u32(&mut self, at: u32, v: u32) {
139 let at = at as usize;
140 self.buf[at..at + 4].copy_from_slice(&v.to_le_bytes());
141 }
142
143 fn alloc_struct_block(&mut self, type_index: u16) -> Result<u32> {
145 let lay = self.schema.layout_unchecked(type_index).as_fixed();
146 let (align, size) = (lay.align, lay.size);
147 let base = self.pad_to(align)?;
148 self.buf.resize(self.buf.len() + size as usize, 0);
149 self.pos()?; Ok(base)
151 }
152
153 fn write_struct(&mut self, type_index: u16, values: &[(u16, Value)]) -> Result<u32> {
154 if self.schema.struct_def_unchecked(type_index).is_packed() {
155 return self.write_packed_struct(type_index, values);
156 }
157 let base = self.alloc_struct_block(type_index)?;
158 self.fill_struct_at(base, type_index, values)?;
159 Ok(base)
160 }
161
162 fn fill_struct_at(
166 &mut self,
167 base: u32,
168 type_index: u16,
169 values: &[(u16, Value)],
170 ) -> Result<()> {
171 let schema = self.schema;
172 let sd = schema.struct_def_unchecked(type_index);
173 let lay = schema.layout_unchecked(type_index).as_fixed();
174 let mut heap_jobs: Vec<(u32, &Value, &'s Type)> = Vec::new();
175 let mut seen = vec![false; sd.fields.len()];
176 for (id, value) in values {
177 let pos = sd
178 .fields
179 .binary_search_by_key(id, |f| f.id)
180 .map_err(|_| Error::UnknownFieldId(*id))?;
181 if seen[pos] {
182 return Err(Error::DuplicateField(*id));
183 }
184 seen[pos] = true;
185 if !sd.is_dense() {
186 let bit_at = (base + pos as u32 / 8) as usize;
187 self.buf[bit_at] |= 1 << (pos % 8);
188 }
189 let slot = base + lay.slots[pos];
190 let ty = &sd.fields[pos].ty;
191 match ty {
192 Type::String
193 | Type::Bytes
194 | Type::List(_)
195 | Type::Struct(_)
196 | Type::Map(_, _)
197 | Type::Union(_) => {
198 let ok = matches!(
200 (ty, value),
201 (Type::String, Value::Str(_))
202 | (Type::Bytes, Value::Bytes(_))
203 | (Type::List(_), Value::List(_))
204 | (Type::List(_), Value::Scalars(_))
205 | (Type::Struct(_), Value::Struct(_))
206 | (Type::Map(_, _), Value::Map(_))
207 | (Type::Union(_), Value::Union(..))
208 );
209 if !ok {
210 return Err(type_mismatch(schema, ty, value));
211 }
212 heap_jobs.push((slot, value, ty));
213 }
214 _ => self.store_scalar_at(slot, value, ty)?,
215 }
216 }
217 if sd.is_dense() {
218 if let Some(pos) = seen.iter().position(|s| !s) {
219 return Err(Error::MissingField(sd.fields[pos].id));
220 }
221 }
222 for (slot, value, ty) in heap_jobs {
223 let off = self.write_heap(value, ty)?;
224 self.patch_u32(slot, off);
225 }
226 Ok(())
227 }
228
229 fn write_packed_struct(&mut self, type_index: u16, values: &[(u16, Value)]) -> Result<u32> {
232 let schema = self.schema;
233 let sd = schema.struct_def_unchecked(type_index);
234 let lay = schema.layout_unchecked(type_index).as_packed();
235
236 let mut bitmap = 0u64;
238 let mut present: Vec<(usize, &Value, &'s Type)> = Vec::with_capacity(values.len());
239 for (id, value) in values {
240 let pos = sd
241 .fields
242 .binary_search_by_key(id, |f| f.id)
243 .map_err(|_| Error::UnknownFieldId(*id))?;
244 let bit = 1u64 << pos;
245 if bitmap & bit != 0 {
246 return Err(Error::DuplicateField(*id));
247 }
248 bitmap |= bit;
249 present.push((pos, value, &sd.fields[pos].ty));
250 }
251
252 let size = lay.block_size(bitmap);
253 let base = self.pad_to(lay.align)?;
254 self.buf.resize(self.buf.len() + size as usize, 0);
255 self.pos()?;
256 let bmap_bytes = bitmap.to_le_bytes();
258 let bstart = base as usize;
259 self.buf[bstart..bstart + lay.bitmap_bytes as usize]
260 .copy_from_slice(&bmap_bytes[..lay.bitmap_bytes as usize]);
261
262 let mut heap_jobs: Vec<(u32, &Value, &'s Type)> = Vec::new();
263 for (pos, value, ty) in present {
264 let slot = base + lay.field_offset(bitmap, pos);
265 match ty {
266 Type::String
267 | Type::Bytes
268 | Type::List(_)
269 | Type::Struct(_)
270 | Type::Map(_, _)
271 | Type::Union(_) => {
272 let ok = matches!(
273 (ty, value),
274 (Type::String, Value::Str(_))
275 | (Type::Bytes, Value::Bytes(_))
276 | (Type::List(_), Value::List(_))
277 | (Type::List(_), Value::Scalars(_))
278 | (Type::Struct(_), Value::Struct(_))
279 | (Type::Map(_, _), Value::Map(_))
280 | (Type::Union(_), Value::Union(..))
281 );
282 if !ok {
283 return Err(type_mismatch(schema, ty, value));
284 }
285 heap_jobs.push((slot, value, ty));
286 }
287 _ => self.store_scalar_at(slot, value, ty)?,
288 }
289 }
290 for (slot, value, ty) in heap_jobs {
291 let off = self.write_heap(value, ty)?;
292 self.patch_u32(slot, off);
293 }
294 Ok(base)
295 }
296
297 fn store_scalar_at(&mut self, at: u32, value: &Value, ty: &Type) -> Result<()> {
299 let at = at as usize;
300 let buf = &mut self.buf;
301 macro_rules! put {
302 ($bytes:expr) => {{
303 let b = $bytes;
304 buf[at..at + b.len()].copy_from_slice(&b);
305 }};
306 }
307 match (ty, value) {
308 (Type::Bool, Value::Bool(x)) => buf[at] = *x as u8,
309 (Type::U8, Value::U8(x)) => buf[at] = *x,
310 (Type::U16, Value::U16(x)) => put!(x.to_le_bytes()),
311 (Type::U32, Value::U32(x)) => put!(x.to_le_bytes()),
312 (Type::U64, Value::U64(x)) => put!(x.to_le_bytes()),
313 (Type::I8, Value::I8(x)) => buf[at] = *x as u8,
314 (Type::I16, Value::I16(x)) => put!(x.to_le_bytes()),
315 (Type::I32, Value::I32(x)) => put!(x.to_le_bytes()),
316 (Type::I64, Value::I64(x)) => put!(x.to_le_bytes()),
317 (Type::F32, Value::F32(x)) => put!(x.to_le_bytes()),
318 (Type::F64, Value::F64(x)) => put!(x.to_le_bytes()),
319 (Type::Enum(_), Value::Enum(x)) => put!(x.to_le_bytes()),
320 _ => return Err(type_mismatch(self.schema, ty, value)),
321 }
322 Ok(())
323 }
324
325 fn push_scalar(&mut self, value: &Value, ty: &Type) -> Result<()> {
327 let buf = &mut self.buf;
328 match (ty, value) {
329 (Type::Bool, Value::Bool(x)) => buf.push(*x as u8),
330 (Type::U8, Value::U8(x)) => buf.push(*x),
331 (Type::U16, Value::U16(x)) => buf.extend_from_slice(&x.to_le_bytes()),
332 (Type::U32, Value::U32(x)) => buf.extend_from_slice(&x.to_le_bytes()),
333 (Type::U64, Value::U64(x)) => buf.extend_from_slice(&x.to_le_bytes()),
334 (Type::I8, Value::I8(x)) => buf.push(*x as u8),
335 (Type::I16, Value::I16(x)) => buf.extend_from_slice(&x.to_le_bytes()),
336 (Type::I32, Value::I32(x)) => buf.extend_from_slice(&x.to_le_bytes()),
337 (Type::I64, Value::I64(x)) => buf.extend_from_slice(&x.to_le_bytes()),
338 (Type::F32, Value::F32(x)) => buf.extend_from_slice(&x.to_le_bytes()),
339 (Type::F64, Value::F64(x)) => buf.extend_from_slice(&x.to_le_bytes()),
340 (Type::Enum(_), Value::Enum(x)) => buf.extend_from_slice(&x.to_le_bytes()),
341 _ => return Err(type_mismatch(self.schema, ty, value)),
342 }
343 Ok(())
344 }
345
346 fn write_heap(&mut self, value: &Value, ty: &Type) -> Result<u32> {
349 match (ty, value) {
350 (Type::String, Value::Str(s)) => self.write_blob(s.as_bytes()),
351 (Type::Bytes, Value::Bytes(b)) => self.write_blob(b),
352 (Type::Struct(i), Value::Struct(fields)) => self.write_struct(*i, fields),
353 (Type::List(elem), Value::List(items)) => self.write_list(elem, items),
354 (Type::List(elem), Value::Scalars(runs)) => self.write_scalar_list(elem, runs),
355 (Type::Map(k, v), Value::Map(entries)) => self.write_map(k, v, entries),
356 (Type::Union(variants), Value::Union(tag, inner)) => {
357 self.write_union(variants, *tag, inner)
358 }
359 _ => Err(type_mismatch(self.schema, ty, value)),
360 }
361 }
362
363 fn write_union(&mut self, variants: &[Type], tag: u32, inner: &Value) -> Result<u32> {
366 let vty = variants.get(tag as usize).ok_or(Error::BadUnionTag(tag))?;
367 let (pslot, palign) = slot_size_align(vty);
368 let payload_off = crate::layout::align_up(4, palign);
369 let block_align = palign.max(4);
370 let block_size = crate::layout::align_up(payload_off + pslot, block_align);
371 let base = self.pad_to(block_align)?;
372 self.buf.resize(self.buf.len() + block_size as usize, 0);
373 self.pos()?;
374 self.patch_u32(base, tag);
375 let slot = base + payload_off;
376 match vty {
377 Type::String
378 | Type::Bytes
379 | Type::List(_)
380 | Type::Struct(_)
381 | Type::Map(_, _)
382 | Type::Union(_) => {
383 let off = self.write_heap(inner, vty)?;
384 self.patch_u32(slot, off);
385 }
386 _ => self.store_scalar_at(slot, inner, vty)?,
387 }
388 Ok(base)
389 }
390
391 fn write_map(
395 &mut self,
396 key_ty: &Type,
397 val_ty: &Type,
398 entries: &[(Value, Value)],
399 ) -> Result<u32> {
400 let lay = crate::layout::map_entry_layout(key_ty, val_ty);
401 let (key_slot, val_slot) = (lay.slots[0], lay.slots[1]);
402
403 let mut order: Vec<usize> = (0..entries.len()).collect();
406 order.sort_by(|&i, &j| key_cmp(&entries[i].0, &entries[j].0));
407 for w in order.windows(2) {
408 if key_cmp(&entries[w[0]].0, &entries[w[1]].0) == std::cmp::Ordering::Equal {
409 return Err(Error::DuplicateMapKey);
410 }
411 }
412
413 let count = u32::try_from(entries.len()).map_err(|_| Error::MessageTooLarge)?;
414 let off = self.pad_to(4)?;
415 self.buf.extend_from_slice(&count.to_le_bytes());
416 let base = self.pad_to(lay.align)?;
417 let total = (lay.size as usize)
418 .checked_mul(entries.len())
419 .ok_or(Error::MessageTooLarge)?;
420 self.buf.resize(self.buf.len() + total, 0);
421 self.pos()?;
422
423 let mut heap_jobs: Vec<(u32, &Value, &Type)> = Vec::new();
426 for (rank, &i) in order.iter().enumerate() {
427 let entry_base = base + rank as u32 * lay.size;
428 for (slot_off, ty, val) in [
429 (key_slot, key_ty, &entries[i].0),
430 (val_slot, val_ty, &entries[i].1),
431 ] {
432 let slot = entry_base + slot_off;
433 match ty {
434 Type::String
435 | Type::Bytes
436 | Type::List(_)
437 | Type::Struct(_)
438 | Type::Map(_, _) => {
439 heap_jobs.push((slot, val, ty));
440 }
441 _ => self.store_scalar_at(slot, val, ty)?,
442 }
443 }
444 }
445 for (slot, val, ty) in heap_jobs {
446 let child = self.write_heap(val, ty)?;
447 self.patch_u32(slot, child);
448 }
449 Ok(off)
450 }
451
452 fn write_blob(&mut self, bytes: &[u8]) -> Result<u32> {
453 let len = u32::try_from(bytes.len()).map_err(|_| Error::MessageTooLarge)?;
454 let off = self.pad_to(4)?;
455 self.buf.extend_from_slice(&len.to_le_bytes());
456 self.buf.extend_from_slice(bytes);
457 self.pos()?;
458 Ok(off)
459 }
460
461 fn write_scalar_list(&mut self, elem: &Type, runs: &crate::value::Scalars) -> Result<u32> {
470 use crate::value::Scalars;
471 let count = u32::try_from(runs.len()).map_err(|_| Error::MessageTooLarge)?;
472 let (_, elem_align, kind) = elem_info(self.schema, elem);
473 if !matches!(kind, ElemKind::Scalar) {
474 return Err(type_mismatch(
475 self.schema,
476 elem,
477 &Value::Scalars(runs.clone()),
478 ));
479 }
480 let off = self.pad_to(4)?;
481 self.buf.extend_from_slice(&count.to_le_bytes());
482 self.pad_to(elem_align)?;
483
484 macro_rules! run {
487 ($values:expr) => {{
488 self.buf
489 .reserve($values.len() * std::mem::size_of_val(&$values[0]));
490 for x in $values {
491 self.buf.extend_from_slice(&x.to_le_bytes());
492 }
493 }};
494 }
495 match (elem, runs) {
496 (Type::Bool, Scalars::Bool(v)) => {
497 self.buf.reserve(v.len());
498 for x in v {
499 self.buf.push(*x as u8);
500 }
501 }
502 (Type::U8, Scalars::U8(v)) => self.buf.extend_from_slice(v),
503 (Type::I8, Scalars::I8(v)) => {
504 self.buf.reserve(v.len());
505 for x in v {
506 self.buf.push(*x as u8);
507 }
508 }
509 (Type::U16, Scalars::U16(v)) => run!(v),
510 (Type::U32, Scalars::U32(v)) => run!(v),
511 (Type::U64, Scalars::U64(v)) => run!(v),
512 (Type::I16, Scalars::I16(v)) => run!(v),
513 (Type::I32, Scalars::I32(v)) => run!(v),
514 (Type::I64, Scalars::I64(v)) => run!(v),
515 (Type::F32, Scalars::F32(v)) => run!(v),
516 (Type::F64, Scalars::F64(v)) => run!(v),
517 _ => {
518 return Err(type_mismatch(
519 self.schema,
520 elem,
521 &Value::Scalars(runs.clone()),
522 ))
523 }
524 }
525 self.pos()?;
526 Ok(off)
527 }
528
529 fn write_list(&mut self, elem: &Type, items: &[Value]) -> Result<u32> {
530 let schema = self.schema;
531 let (stride, elem_align, kind) = elem_info(schema, elem);
532 let count = u32::try_from(items.len()).map_err(|_| Error::MessageTooLarge)?;
533 let off = self.pad_to(4)?;
534 self.buf.extend_from_slice(&count.to_le_bytes());
535 self.pad_to(elem_align)?;
536 match kind {
537 ElemKind::Scalar => {
538 for item in items {
539 self.push_scalar(item, elem)?;
540 }
541 }
542 ElemKind::Ref => {
543 let slots_base = self.pos()?;
544 self.buf.resize(
545 self.buf.len() + items.len().checked_mul(4).ok_or(Error::MessageTooLarge)?,
546 0,
547 );
548 self.pos()?;
549 for (i, item) in items.iter().enumerate() {
550 let child = self.write_heap(item, elem)?;
551 self.patch_u32(slots_base + (i as u32) * 4, child);
552 }
553 }
554 ElemKind::InlineStruct(type_index) => {
555 let base = self.pos()?;
556 let total = (stride as usize)
557 .checked_mul(items.len())
558 .ok_or(Error::MessageTooLarge)?;
559 self.buf.resize(self.buf.len() + total, 0);
560 self.pos()?;
561 for (i, item) in items.iter().enumerate() {
562 let fields = match item {
563 Value::Struct(fields) => fields,
564 other => return Err(type_mismatch(schema, elem, other)),
565 };
566 self.fill_struct_at(base + (i as u32) * stride, type_index, fields)?;
567 }
568 }
569 }
570 self.pos()?;
571 Ok(off)
572 }
573}