use std::collections::{HashMap, HashSet};
use std::sync::OnceLock;
use facet_core::{EnumRepr, Facet, ScalarType, Shape, Type, UserType};
use vox_jit_cal::{BorrowMode, CalibrationRegistry, DescriptorHandle};
use vox_schema::{SchemaKind, SchemaRegistry};
use crate::error::DeserializeError;
use crate::plan::{FieldOp, TranslationPlan};
fn trace_lower_enabled() -> bool {
static FLAG: OnceLock<bool> = OnceLock::new();
*FLAG.get_or_init(|| {
std::env::var_os("VOX_JIT_TRACE_LOWER")
.map(|v| !v.is_empty())
.unwrap_or(false)
})
}
fn trace_cycle_emission(
ir: &str,
op: &str,
shape: &'static Shape,
top_shape: Option<&'static Shape>,
in_progress: &HashSet<&'static Shape>,
) {
if !trace_lower_enabled() {
return;
}
let top = top_shape
.map(|s| format!("{s}"))
.unwrap_or_else(|| "<none>".to_owned());
let in_progress_list = in_progress
.iter()
.map(|s| format!("{s}"))
.collect::<Vec<_>>()
.join(", ");
eprintln!(
"[vox-jit-trace] ir={ir} op={op} shape@{:p}={shape} top={top} in_progress=[{in_progress_list}]",
shape as *const Shape,
);
}
pub use vox_jit_abi::wire::{OpaqueDescriptorId, TagWidth, WirePrimitive};
pub fn wire_primitive_from_scalar(s: ScalarType) -> Option<WirePrimitive> {
Some(match s {
ScalarType::Unit => WirePrimitive::Unit,
ScalarType::Bool => WirePrimitive::Bool,
ScalarType::U8 => WirePrimitive::U8,
ScalarType::U16 => WirePrimitive::U16,
ScalarType::U32 => WirePrimitive::U32,
ScalarType::U64 => WirePrimitive::U64,
ScalarType::U128 => WirePrimitive::U128,
ScalarType::USize => WirePrimitive::USize,
ScalarType::I8 => WirePrimitive::I8,
ScalarType::I16 => WirePrimitive::I16,
ScalarType::I32 => WirePrimitive::I32,
ScalarType::I64 => WirePrimitive::I64,
ScalarType::I128 => WirePrimitive::I128,
ScalarType::ISize => WirePrimitive::ISize,
ScalarType::F32 => WirePrimitive::F32,
ScalarType::F64 => WirePrimitive::F64,
ScalarType::String => WirePrimitive::String,
ScalarType::Str => WirePrimitive::String,
ScalarType::CowStr => WirePrimitive::String,
ScalarType::Char => WirePrimitive::Char,
_ => return None,
})
}
pub fn tag_width_from_enum_repr(repr: EnumRepr) -> Option<TagWidth> {
match repr {
EnumRepr::U8 | EnumRepr::I8 => Some(TagWidth::U8),
EnumRepr::U16 | EnumRepr::I16 => Some(TagWidth::U16),
EnumRepr::U32 | EnumRepr::I32 => Some(TagWidth::U32),
EnumRepr::U64 | EnumRepr::I64 | EnumRepr::USize | EnumRepr::ISize => Some(TagWidth::U64),
EnumRepr::Rust | EnumRepr::RustNPO => None,
}
}
#[derive(Debug, Clone)]
pub enum DecodeOp {
ReadScalar {
prim: WirePrimitive,
dst_offset: usize,
},
ReadFixedVec {
dst_offset: usize,
descriptor: OpaqueDescriptorId,
elem_size: usize,
validate_bool: bool,
},
ReadString {
dst_offset: usize,
descriptor: OpaqueDescriptorId,
},
ReadCowStr { dst_offset: usize, borrowed: bool },
ReadStrRef { dst_offset: usize },
ReadCowByteSlice { dst_offset: usize, borrowed: bool },
ReadByteSliceRef { dst_offset: usize },
ReadOpaque {
shape: &'static Shape,
dst_offset: usize,
},
SkipValue { kind: SchemaKind },
WriteDefault {
shape: &'static Shape,
dst_offset: usize,
},
DecodeOption {
dst_offset: usize,
inner_offset: usize,
some_block: usize,
none_bytes: Box<[u8]>,
some_bytes: Box<[u8]>,
},
DecodeResult {
dst_offset: usize,
ok_block: usize,
err_block: usize,
ok_offset: usize,
err_offset: usize,
ok_bytes: Box<[u8]>,
err_bytes: Box<[u8]>,
},
DecodeResultInit {
dst_offset: usize,
ok_block: usize,
err_block: usize,
ok_size: usize,
ok_align: usize,
err_size: usize,
err_align: usize,
init_ok_fn: facet_core::ResultInitOkFn,
init_err_fn: facet_core::ResultInitErrFn,
},
ReadDiscriminant,
BranchOnVariant {
tag_offset: usize,
tag_width: TagWidth,
variant_table: Vec<Option<usize>>,
variant_blocks: Vec<(u64, usize)>,
},
PushFrame {
field_offset: usize,
frame_size: usize,
},
PopFrame,
ReadListLen {
descriptor: OpaqueDescriptorId,
dst_offset: usize,
empty_block: usize,
body_block: usize,
},
CommitListLen {
dst_offset: usize,
descriptor: OpaqueDescriptorId,
},
DecodeArray {
dst_offset: usize,
count: usize,
elem_size: usize,
body_block: usize,
},
MaterializeEmpty {
dst_offset: usize,
descriptor: OpaqueDescriptorId,
},
AllocBacking {
dst_offset: usize,
descriptor: OpaqueDescriptorId,
body_block: usize,
elem_size: usize,
},
AllocBoxed {
dst_offset: usize,
descriptor: OpaqueDescriptorId,
body_block: usize,
},
SlowPath {
shape: &'static Shape,
plan: Box<TranslationPlan>,
dst_offset: usize,
},
Jump { block_id: usize },
Return,
CallSelf { dst_offset: usize },
TailCallSelf { dst_offset: usize },
}
#[derive(Debug, Clone, Default)]
pub struct DecodeBlock {
pub ops: Vec<DecodeOp>,
}
#[derive(Debug, Clone)]
pub struct DecodeProgram {
pub blocks: Vec<DecodeBlock>,
pub root_size: usize,
pub root_align: usize,
pub top_shape: Option<&'static Shape>,
#[doc(hidden)]
pub lowering_in_progress: HashSet<&'static Shape>,
}
impl DecodeProgram {
fn new_block(&mut self) -> usize {
let id = self.blocks.len();
self.blocks.push(DecodeBlock::default());
id
}
fn emit(&mut self, block: usize, op: DecodeOp) {
self.blocks[block].ops.push(op);
}
}
#[derive(Debug)]
pub enum LowerError {
UnsizedShape,
UnstableEnumRepr,
SchemaMissing,
Unsupported(String),
}
pub fn lower(
plan: &TranslationPlan,
shape: &'static Shape,
registry: &SchemaRegistry,
) -> Result<DecodeProgram, LowerError> {
lower_with_cal(plan, shape, registry, None, BorrowMode::Owned)
}
pub fn lower_with_cal(
plan: &TranslationPlan,
shape: &'static Shape,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
borrow_mode: BorrowMode,
) -> Result<DecodeProgram, LowerError> {
let layout = shape
.layout
.sized_layout()
.map_err(|_| LowerError::UnsizedShape)?;
let mut program = DecodeProgram {
blocks: vec![DecodeBlock::default()],
root_size: layout.size(),
root_align: layout.align(),
top_shape: Some(shape),
lowering_in_progress: HashSet::new(),
};
let entry = 0;
lower_value(
plan,
shape,
registry,
cal,
borrow_mode,
&mut program,
entry,
0,
)?;
program.emit(entry, DecodeOp::Return);
debug_assert!(program.lowering_in_progress.is_empty());
mark_tail_calls(&mut program);
Ok(program)
}
fn mark_tail_calls(program: &mut DecodeProgram) {
let mut tail_blocks: HashSet<usize> = HashSet::new();
tail_blocks.insert(0);
let mut changed = true;
while changed {
changed = false;
for block_idx in 0..program.blocks.len() {
if !tail_blocks.contains(&block_idx) {
continue;
}
let last_real = program.blocks[block_idx]
.ops
.iter()
.rposition(|op| !matches!(op, DecodeOp::Return));
let Some(pos) = last_real else { continue };
let op = program.blocks[block_idx].ops[pos].clone();
match op {
DecodeOp::AllocBoxed { body_block, .. } => {
changed |= tail_blocks.insert(body_block);
}
DecodeOp::BranchOnVariant { variant_blocks, .. } => {
for (_, vb) in variant_blocks.iter() {
if *vb == usize::MAX {
continue;
}
if tail_blocks.insert(*vb) {
changed = true;
}
}
}
DecodeOp::ReadListLen { empty_block, .. } => {
changed |= tail_blocks.insert(empty_block);
}
DecodeOp::DecodeOption { some_block, .. } => {
changed |= tail_blocks.insert(some_block);
}
DecodeOp::DecodeResult {
ok_block,
err_block,
..
}
| DecodeOp::DecodeResultInit {
ok_block,
err_block,
..
} => {
if tail_blocks.insert(ok_block) {
changed = true;
}
if tail_blocks.insert(err_block) {
changed = true;
}
}
DecodeOp::Jump { block_id } => {
changed |= tail_blocks.insert(block_id);
}
_ => {}
}
}
}
for &block_idx in &tail_blocks {
let ops = &mut program.blocks[block_idx].ops;
let Some(pos) = ops.iter().rposition(|op| !matches!(op, DecodeOp::Return)) else {
continue;
};
if let DecodeOp::CallSelf { dst_offset } = ops[pos] {
ops[pos] = DecodeOp::TailCallSelf { dst_offset };
}
}
}
#[allow(clippy::too_many_arguments)]
fn lower_value(
plan: &TranslationPlan,
shape: &'static Shape,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
borrow_mode: BorrowMode,
program: &mut DecodeProgram,
block: usize,
dst_offset: usize,
) -> Result<(), LowerError> {
if program.lowering_in_progress.contains(&shape) {
if program.top_shape == Some(shape) {
trace_cycle_emission(
"decode",
"CallSelf",
shape,
program.top_shape,
&program.lowering_in_progress,
);
program.emit(block, DecodeOp::CallSelf { dst_offset });
} else {
trace_cycle_emission(
"decode",
"SlowPath",
shape,
program.top_shape,
&program.lowering_in_progress,
);
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
}
return Ok(());
}
program.lowering_in_progress.insert(shape);
let result = lower_value_inner(
plan,
shape,
registry,
cal,
borrow_mode,
program,
block,
dst_offset,
);
program.lowering_in_progress.remove(&shape);
result
}
#[allow(clippy::too_many_arguments)]
fn lower_value_inner(
plan: &TranslationPlan,
shape: &'static Shape,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
borrow_mode: BorrowMode,
program: &mut DecodeProgram,
block: usize,
dst_offset: usize,
) -> Result<(), LowerError> {
if let facet_core::Def::Result(_) = shape.def {
return lower_def(
plan,
shape,
registry,
cal,
borrow_mode,
program,
block,
dst_offset,
);
}
if shape.opaque_adapter.is_some() {
program.emit(block, DecodeOp::ReadOpaque { shape, dst_offset });
return Ok(());
}
if shape.proxy.is_some() {
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
}
if shape.is_transparent() {
if let Type::User(UserType::Struct(st)) = shape.ty
&& let Some(inner_field) = st.fields.first()
{
let inner_shape = inner_field.shape();
return lower_value(
plan,
inner_shape,
registry,
cal,
borrow_mode,
program,
block,
dst_offset,
);
}
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
}
if let Some(scalar) = shape.scalar_type() {
match scalar {
facet_core::ScalarType::String if shape.is_type::<String>() => {
let cal = cal.ok_or_else(|| {
LowerError::Unsupported(
"ScalarType::String requires a CalibrationRegistry".into(),
)
})?;
let handle = cal.string_descriptor_handle().ok_or_else(|| {
LowerError::Unsupported(
"String descriptor not registered in CalibrationRegistry".into(),
)
})?;
program.emit(
block,
DecodeOp::ReadString {
dst_offset,
descriptor: OpaqueDescriptorId(handle.0),
},
);
return Ok(());
}
facet_core::ScalarType::CowStr => {
program.emit(
block,
DecodeOp::ReadCowStr {
dst_offset,
borrowed: borrow_mode == BorrowMode::Borrowed,
},
);
return Ok(());
}
facet_core::ScalarType::Str => {
program.emit(block, DecodeOp::ReadStrRef { dst_offset });
return Ok(());
}
_ => {}
}
if let Some(prim) = wire_primitive_from_scalar(scalar) {
if matches!(prim, WirePrimitive::String) {
return Err(LowerError::Unsupported(format!(
"ScalarType::String on non-`std::string::String` type {shape} requires \
a per-shape string descriptor; not yet calibrated"
)));
}
program.emit(block, DecodeOp::ReadScalar { prim, dst_offset });
return Ok(());
}
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
}
match shape.def {
facet_core::Def::Option(_)
| facet_core::Def::Array(_)
| facet_core::Def::List(_)
| facet_core::Def::Pointer(_) => {
return lower_def(
plan,
shape,
registry,
cal,
borrow_mode,
program,
block,
dst_offset,
);
}
_ => {}
}
match shape.ty {
Type::User(UserType::Struct(st)) => lower_struct(
plan,
st,
registry,
cal,
borrow_mode,
program,
block,
dst_offset,
),
Type::User(UserType::Enum(et)) => lower_enum(
plan,
shape,
et,
registry,
cal,
borrow_mode,
program,
block,
dst_offset,
),
_ => lower_def(
plan,
shape,
registry,
cal,
borrow_mode,
program,
block,
dst_offset,
),
}
}
#[allow(clippy::too_many_arguments)]
fn lower_def(
plan: &TranslationPlan,
shape: &'static Shape,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
borrow_mode: BorrowMode,
program: &mut DecodeProgram,
block: usize,
dst_offset: usize,
) -> Result<(), LowerError> {
use facet_core::Def;
match shape.def {
Def::Option(opt_def) => lower_option(
plan,
shape,
opt_def,
registry,
cal,
borrow_mode,
program,
block,
dst_offset,
),
Def::Array(arr_def) => lower_array(
plan,
arr_def,
registry,
cal,
borrow_mode,
program,
block,
dst_offset,
),
Def::List(list_def) => lower_list(
plan,
shape,
list_def,
registry,
cal,
borrow_mode,
program,
block,
dst_offset,
),
Def::Pointer(ptr_def) => lower_pointer(
plan,
shape,
ptr_def,
registry,
cal,
borrow_mode,
program,
block,
dst_offset,
),
Def::Result(result_def) => lower_result(
plan,
shape,
result_def,
registry,
cal,
borrow_mode,
program,
block,
dst_offset,
),
_ => {
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
Ok(())
}
}
}
#[allow(clippy::too_many_arguments)]
fn lower_result(
plan: &TranslationPlan,
shape: &'static Shape,
result_def: facet_core::ResultDef,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
borrow_mode: BorrowMode,
program: &mut DecodeProgram,
block: usize,
dst_offset: usize,
) -> Result<(), LowerError> {
let (ok_plan, err_plan) = match plan {
TranslationPlan::Enum { nested, .. } => (
nested.get(&0).unwrap_or(&TranslationPlan::Identity),
nested.get(&1).unwrap_or(&TranslationPlan::Identity),
),
TranslationPlan::Identity => (&TranslationPlan::Identity, &TranslationPlan::Identity),
_ => {
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
}
};
let ok_block = program.new_block();
let err_block = program.new_block();
if let Some(layout) = calibrate_result_layout(shape, result_def) {
program.emit(
block,
DecodeOp::DecodeResult {
dst_offset,
ok_block,
err_block,
ok_offset: layout.ok_offset,
err_offset: layout.err_offset,
ok_bytes: layout.ok_bytes,
err_bytes: layout.err_bytes,
},
);
} else {
let Ok(ok_layout) = result_def.t.layout.sized_layout() else {
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
};
let Ok(err_layout) = result_def.e.layout.sized_layout() else {
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
};
program.emit(
block,
DecodeOp::DecodeResultInit {
dst_offset,
ok_block,
err_block,
ok_size: ok_layout.size(),
ok_align: ok_layout.align(),
err_size: err_layout.size(),
err_align: err_layout.align(),
init_ok_fn: result_def.vtable.init_ok,
init_err_fn: result_def.vtable.init_err,
},
);
}
lower_value(
ok_plan,
result_def.t,
registry,
cal,
borrow_mode,
program,
ok_block,
0,
)?;
program.emit(ok_block, DecodeOp::Return);
lower_value(
err_plan,
result_def.e,
registry,
cal,
borrow_mode,
program,
err_block,
0,
)?;
program.emit(err_block, DecodeOp::Return);
Ok(())
}
#[allow(clippy::too_many_arguments)]
fn lower_struct(
plan: &TranslationPlan,
st: facet_core::StructType,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
borrow_mode: BorrowMode,
program: &mut DecodeProgram,
block: usize,
dst_offset: usize,
) -> Result<(), LowerError> {
let (field_ops, nested) = match plan {
TranslationPlan::Struct { field_ops, nested }
| TranslationPlan::Tuple { field_ops, nested } => (field_ops.as_slice(), nested),
TranslationPlan::Identity => {
let identity = build_identity_plan_for_struct(st);
return lower_struct(
&identity,
st,
registry,
cal,
borrow_mode,
program,
block,
dst_offset,
);
}
_ => {
return Err(LowerError::SchemaMissing);
}
};
let mut matched = vec![false; st.fields.len()];
for op in field_ops {
match op {
FieldOp::Read { local_index } => {
matched[*local_index] = true;
let field = &st.fields[*local_index];
let field_shape = field.shape();
let field_offset = dst_offset + field.offset;
let sub_plan = nested
.get(local_index)
.unwrap_or(&TranslationPlan::Identity);
lower_value(
sub_plan,
field_shape,
registry,
cal,
borrow_mode,
program,
block,
field_offset,
)?;
}
FieldOp::Skip { type_ref } => {
let kind = type_ref
.resolve_kind(registry)
.ok_or(LowerError::SchemaMissing)?;
program.emit(block, DecodeOp::SkipValue { kind });
}
}
}
for (i, field) in st.fields.iter().enumerate() {
if !matched[i] {
program.emit(
block,
DecodeOp::WriteDefault {
shape: field.shape(),
dst_offset: dst_offset + field.offset,
},
);
}
}
Ok(())
}
#[allow(clippy::too_many_arguments)]
fn lower_enum(
plan: &TranslationPlan,
shape: &'static Shape,
et: facet_core::EnumType,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
borrow_mode: BorrowMode,
program: &mut DecodeProgram,
block: usize,
dst_offset: usize,
) -> Result<(), LowerError> {
let Some(tag_width) = tag_width_from_enum_repr(et.enum_repr) else {
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
};
let (variant_map, variant_plans, nested) = match plan {
TranslationPlan::Enum {
variant_map,
variant_plans,
nested,
} => (variant_map, variant_plans, nested),
TranslationPlan::Identity => {
let identity = crate::build_identity_plan(shape);
return lower_enum(
&identity,
shape,
et,
registry,
cal,
borrow_mode,
program,
block,
dst_offset,
);
}
_ => {
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
}
};
program.emit(block, DecodeOp::ReadDiscriminant);
let mut variant_blocks: Vec<(u64, usize)> = Vec::new();
for (remote_idx, maybe_local) in variant_map.iter().enumerate() {
let Some(local_idx) = maybe_local else {
variant_blocks.push((u64::MAX, usize::MAX));
continue;
};
let local_variant = &et.variants[*local_idx];
let local_disc = local_variant
.discriminant
.map(|d| d as u64)
.unwrap_or(*local_idx as u64);
let variant_block = program.new_block();
variant_blocks.push((local_disc, variant_block));
if let Some(variant_plan) = variant_plans.get(&remote_idx) {
lower_struct(
variant_plan,
local_variant.data,
registry,
cal,
borrow_mode,
program,
variant_block,
dst_offset,
)?;
} else if let Some(inner_plan) = nested.get(local_idx) {
if let Some(field) = local_variant.data.fields.first() {
let field_offset = dst_offset + field.offset;
lower_value(
inner_plan,
field.shape(),
registry,
cal,
borrow_mode,
program,
variant_block,
field_offset,
)?;
}
} else {
let identity = build_identity_plan_for_struct(local_variant.data);
lower_struct(
&identity,
local_variant.data,
registry,
cal,
borrow_mode,
program,
variant_block,
dst_offset,
)?;
}
program.emit(variant_block, DecodeOp::Return);
}
program.emit(
block,
DecodeOp::BranchOnVariant {
tag_offset: dst_offset,
tag_width,
variant_table: variant_map.clone(),
variant_blocks,
},
);
Ok(())
}
struct ScratchBuf {
ptr: *mut u8,
layout: std::alloc::Layout,
}
impl ScratchBuf {
#[allow(unsafe_code)]
fn new(layout: std::alloc::Layout) -> Option<Self> {
let ptr = unsafe { std::alloc::alloc_zeroed(layout) };
if ptr.is_null() {
None
} else {
Some(Self { ptr, layout })
}
}
#[allow(unsafe_code)]
fn new_filled(layout: std::alloc::Layout, fill: u8) -> Option<Self> {
let ptr = unsafe { std::alloc::alloc(layout) };
if ptr.is_null() {
return None;
}
unsafe { std::ptr::write_bytes(ptr, fill, layout.size()) };
Some(Self { ptr, layout })
}
#[allow(unsafe_code)]
fn to_bytes(&self) -> Box<[u8]> {
unsafe { std::slice::from_raw_parts(self.ptr as *const u8, self.layout.size()) }
.to_vec()
.into_boxed_slice()
}
}
impl Drop for ScratchBuf {
#[allow(unsafe_code)]
fn drop(&mut self) {
unsafe { std::alloc::dealloc(self.ptr, self.layout) };
}
}
struct CalibratedOptionLayout {
inner_offset: usize,
none_bytes: Box<[u8]>,
some_bytes: Box<[u8]>,
tag_bytes: Box<[(usize, u8)]>,
}
struct CalibratedResultLayout {
ok_offset: usize,
err_offset: usize,
ok_bytes: Box<[u8]>,
err_bytes: Box<[u8]>,
}
#[allow(unsafe_code)]
fn calibrate_option_layout(
shape: &'static Shape,
opt_def: facet_core::OptionDef,
) -> Option<CalibratedOptionLayout> {
let opt_layout = shape.layout.sized_layout().ok()?;
let inner_layout = opt_def.t.layout.sized_layout().ok()?;
const FILLS: [u8; 4] = [0x00, 0xFF, 0x5A, 0xA5];
let mut none_probes: Vec<Box<[u8]>> = Vec::with_capacity(FILLS.len());
for &fill in &FILLS {
none_probes.push(probe_option_none(shape, opt_def, opt_layout, fill)?.0);
}
if opt_layout.size() == inner_layout.size() {
let mut tag_bytes: Vec<(usize, u8)> = Vec::new();
for i in 0..opt_layout.size() {
let val = none_probes[0][i];
let consistent = none_probes.iter().all(|p| p[i] == val);
if consistent && val == 0 {
tag_bytes.push((i, 0));
}
}
if tag_bytes.is_empty() {
return None;
}
let none_bytes = none_probes.into_iter().next().unwrap();
let some_bytes = none_bytes.clone();
return Some(CalibratedOptionLayout {
inner_offset: 0,
none_bytes,
some_bytes,
tag_bytes: tag_bytes.into_boxed_slice(),
});
}
let mut some_probes: Vec<Box<[u8]>> = Vec::with_capacity(FILLS.len());
let mut inner_offset: Option<usize> = None;
for &fill in &FILLS {
let (bytes, off) = probe_option_some(shape, opt_def, opt_layout, inner_layout, fill)?;
match inner_offset {
Some(prev) if prev != off => return None,
_ => inner_offset = Some(off),
}
some_probes.push(bytes);
}
let inner_offset = inner_offset?;
if inner_offset.checked_add(inner_layout.size())? > opt_layout.size() {
return None;
}
let mut candidates: Vec<(usize, u8, u8)> = Vec::new();
for i in 0..opt_layout.size() {
let none_val = none_probes[0][i];
let some_val = some_probes[0][i];
let none_written = none_probes.iter().all(|p| p[i] == none_val);
let some_written = some_probes.iter().all(|p| p[i] == some_val);
if none_written && some_written && none_val != some_val {
candidates.push((i, none_val, some_val));
}
}
let mut tag_bytes: Vec<(usize, u8)> = Vec::new();
for &(i, none_val, some_val) in &candidates {
let oracle_buf = ScratchBuf::new_filled(opt_layout, 0x00)?;
unsafe {
(opt_def.vtable.init_none)(facet_core::PtrUninit::new(oracle_buf.ptr as *mut ()))
};
unsafe { oracle_buf.ptr.add(i).write(some_val) };
let is_some = unsafe {
(opt_def.vtable.is_some)(facet_core::PtrConst::new(oracle_buf.ptr as *const ()))
};
unsafe { shape.call_drop_in_place(facet_core::PtrMut::new(oracle_buf.ptr as *mut ())) };
if is_some {
tag_bytes.push((i, none_val));
}
}
if tag_bytes.is_empty() {
return None;
}
Some(CalibratedOptionLayout {
inner_offset,
none_bytes: none_probes.into_iter().next().unwrap(),
some_bytes: some_probes.into_iter().next().unwrap(),
tag_bytes: tag_bytes.into_boxed_slice(),
})
}
#[allow(unsafe_code)]
fn probe_option_none(
shape: &'static Shape,
opt_def: facet_core::OptionDef,
opt_layout: std::alloc::Layout,
fill: u8,
) -> Option<(Box<[u8]>, ())> {
let buf = ScratchBuf::new_filled(opt_layout, fill)?;
unsafe { (opt_def.vtable.init_none)(facet_core::PtrUninit::new(buf.ptr as *mut ())) };
let bytes = buf.to_bytes();
unsafe { shape.call_drop_in_place(facet_core::PtrMut::new(buf.ptr as *mut ())) };
Some((bytes, ()))
}
#[allow(unsafe_code)]
fn probe_option_some(
shape: &'static Shape,
opt_def: facet_core::OptionDef,
opt_layout: std::alloc::Layout,
inner_layout: std::alloc::Layout,
fill: u8,
) -> Option<(Box<[u8]>, usize)> {
let buf = ScratchBuf::new_filled(opt_layout, fill)?;
let inner_buf = ScratchBuf::new(inner_layout)?;
unsafe {
opt_def
.t
.call_default_in_place(facet_core::PtrUninit::new(inner_buf.ptr as *mut ()))?
};
unsafe {
(opt_def.vtable.init_some)(
facet_core::PtrUninit::new(buf.ptr as *mut ()),
facet_core::PtrMut::new(inner_buf.ptr as *mut ()),
)
};
let ret_ptr =
unsafe { (opt_def.vtable.get_value)(facet_core::PtrConst::new(buf.ptr as *const ())) };
let base_ptr = buf.ptr as *const u8;
let end_ptr = unsafe { base_ptr.add(opt_layout.size()) };
if ret_ptr < base_ptr || ret_ptr > end_ptr {
return None;
}
let inner_offset = ret_ptr as usize - base_ptr as usize;
let bytes = buf.to_bytes();
unsafe { shape.call_drop_in_place(facet_core::PtrMut::new(buf.ptr as *mut ())) };
Some((bytes, inner_offset))
}
#[allow(unsafe_code)]
fn calibrate_result_layout(
shape: &'static Shape,
result_def: facet_core::ResultDef,
) -> Option<CalibratedResultLayout> {
let result_layout = shape.layout.sized_layout().ok()?;
let ok_layout = result_def.t.layout.sized_layout().ok()?;
let err_layout = result_def.e.layout.sized_layout().ok()?;
let ok_buf = ScratchBuf::new(result_layout)?;
let ok_inner = ScratchBuf::new(ok_layout)?;
unsafe {
result_def
.t
.call_default_in_place(facet_core::PtrUninit::new(ok_inner.ptr as *mut ()))?
};
unsafe {
(result_def.vtable.init_ok)(
facet_core::PtrUninit::new(ok_buf.ptr as *mut ()),
facet_core::PtrMut::new(ok_inner.ptr as *mut ()),
)
};
let err_buf = ScratchBuf::new(result_layout)?;
let err_inner = ScratchBuf::new(err_layout)?;
unsafe {
result_def
.e
.call_default_in_place(facet_core::PtrUninit::new(err_inner.ptr as *mut ()))?
};
unsafe {
(result_def.vtable.init_err)(
facet_core::PtrUninit::new(err_buf.ptr as *mut ()),
facet_core::PtrMut::new(err_inner.ptr as *mut ()),
)
};
let base_ptr = ok_buf.ptr as *const u8;
let end_ptr = unsafe { base_ptr.add(result_layout.size()) };
let ok_ptr =
unsafe { (result_def.vtable.get_ok)(facet_core::PtrConst::new(ok_buf.ptr as *const ())) };
if ok_ptr < base_ptr || ok_ptr > end_ptr {
return None;
}
let ok_offset = ok_ptr as usize - base_ptr as usize;
if ok_offset.checked_add(ok_layout.size())? > result_layout.size() {
return None;
}
let err_base_ptr = err_buf.ptr as *const u8;
let err_end_ptr = unsafe { err_base_ptr.add(result_layout.size()) };
let err_ptr =
unsafe { (result_def.vtable.get_err)(facet_core::PtrConst::new(err_buf.ptr as *const ())) };
if err_ptr < err_base_ptr || err_ptr > err_end_ptr {
return None;
}
let err_offset = err_ptr as usize - err_base_ptr as usize;
if err_offset.checked_add(err_layout.size())? > result_layout.size() {
return None;
}
let ok_bytes = ok_buf.to_bytes();
let err_bytes = err_buf.to_bytes();
let _ = unsafe { shape.call_drop_in_place(facet_core::PtrMut::new(ok_buf.ptr as *mut ())) };
let _ = unsafe { shape.call_drop_in_place(facet_core::PtrMut::new(err_buf.ptr as *mut ())) };
Some(CalibratedResultLayout {
ok_offset,
err_offset,
ok_bytes,
err_bytes,
})
}
#[allow(unsafe_code)]
#[allow(clippy::too_many_arguments)]
fn lower_option(
plan: &TranslationPlan,
shape: &'static Shape,
opt_def: facet_core::OptionDef,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
borrow_mode: BorrowMode,
program: &mut DecodeProgram,
block: usize,
dst_offset: usize,
) -> Result<(), LowerError> {
let inner_plan = match plan {
TranslationPlan::Option { inner } => inner.as_ref(),
TranslationPlan::Identity => &TranslationPlan::Identity,
_ => {
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
}
};
let Some(layout) = calibrate_option_layout(shape, opt_def) else {
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
};
let some_block = program.new_block();
program.emit(
block,
DecodeOp::DecodeOption {
dst_offset,
inner_offset: layout.inner_offset,
some_block,
none_bytes: layout.none_bytes,
some_bytes: layout.some_bytes,
},
);
lower_value(
inner_plan,
opt_def.t,
registry,
cal,
borrow_mode,
program,
some_block,
0,
)?;
program.emit(some_block, DecodeOp::Return);
Ok(())
}
#[allow(clippy::too_many_arguments)]
fn lower_array(
plan: &TranslationPlan,
arr_def: facet_core::ArrayDef,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
borrow_mode: BorrowMode,
program: &mut DecodeProgram,
block: usize,
dst_offset: usize,
) -> Result<(), LowerError> {
let element_plan = match plan {
TranslationPlan::Array { element } => element.as_ref(),
TranslationPlan::Identity => &TranslationPlan::Identity,
_ => &TranslationPlan::Identity,
};
let elem_shape = arr_def.t;
let elem_layout = elem_shape
.layout
.sized_layout()
.map_err(|_| LowerError::UnsizedShape)?;
let elem_size = elem_layout.size();
let body_block = program.new_block();
program.emit(
block,
DecodeOp::DecodeArray {
dst_offset,
count: arr_def.n,
elem_size,
body_block,
},
);
lower_value(
element_plan,
elem_shape,
registry,
cal,
borrow_mode,
program,
body_block,
0,
)?;
program.emit(body_block, DecodeOp::Return);
Ok(())
}
#[allow(clippy::too_many_arguments)]
fn lower_list(
plan: &TranslationPlan,
shape: &'static Shape,
list_def: facet_core::ListDef,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
borrow_mode: BorrowMode,
program: &mut DecodeProgram,
block: usize,
dst_offset: usize,
) -> Result<(), LowerError> {
let elem_shape = list_def.t;
let elem_layout = match elem_shape.layout.sized_layout() {
Ok(l) => l,
Err(_) => {
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
}
};
let elem_size = elem_layout.size();
let is_byte_elem = list_def.t.is_type::<u8>() || list_def.t.is_type::<i8>();
let is_bool_elem = list_def.t.is_type::<bool>();
let is_float_elem_le = cfg!(target_endian = "little")
&& (list_def.t.is_type::<f32>() || list_def.t.is_type::<f64>());
if is_byte_elem || is_bool_elem || is_float_elem_le {
if let Some(cal) = cal
&& let Some(descriptor) = cal.lookup_by_shape(shape)
{
let descriptor = OpaqueDescriptorId(descriptor.0);
program.emit(
block,
DecodeOp::ReadFixedVec {
dst_offset,
descriptor,
elem_size,
validate_bool: is_bool_elem,
},
);
return Ok(());
}
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
}
if let Some(cal) = cal
&& let Some(descriptor_handle) = cal.lookup_by_shape(shape)
{
let descriptor = OpaqueDescriptorId(descriptor_handle.0);
let empty_block = program.new_block();
let body_block = program.new_block();
let inner_block = program.new_block();
program.emit(
block,
DecodeOp::ReadListLen {
descriptor,
dst_offset,
empty_block,
body_block,
},
);
program.emit(
empty_block,
DecodeOp::MaterializeEmpty {
dst_offset,
descriptor,
},
);
program.emit(empty_block, DecodeOp::Return);
program.emit(
body_block,
DecodeOp::AllocBacking {
dst_offset,
descriptor,
body_block: inner_block,
elem_size,
},
);
program.emit(body_block, DecodeOp::Return);
let element_plan = match plan {
TranslationPlan::List { element } => element.as_ref(),
_ => &TranslationPlan::Identity,
};
lower_value(
element_plan,
elem_shape,
registry,
Some(cal),
borrow_mode,
program,
inner_block,
0,
)?;
program.emit(
inner_block,
DecodeOp::CommitListLen {
dst_offset,
descriptor,
},
);
program.emit(inner_block, DecodeOp::Return);
return Ok(());
}
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
Ok(())
}
#[allow(clippy::too_many_arguments)]
fn lower_pointer(
plan: &TranslationPlan,
shape: &'static Shape,
ptr_def: facet_core::PointerDef,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
borrow_mode: BorrowMode,
program: &mut DecodeProgram,
block: usize,
dst_offset: usize,
) -> Result<(), LowerError> {
let pointee_plan = match plan {
TranslationPlan::Pointer { pointee } => pointee.as_ref(),
TranslationPlan::Identity => &TranslationPlan::Identity,
_ => {
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
}
};
let Some(pointee_shape) = ptr_def.pointee() else {
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
};
if let facet_core::Def::Slice(slice_def) = pointee_shape.def
&& slice_def.t().is_type::<u8>()
{
match ptr_def.known {
Some(facet_core::KnownPointer::Cow) => {
program.emit(
block,
DecodeOp::ReadCowByteSlice {
dst_offset,
borrowed: borrow_mode == BorrowMode::Borrowed,
},
);
return Ok(());
}
Some(facet_core::KnownPointer::SharedReference)
if borrow_mode == BorrowMode::Borrowed =>
{
program.emit(block, DecodeOp::ReadByteSliceRef { dst_offset });
return Ok(());
}
_ => {}
}
}
if let facet_core::Def::Slice(_) = pointee_shape.def {
if let Some(cal) = cal
&& let Some(descriptor_handle) = cal.lookup_by_shape(shape)
{
let descriptor = OpaqueDescriptorId(descriptor_handle.0);
let body_block = program.new_block();
program.emit(
block,
DecodeOp::AllocBoxed {
dst_offset,
descriptor,
body_block,
},
);
program.emit(
body_block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset: 0,
},
);
program.emit(body_block, DecodeOp::Return);
return Ok(());
}
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
return Ok(());
}
if let Some(cal) = cal
&& let Some(descriptor_handle) = cal.lookup_by_shape(shape)
{
let descriptor = OpaqueDescriptorId(descriptor_handle.0);
let body_block = program.new_block();
program.emit(
block,
DecodeOp::AllocBoxed {
dst_offset,
descriptor,
body_block,
},
);
lower_value(
pointee_plan,
pointee_shape,
registry,
Some(cal),
borrow_mode,
program,
body_block,
0,
)?;
program.emit(body_block, DecodeOp::Return);
return Ok(());
}
program.emit(
block,
DecodeOp::SlowPath {
shape,
plan: Box::new(clone_plan(plan)),
dst_offset,
},
);
Ok(())
}
fn build_identity_plan_for_struct(st: facet_core::StructType) -> TranslationPlan {
let field_ops = (0..st.fields.len())
.map(|i| FieldOp::Read { local_index: i })
.collect();
TranslationPlan::Struct {
field_ops,
nested: HashMap::new(),
}
}
fn clone_plan(plan: &TranslationPlan) -> TranslationPlan {
match plan {
TranslationPlan::Identity => TranslationPlan::Identity,
TranslationPlan::Struct { field_ops, nested } => TranslationPlan::Struct {
field_ops: field_ops.clone(),
nested: nested.iter().map(|(&k, v)| (k, clone_plan(v))).collect(),
},
TranslationPlan::Enum {
variant_map,
variant_plans,
nested,
} => TranslationPlan::Enum {
variant_map: variant_map.clone(),
variant_plans: variant_plans
.iter()
.map(|(&k, v)| (k, clone_plan(v)))
.collect(),
nested: nested.iter().map(|(&k, v)| (k, clone_plan(v))).collect(),
},
TranslationPlan::Tuple { field_ops, nested } => TranslationPlan::Tuple {
field_ops: field_ops.clone(),
nested: nested.iter().map(|(&k, v)| (k, clone_plan(v))).collect(),
},
TranslationPlan::List { element } => TranslationPlan::List {
element: Box::new(clone_plan(element)),
},
TranslationPlan::Option { inner } => TranslationPlan::Option {
inner: Box::new(clone_plan(inner)),
},
TranslationPlan::Map { key, value } => TranslationPlan::Map {
key: Box::new(clone_plan(key)),
value: Box::new(clone_plan(value)),
},
TranslationPlan::Array { element } => TranslationPlan::Array {
element: Box::new(clone_plan(element)),
},
TranslationPlan::Pointer { pointee } => TranslationPlan::Pointer {
pointee: Box::new(clone_plan(pointee)),
},
}
}
struct InterpState<'a> {
input: &'a [u8],
pos: usize,
discriminant: u64,
list_len: usize,
}
impl<'a> InterpState<'a> {
fn new(input: &'a [u8]) -> Self {
Self {
input,
pos: 0,
discriminant: 0,
list_len: 0,
}
}
fn read_byte(&mut self) -> Result<u8, DeserializeError> {
if self.pos >= self.input.len() {
return Err(DeserializeError::UnexpectedEof { pos: self.pos });
}
let b = self.input[self.pos];
self.pos += 1;
Ok(b)
}
fn read_bytes(&mut self, n: usize) -> Result<&'a [u8], DeserializeError> {
if self.pos + n > self.input.len() {
return Err(DeserializeError::UnexpectedEof { pos: self.pos });
}
let s = &self.input[self.pos..self.pos + n];
self.pos += n;
Ok(s)
}
fn read_varint(&mut self) -> Result<u64, DeserializeError> {
let start = self.pos;
let mut result: u64 = 0;
let mut shift: u32 = 0;
loop {
let byte = self.read_byte()?;
result |= ((byte & 0x7F) as u64) << shift;
if byte & 0x80 == 0 {
return Ok(result);
}
shift += 7;
if shift >= 64 {
return Err(DeserializeError::VarintOverflow { pos: start });
}
}
}
fn read_signed_varint(&mut self) -> Result<i64, DeserializeError> {
let z = self.read_varint()?;
Ok(((z >> 1) as i64) ^ (-((z & 1) as i64)))
}
fn read_varint_u128(&mut self) -> Result<u128, DeserializeError> {
let start = self.pos;
let mut result: u128 = 0;
let mut shift: u32 = 0;
loop {
let byte = self.read_byte()?;
result |= ((byte & 0x7F) as u128) << shift;
if byte & 0x80 == 0 {
return Ok(result);
}
shift += 7;
if shift >= 128 {
return Err(DeserializeError::VarintOverflow { pos: start });
}
}
}
fn read_signed_varint_i128(&mut self) -> Result<i128, DeserializeError> {
let z = self.read_varint_u128()?;
Ok(((z >> 1) as i128) ^ (-((z & 1) as i128)))
}
fn read_str(&mut self) -> Result<&'a str, DeserializeError> {
let len = self.read_varint()? as usize;
let bytes = self.read_bytes(len)?;
std::str::from_utf8(bytes).map_err(|_| DeserializeError::InvalidUtf8 {
pos: self.pos - len,
})
}
fn read_byte_slice(&mut self) -> Result<&'a [u8], DeserializeError> {
let len = self.read_varint()? as usize;
self.read_bytes(len)
}
fn read_opaque_bytes(&mut self) -> Result<&'a [u8], DeserializeError> {
let len_bytes = self.read_bytes(4)?;
let len =
u32::from_le_bytes([len_bytes[0], len_bytes[1], len_bytes[2], len_bytes[3]]) as usize;
self.read_bytes(len)
}
}
#[allow(unsafe_code)]
pub unsafe fn interpret(
program: &DecodeProgram,
input: &[u8],
dst: *mut u8,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
) -> Result<usize, DeserializeError> {
let mut state = InterpState::new(input);
run_block(program, 0, &mut state, dst, registry, cal)?;
Ok(state.pos)
}
#[allow(unsafe_code)]
fn run_block(
program: &DecodeProgram,
block_id: usize,
state: &mut InterpState<'_>,
base: *mut u8,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
) -> Result<(), DeserializeError> {
let block = &program.blocks[block_id];
let mut i = 0;
while i < block.ops.len() {
let op = &block.ops[i];
match op {
DecodeOp::ReadScalar { prim, dst_offset } => {
let dst = unsafe { base.add(*dst_offset) };
exec_read_scalar(state, *prim, dst)?;
}
DecodeOp::ReadFixedVec {
dst_offset,
descriptor,
elem_size,
validate_bool,
} => {
let cal = cal.ok_or_else(|| {
DeserializeError::Custom("ReadFixedVec requires a calibration registry".into())
})?;
let desc = cal
.get(vox_jit_cal::DescriptorHandle(descriptor.0))
.ok_or_else(|| {
DeserializeError::Custom("ReadFixedVec: descriptor handle not found".into())
})?;
let list_len = state.read_varint()? as usize;
let byte_count = list_len * *elem_size;
if list_len == 0 {
unsafe {
std::ptr::copy_nonoverlapping(
desc.empty_bytes.as_ptr(),
base.add(*dst_offset),
desc.empty_bytes.len(),
);
}
} else {
let layout = std::alloc::Layout::from_size_align(byte_count, desc.elem_align)
.map_err(|_| {
DeserializeError::Custom("ReadFixedVec: invalid layout".into())
})?;
let backing_ptr = unsafe { std::alloc::alloc(layout) };
if backing_ptr.is_null() {
return Err(DeserializeError::Custom(
"ReadFixedVec: allocation failed (OOM)".into(),
));
}
let src_bytes = state.read_bytes(byte_count)?;
unsafe {
std::ptr::copy_nonoverlapping(src_bytes.as_ptr(), backing_ptr, byte_count);
}
if *validate_bool {
let mut acc: u8 = 0;
for &b in src_bytes {
acc |= b;
}
if acc > 1 {
unsafe { std::alloc::dealloc(backing_ptr, layout) };
return Err(DeserializeError::Custom(
"ReadFixedVec: invalid bool byte (must be 0 or 1)".into(),
));
}
}
let dst = unsafe { base.add(*dst_offset) };
unsafe {
std::ptr::write(
dst.add(desc.ptr_offset as usize) as *mut *mut u8,
backing_ptr,
);
std::ptr::write(dst.add(desc.len_offset as usize) as *mut usize, list_len);
std::ptr::write(dst.add(desc.cap_offset as usize) as *mut usize, list_len);
}
}
}
DecodeOp::ReadString {
dst_offset,
descriptor: _,
} => {
let s = state.read_str()?;
let owned = s.to_owned();
unsafe {
std::ptr::write(base.add(*dst_offset) as *mut String, owned);
}
}
DecodeOp::ReadCowStr {
dst_offset,
borrowed,
} => {
let s = state.read_str()?;
let dst = unsafe { base.add(*dst_offset) as *mut std::borrow::Cow<'static, str> };
let value = if *borrowed {
let borrowed: &'static str = unsafe { std::mem::transmute(s) };
std::borrow::Cow::Borrowed(borrowed)
} else {
std::borrow::Cow::Owned(s.to_owned())
};
unsafe {
std::ptr::write(dst, value);
}
}
DecodeOp::ReadStrRef { dst_offset } => {
let s = state.read_str()?;
let s: &'static str = unsafe { std::mem::transmute(s) };
unsafe {
std::ptr::write(base.add(*dst_offset) as *mut &'static str, s);
}
}
DecodeOp::ReadCowByteSlice {
dst_offset,
borrowed,
} => {
let bytes = state.read_byte_slice()?;
let dst = unsafe { base.add(*dst_offset) as *mut std::borrow::Cow<'static, [u8]> };
let value = if *borrowed {
let borrowed: &'static [u8] = unsafe { std::mem::transmute(bytes) };
std::borrow::Cow::Borrowed(borrowed)
} else {
std::borrow::Cow::Owned(bytes.to_vec())
};
unsafe {
std::ptr::write(dst, value);
}
}
DecodeOp::ReadByteSliceRef { dst_offset } => {
let bytes = state.read_byte_slice()?;
let bytes: &'static [u8] = unsafe { std::mem::transmute(bytes) };
unsafe {
std::ptr::write(base.add(*dst_offset) as *mut &'static [u8], bytes);
}
}
DecodeOp::ReadOpaque { shape, dst_offset } => {
let bytes = state.read_opaque_bytes()?;
let adapter = shape.opaque_adapter.ok_or_else(|| {
DeserializeError::ReflectError(format!("missing opaque adapter for {shape}"))
})?;
let input = facet::OpaqueDeserialize::Borrowed(bytes);
unsafe {
(adapter.deserialize)(input, facet_core::PtrUninit::new(base.add(*dst_offset)))
}
.map_err(|e| {
DeserializeError::ReflectError(format!(
"opaque adapter deserialize failed for {shape}: {e}"
))
})?;
}
DecodeOp::SkipValue { kind } => {
skip_in_state(state, kind, registry)?;
}
DecodeOp::WriteDefault { shape, dst_offset } => {
let dst = unsafe { base.add(*dst_offset) };
unsafe {
shape
.call_default_in_place(facet_core::PtrUninit::new(dst as *mut ()))
.ok_or_else(|| {
DeserializeError::ReflectError(format!(
"no Default available for fill-defaults field {shape}"
))
})?;
}
}
DecodeOp::DecodeOption {
dst_offset,
inner_offset,
some_block,
none_bytes,
some_bytes,
} => {
let tag = state.read_byte()?;
let option_ptr = unsafe { base.add(*dst_offset) };
match tag {
0x00 => unsafe {
std::ptr::copy_nonoverlapping(
none_bytes.as_ptr(),
option_ptr,
none_bytes.len(),
);
},
0x01 => {
unsafe {
std::ptr::copy_nonoverlapping(
some_bytes.as_ptr(),
option_ptr,
some_bytes.len(),
);
}
let inner_ptr = unsafe { option_ptr.add(*inner_offset) };
run_block(program, *some_block, state, inner_ptr, registry, cal)?;
}
other => {
return Err(DeserializeError::InvalidOptionTag {
pos: state.pos - 1,
got: other,
});
}
}
}
DecodeOp::DecodeResult {
dst_offset,
ok_block,
err_block,
ok_offset,
err_offset,
ok_bytes,
err_bytes,
} => {
let variant_index = state.read_varint()? as usize;
let result_ptr = unsafe { base.add(*dst_offset) };
match variant_index {
0 => {
unsafe {
std::ptr::copy_nonoverlapping(
ok_bytes.as_ptr(),
result_ptr,
ok_bytes.len(),
);
}
let payload_ptr = unsafe { result_ptr.add(*ok_offset) };
run_block(program, *ok_block, state, payload_ptr, registry, cal)?;
}
1 => {
unsafe {
std::ptr::copy_nonoverlapping(
err_bytes.as_ptr(),
result_ptr,
err_bytes.len(),
);
}
let payload_ptr = unsafe { result_ptr.add(*err_offset) };
run_block(program, *err_block, state, payload_ptr, registry, cal)?;
}
other => {
return Err(DeserializeError::UnknownVariant {
remote_index: other,
});
}
}
}
DecodeOp::DecodeResultInit {
dst_offset,
ok_block,
err_block,
ok_size,
ok_align,
err_size,
err_align,
init_ok_fn,
init_err_fn,
} => {
let variant_index = state.read_varint()? as usize;
let result_ptr = unsafe { base.add(*dst_offset) };
match variant_index {
0 => {
let layout = std::alloc::Layout::from_size_align(*ok_size, *ok_align)
.map_err(|_| {
DeserializeError::Custom("bad Result::Ok layout".into())
})?;
let tmp = facet_core::alloc_for_layout(layout);
let tmp_ptr = unsafe { tmp.assume_init() };
if let Err(err) = run_block(
program,
*ok_block,
state,
tmp_ptr.as_mut_byte_ptr(),
registry,
cal,
) {
unsafe { facet_core::dealloc_for_layout(tmp_ptr, layout) };
return Err(err);
}
unsafe {
init_ok_fn(facet_core::PtrUninit::new(result_ptr), tmp_ptr);
facet_core::dealloc_for_layout(tmp_ptr, layout);
}
}
1 => {
let layout = std::alloc::Layout::from_size_align(*err_size, *err_align)
.map_err(|_| {
DeserializeError::Custom("bad Result::Err layout".into())
})?;
let tmp = facet_core::alloc_for_layout(layout);
let tmp_ptr = unsafe { tmp.assume_init() };
if let Err(err) = run_block(
program,
*err_block,
state,
tmp_ptr.as_mut_byte_ptr(),
registry,
cal,
) {
unsafe { facet_core::dealloc_for_layout(tmp_ptr, layout) };
return Err(err);
}
unsafe {
init_err_fn(facet_core::PtrUninit::new(result_ptr), tmp_ptr);
facet_core::dealloc_for_layout(tmp_ptr, layout);
}
}
other => {
return Err(DeserializeError::UnknownVariant {
remote_index: other,
});
}
}
}
DecodeOp::ReadDiscriminant => {
state.discriminant = state.read_varint()?;
}
DecodeOp::BranchOnVariant {
tag_offset,
tag_width,
variant_table,
variant_blocks,
} => {
let remote_disc = state.discriminant as usize;
let local_idx = variant_table.get(remote_disc).copied().flatten().ok_or(
DeserializeError::UnknownVariant {
remote_index: remote_disc,
},
)?;
let (local_disc, variant_block) = variant_blocks
.get(remote_disc)
.copied()
.filter(|&(_, b)| b != usize::MAX)
.ok_or(DeserializeError::UnknownVariant {
remote_index: remote_disc,
})?;
write_tag(unsafe { base.add(*tag_offset) }, *tag_width, local_disc);
run_block(program, variant_block, state, base, registry, cal)?;
let _ = local_idx; }
DecodeOp::PushFrame {
field_offset,
frame_size: _,
} => {
let new_base = unsafe { base.add(*field_offset) };
let _ = new_base;
}
DecodeOp::PopFrame => { }
DecodeOp::ReadListLen {
descriptor: _,
dst_offset: _,
empty_block,
body_block,
} => {
let len = state.read_varint()? as usize;
state.list_len = len;
if len == 0 {
run_block(program, *empty_block, state, base, registry, cal)?;
} else {
run_block(program, *body_block, state, base, registry, cal)?;
}
}
DecodeOp::CommitListLen {
dst_offset: _,
descriptor: _,
} => {
}
DecodeOp::DecodeArray {
dst_offset,
count,
elem_size,
body_block,
} => {
let mut elem_ptr = unsafe { base.add(*dst_offset) };
for _ in 0..*count {
run_block(program, *body_block, state, elem_ptr, registry, cal)?;
elem_ptr = unsafe { elem_ptr.add(*elem_size) };
}
}
DecodeOp::MaterializeEmpty {
dst_offset,
descriptor,
} => {
if let Some(cal) = cal
&& let Some(desc) = cal.get(DescriptorHandle::from(*descriptor))
{
unsafe {
std::ptr::copy_nonoverlapping(
desc.empty_bytes.as_ptr(),
base.add(*dst_offset),
desc.empty_bytes.len(),
);
}
} else {
unsafe {
std::ptr::write_bytes(
base.add(*dst_offset),
0,
std::mem::size_of::<usize>() * 3,
);
}
}
}
DecodeOp::AllocBacking {
dst_offset,
descriptor,
body_block,
elem_size,
} => {
let cal = cal.ok_or_else(|| {
DeserializeError::Custom("AllocBacking requires a calibration registry".into())
})?;
let desc = cal
.get(vox_jit_cal::DescriptorHandle(descriptor.0))
.ok_or_else(|| {
DeserializeError::Custom("AllocBacking: descriptor handle not found".into())
})?;
let list_len = state.list_len;
let backing_ptr: *mut u8 = if desc.elem_size == 0 || list_len == 0 {
desc.elem_align as *mut u8
} else {
let layout = std::alloc::Layout::from_size_align(
list_len * desc.elem_size,
desc.elem_align,
)
.map_err(|_| DeserializeError::Custom("AllocBacking: invalid layout".into()))?;
let p = unsafe { std::alloc::alloc(layout) };
if p.is_null() {
return Err(DeserializeError::Custom(
"AllocBacking: allocation failed (OOM)".into(),
));
}
p
};
let dst = unsafe { base.add(*dst_offset) };
unsafe {
std::ptr::write(
dst.add(desc.ptr_offset as usize) as *mut *mut u8,
backing_ptr,
);
if desc.len_offset != vox_jit_cal::OFFSET_ABSENT {
std::ptr::write(dst.add(desc.len_offset as usize) as *mut usize, 0);
}
if desc.cap_offset != vox_jit_cal::OFFSET_ABSENT {
std::ptr::write(dst.add(desc.cap_offset as usize) as *mut usize, list_len);
}
}
let outer_list_len = state.list_len;
let len_slot = if desc.len_offset != vox_jit_cal::OFFSET_ABSENT {
Some(unsafe { dst.add(desc.len_offset as usize) as *mut usize })
} else {
None
};
for i in 0..list_len {
let elem_ptr = unsafe { backing_ptr.add(i * elem_size) };
run_block(program, *body_block, state, elem_ptr, registry, cal.into())?;
if let Some(ptr) = len_slot {
unsafe { std::ptr::write(ptr, i + 1) };
}
}
state.list_len = outer_list_len;
}
DecodeOp::AllocBoxed {
dst_offset,
descriptor,
body_block,
} => {
let Some(cal) = cal else {
return Err(DeserializeError::Custom(
"AllocBoxed requires a calibration registry".into(),
));
};
let handle = DescriptorHandle(descriptor.0);
let desc = cal.get(handle).ok_or_else(|| {
DeserializeError::Custom("AllocBoxed: descriptor handle not found".into())
})?;
let alloc_ptr = if desc.elem_size == 0 {
desc.elem_align as *mut u8
} else {
let layout =
std::alloc::Layout::from_size_align(desc.elem_size, desc.elem_align)
.map_err(|_| {
DeserializeError::Custom("AllocBoxed: invalid layout".into())
})?;
let p = unsafe { std::alloc::alloc(layout) };
if p.is_null() {
return Err(DeserializeError::Custom(
"AllocBoxed: allocation failed (OOM)".into(),
));
}
p
};
let container_ptr = unsafe { base.add(*dst_offset) };
unsafe {
let ptr_slot = container_ptr.add(desc.ptr_offset as usize) as *mut *mut u8;
std::ptr::write(ptr_slot, alloc_ptr);
}
run_block(program, *body_block, state, alloc_ptr, registry, Some(cal))?;
}
DecodeOp::SlowPath {
shape,
plan,
dst_offset,
} => {
exec_slow_path(state, shape, plan, *dst_offset, base, registry)?;
}
DecodeOp::Jump { block_id } => {
return run_block(program, *block_id, state, base, registry, cal);
}
DecodeOp::Return => {
return Ok(());
}
DecodeOp::CallSelf { dst_offset } | DecodeOp::TailCallSelf { dst_offset } => {
let new_base = unsafe { base.add(*dst_offset) };
run_block(program, 0, state, new_base, registry, cal)?;
}
}
i += 1;
}
Ok(())
}
#[allow(unsafe_code)]
fn exec_read_scalar(
state: &mut InterpState<'_>,
prim: WirePrimitive,
dst: *mut u8,
) -> Result<(), DeserializeError> {
match prim {
WirePrimitive::Unit => {}
WirePrimitive::Bool => {
let b = state.read_byte()?;
match b {
0x00 => unsafe { std::ptr::write(dst as *mut bool, false) },
0x01 => unsafe { std::ptr::write(dst as *mut bool, true) },
other => {
return Err(DeserializeError::InvalidBool {
pos: state.pos - 1,
got: other,
});
}
}
}
WirePrimitive::U8 => {
let v = state.read_byte()?;
unsafe { std::ptr::write(dst, v) };
}
WirePrimitive::U16 => {
let v = state.read_varint()? as u16;
unsafe { std::ptr::write(dst as *mut u16, v) };
}
WirePrimitive::U32 => {
let v = state.read_varint()? as u32;
unsafe { std::ptr::write(dst as *mut u32, v) };
}
WirePrimitive::U64 => {
let v = state.read_varint()?;
unsafe { std::ptr::write(dst as *mut u64, v) };
}
WirePrimitive::U128 => {
let v = state.read_varint_u128()?;
unsafe { std::ptr::write(dst as *mut u128, v) };
}
WirePrimitive::USize => {
let v = state.read_varint()? as usize;
unsafe { std::ptr::write(dst as *mut usize, v) };
}
WirePrimitive::I8 => {
let v = state.read_byte()? as i8;
unsafe { std::ptr::write(dst as *mut i8, v) };
}
WirePrimitive::I16 => {
let v = state.read_signed_varint()? as i16;
unsafe { std::ptr::write(dst as *mut i16, v) };
}
WirePrimitive::I32 => {
let v = state.read_signed_varint()? as i32;
unsafe { std::ptr::write(dst as *mut i32, v) };
}
WirePrimitive::I64 => {
let v = state.read_signed_varint()?;
unsafe { std::ptr::write(dst as *mut i64, v) };
}
WirePrimitive::I128 => {
let v = state.read_signed_varint_i128()?;
unsafe { std::ptr::write(dst as *mut i128, v) };
}
WirePrimitive::ISize => {
let v = state.read_signed_varint()? as isize;
unsafe { std::ptr::write(dst as *mut isize, v) };
}
WirePrimitive::F32 => {
let bytes = state.read_bytes(4)?;
let v = f32::from_le_bytes(bytes.try_into().unwrap());
unsafe { std::ptr::write(dst as *mut f32, v) };
}
WirePrimitive::F64 => {
let bytes = state.read_bytes(8)?;
let v = f64::from_le_bytes(bytes.try_into().unwrap());
unsafe { std::ptr::write(dst as *mut f64, v) };
}
WirePrimitive::String => {
let s = state.read_str()?;
let owned = s.to_owned();
unsafe { std::ptr::write(dst as *mut String, owned) };
}
WirePrimitive::Bytes => {
let bytes = state.read_byte_slice()?;
let vec: Vec<u8> = bytes.to_vec();
unsafe { std::ptr::write(dst as *mut Vec<u8>, vec) };
}
WirePrimitive::Payload => {
let len_bytes = state.read_bytes(4)?;
let len = u32::from_le_bytes(len_bytes.try_into().unwrap()) as usize;
let payload = state.read_bytes(len)?.to_vec();
unsafe { std::ptr::write(dst as *mut Vec<u8>, payload) };
}
WirePrimitive::Char => {
let s = state.read_str()?;
let c = s
.chars()
.next()
.ok_or_else(|| DeserializeError::Custom("empty string for char".into()))?;
unsafe { std::ptr::write(dst as *mut char, c) };
}
}
Ok(())
}
#[allow(unsafe_code)]
fn write_tag(tag_ptr: *mut u8, width: TagWidth, disc: u64) {
match width {
TagWidth::U8 => unsafe { std::ptr::write(tag_ptr, disc as u8) },
TagWidth::U16 => unsafe { std::ptr::write(tag_ptr as *mut u16, disc as u16) },
TagWidth::U32 => unsafe { std::ptr::write(tag_ptr as *mut u32, disc as u32) },
TagWidth::U64 => unsafe { std::ptr::write(tag_ptr as *mut u64, disc) },
}
}
fn skip_in_state(
state: &mut InterpState<'_>,
kind: &SchemaKind,
registry: &SchemaRegistry,
) -> Result<(), DeserializeError> {
let mut tmp = crate::decode::Cursor::new(state.input);
tmp.advance_to(state.pos);
crate::decode::skip_value(&mut tmp, kind, registry)?;
state.pos = tmp.pos();
Ok(())
}
#[allow(unsafe_code)]
fn exec_slow_path(
state: &mut InterpState<'_>,
shape: &'static Shape,
plan: &TranslationPlan,
dst_offset: usize,
base: *mut u8,
registry: &SchemaRegistry,
) -> Result<(), DeserializeError> {
use facet_core::PtrUninit;
use facet_reflect::Partial;
let remaining = &state.input[state.pos..];
let mut cursor = crate::decode::Cursor::new(remaining);
let dst_ptr = unsafe { base.add(dst_offset) };
let uninit = PtrUninit::new(dst_ptr as *mut ());
let partial = unsafe { Partial::from_raw_with_shape(uninit, shape) }
.map_err(|e| DeserializeError::ReflectError(e.to_string()))?;
let partial =
crate::deserialize::deserialize_value_pub::<false>(partial, &mut cursor, plan, registry)?;
partial
.finish_in_place()
.map_err(|e| DeserializeError::ReflectError(e.to_string()))?;
state.pos += cursor.pos();
Ok(())
}
pub unsafe fn slow_path_decode_raw(
input_ptr: *const u8,
input_len: usize,
consumed: usize,
shape: &'static Shape,
plan: *const TranslationPlan,
dst_base: *mut u8,
dst_offset: usize,
) -> Option<usize> {
use facet_core::PtrUninit;
use facet_reflect::Partial;
let input = unsafe { core::slice::from_raw_parts(input_ptr, input_len) };
let remaining = &input[consumed..];
let mut cursor = crate::decode::Cursor::new(remaining);
let dst_ptr = unsafe { dst_base.add(dst_offset) };
let uninit = PtrUninit::new(dst_ptr as *mut ());
let partial = unsafe { Partial::from_raw_with_shape(uninit, shape) }.ok()?;
let plan_ref = unsafe { &*plan };
let registry = vox_schema::SchemaRegistry::new();
let partial = crate::deserialize::deserialize_value_pub::<false>(
partial,
&mut cursor,
plan_ref,
®istry,
)
.ok()?;
partial.finish_in_place().ok()?;
Some(consumed + cursor.pos())
}
pub fn from_slice_ir<T>(
input: &[u8],
plan: &TranslationPlan,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
) -> Result<T, DeserializeError>
where
T: facet::Facet<'static>,
{
unsafe { from_slice_ir_impl::<T>(input, plan, registry, cal, BorrowMode::Owned) }
}
pub fn from_slice_ir_borrowed<'input, 'facet, T>(
input: &'input [u8],
plan: &TranslationPlan,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
) -> Result<T, DeserializeError>
where
T: facet::Facet<'facet>,
'input: 'facet,
{
unsafe { from_slice_ir_impl::<T>(input, plan, registry, cal, BorrowMode::Borrowed) }
}
#[allow(unsafe_code)]
unsafe fn from_slice_ir_impl<'facet, T>(
input: &[u8],
plan: &TranslationPlan,
registry: &SchemaRegistry,
cal: Option<&CalibrationRegistry>,
borrow_mode: BorrowMode,
) -> Result<T, DeserializeError>
where
T: facet::Facet<'facet>,
{
let shape = T::SHAPE;
let program = lower_with_cal(plan, shape, registry, cal, borrow_mode).map_err(|e| match e {
LowerError::UnsizedShape => DeserializeError::UnsupportedType("unsized shape".into()),
LowerError::UnstableEnumRepr => {
DeserializeError::UnsupportedType("unstable enum repr".into())
}
LowerError::SchemaMissing => DeserializeError::Custom("schema missing during lower".into()),
LowerError::Unsupported(reason) => DeserializeError::UnsupportedType(reason),
})?;
let layout = shape
.layout
.sized_layout()
.map_err(|_| DeserializeError::UnsupportedType(format!("{shape}")))?;
let ptr = {
let p = unsafe {
std::alloc::alloc_zeroed(
std::alloc::Layout::from_size_align(layout.size(), layout.align())
.map_err(|_| DeserializeError::Custom("bad layout".into()))?,
)
};
if p.is_null() {
std::alloc::handle_alloc_error(
std::alloc::Layout::from_size_align(layout.size(), layout.align()).unwrap(),
);
}
p
};
let result = unsafe { interpret(&program, input, ptr, registry, cal) };
match result {
Ok(_bytes_consumed) => {
let value: T = unsafe { std::ptr::read(ptr as *const T) };
unsafe {
std::alloc::dealloc(
ptr,
std::alloc::Layout::from_size_align(layout.size(), layout.align()).unwrap(),
);
}
Ok(value)
}
Err(e) => {
unsafe {
std::ptr::write_bytes(ptr, 0, layout.size());
std::alloc::dealloc(
ptr,
std::alloc::Layout::from_size_align(layout.size(), layout.align()).unwrap(),
);
}
Err(e)
}
}
}
#[derive(Debug, Clone)]
pub enum EncodeOp {
WriteScalar {
prim: WirePrimitive,
src_offset: usize,
},
WriteStringLike {
shape: &'static Shape,
src_offset: usize,
},
WriteBytesLike {
shape: &'static Shape,
src_offset: usize,
},
WriteShape {
shape: &'static Shape,
src_offset: usize,
},
WriteOpaque {
shape: &'static Shape,
src_offset: usize,
},
WriteProxy {
shape: &'static Shape,
src_offset: usize,
},
SlowPath {
shape: &'static Shape,
src_offset: usize,
},
BorrowPointer {
src_offset: usize,
body_block: usize,
borrow_fn: facet_core::BorrowFn,
},
DerefPointer {
src_offset: usize,
body_block: usize,
},
WriteByteSlice {
src_offset: usize,
len_fn: facet_core::SliceLenFn,
as_ptr_fn: facet_core::SliceAsPtrFn,
},
EncodeOption {
src_offset: usize,
some_block: usize,
is_some_fn: facet_core::OptionIsSomeFn,
get_value_fn: facet_core::OptionGetValueFn,
},
EncodeOptionCalibrated {
src_offset: usize,
inner_offset: usize,
some_block: usize,
tag_bytes: Box<[(usize, u8)]>,
},
EncodeResult {
shape: &'static Shape,
src_offset: usize,
ok_block: usize,
err_block: usize,
ok_shape: &'static Shape,
err_shape: &'static Shape,
is_ok_fn: facet_core::ResultIsOkFn,
get_ok_fn: facet_core::ResultGetOkFn,
get_err_fn: facet_core::ResultGetErrFn,
},
WriteVariantIndex { index: u64 },
BranchOnEncode {
src_offset: usize,
tag_width: TagWidth,
variant_blocks: Vec<(u64, usize)>,
},
EncodeList {
src_offset: usize,
descriptor: OpaqueDescriptorId,
body_block: usize,
elem_size: usize,
},
WriteFixedList {
src_offset: usize,
descriptor: OpaqueDescriptorId,
elem_size: usize,
},
EncodeArray {
src_offset: usize,
count: usize,
elem_size: usize,
body_block: usize,
},
Jump { block_id: usize },
CallSelf { src_offset: usize },
Return,
}
#[derive(Debug, Clone, Default)]
pub struct EncodeBlock {
pub ops: Vec<EncodeOp>,
}
#[derive(Debug, Clone)]
pub struct EncodeProgram {
pub blocks: Vec<EncodeBlock>,
pub root_size: usize,
pub root_align: usize,
pub top_shape: Option<&'static Shape>,
pub lowering_in_progress: HashSet<&'static Shape>,
}
impl EncodeProgram {
fn new_block(&mut self) -> usize {
let id = self.blocks.len();
self.blocks.push(EncodeBlock::default());
id
}
fn emit(&mut self, block: usize, op: EncodeOp) {
self.blocks[block].ops.push(op);
}
}
#[derive(Debug)]
pub enum EncodeLowerError {
UnsizedShape,
UnstableEnumRepr,
Unsupported(String),
}
impl std::fmt::Display for EncodeLowerError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnsizedShape => write!(f, "unsized shape"),
Self::UnstableEnumRepr => write!(f, "unstable enum repr"),
Self::Unsupported(s) => write!(f, "unsupported: {s}"),
}
}
}
pub fn lower_encode(
shape: &'static Shape,
cal: Option<&CalibrationRegistry>,
) -> Result<EncodeProgram, EncodeLowerError> {
let layout = shape
.layout
.sized_layout()
.map_err(|_| EncodeLowerError::UnsizedShape)?;
let mut program = EncodeProgram {
blocks: vec![EncodeBlock::default()],
root_size: layout.size(),
root_align: layout.align(),
top_shape: Some(shape),
lowering_in_progress: HashSet::new(),
};
lower_encode_value(shape, cal, &mut program, 0, 0)?;
program.emit(0, EncodeOp::Return);
debug_assert!(program.lowering_in_progress.is_empty());
Ok(program)
}
fn lower_encode_value(
shape: &'static Shape,
cal: Option<&CalibrationRegistry>,
program: &mut EncodeProgram,
block: usize,
src_offset: usize,
) -> Result<(), EncodeLowerError> {
if program.lowering_in_progress.contains(&shape) {
if program.top_shape == Some(shape) {
trace_cycle_emission(
"encode",
"CallSelf",
shape,
program.top_shape,
&program.lowering_in_progress,
);
program.emit(block, EncodeOp::CallSelf { src_offset });
} else {
trace_cycle_emission(
"encode",
"SlowPath",
shape,
program.top_shape,
&program.lowering_in_progress,
);
program.emit(block, EncodeOp::SlowPath { shape, src_offset });
}
return Ok(());
}
program.lowering_in_progress.insert(shape);
let result = lower_encode_value_inner(shape, cal, program, block, src_offset);
program.lowering_in_progress.remove(&shape);
result
}
fn lower_encode_value_inner(
shape: &'static Shape,
cal: Option<&CalibrationRegistry>,
program: &mut EncodeProgram,
block: usize,
src_offset: usize,
) -> Result<(), EncodeLowerError> {
use facet_core::{Def, Type, UserType};
if shape.is_transparent() {
if let Type::User(UserType::Struct(st)) = shape.ty
&& let Some(inner_field) = st.fields.first()
{
return lower_encode_value(inner_field.shape(), cal, program, block, src_offset);
}
return Err(EncodeLowerError::Unsupported(format!(
"transparent non-struct: {shape}"
)));
}
if let Def::Result(result_def) = shape.def {
return lower_encode_result(shape, result_def, cal, program, block, src_offset);
}
if shape.opaque_adapter.is_some() {
program.emit(block, EncodeOp::WriteOpaque { shape, src_offset });
return Ok(());
}
if shape.proxy.is_some() {
program.emit(block, EncodeOp::WriteProxy { shape, src_offset });
return Ok(());
}
if let Some(scalar) = shape.scalar_type() {
match scalar {
facet_core::ScalarType::String => {
if let Some(cal) = cal
&& let Some(h) = cal.lookup_by_shape(shape)
{
program.emit(
block,
EncodeOp::WriteFixedList {
src_offset,
descriptor: OpaqueDescriptorId(h.0),
elem_size: 1,
},
);
return Ok(());
}
program.emit(block, EncodeOp::WriteStringLike { shape, src_offset });
return Ok(());
}
facet_core::ScalarType::Str | facet_core::ScalarType::CowStr => {
program.emit(block, EncodeOp::WriteStringLike { shape, src_offset });
return Ok(());
}
_ => {}
}
if let Some(prim) = wire_primitive_from_scalar(scalar) {
program.emit(block, EncodeOp::WriteScalar { prim, src_offset });
return Ok(());
}
return Err(EncodeLowerError::Unsupported(format!(
"unknown scalar: {scalar:?}"
)));
}
match shape.def {
Def::Option(opt_def) => {
return lower_encode_option(shape, opt_def, cal, program, block, src_offset);
}
Def::Array(arr_def) => {
return lower_encode_array(arr_def, cal, program, block, src_offset);
}
Def::List(list_def) => {
return lower_encode_list(shape, list_def, cal, program, block, src_offset);
}
Def::Pointer(ptr_def) => {
return lower_encode_pointer(shape, ptr_def, cal, program, block, src_offset);
}
Def::Slice(slice_def) => {
return lower_encode_slice(shape, slice_def, program, block, src_offset);
}
Def::Map(_) | Def::Set(_) => {
return Err(EncodeLowerError::Unsupported(format!(
"unsupported def: {shape}"
)));
}
_ => {}
}
match shape.ty {
Type::User(UserType::Struct(st)) => {
for field in st.fields {
let field_offset = src_offset + field.offset;
lower_encode_value(field.shape(), cal, program, block, field_offset)?;
}
Ok(())
}
Type::User(UserType::Enum(et)) => {
lower_encode_enum(shape, et, cal, program, block, src_offset)
}
_ => Err(EncodeLowerError::Unsupported(format!(
"unsupported type: {shape}"
))),
}
}
fn lower_encode_pointer(
shape: &'static Shape,
ptr_def: facet_core::PointerDef,
cal: Option<&CalibrationRegistry>,
program: &mut EncodeProgram,
block: usize,
src_offset: usize,
) -> Result<(), EncodeLowerError> {
let Some(pointee_shape) = ptr_def.pointee() else {
return Err(EncodeLowerError::Unsupported(
"opaque pointer without pointee".into(),
));
};
if pointee_shape == <str as Facet<'static>>::SHAPE {
program.emit(block, EncodeOp::WriteStringLike { shape, src_offset });
return Ok(());
}
if let facet_core::Def::Slice(slice_def) = pointee_shape.def
&& slice_def.t().is_type::<u8>()
{
program.emit(block, EncodeOp::WriteBytesLike { shape, src_offset });
return Ok(());
}
let is_thin_pointer = matches!(
ptr_def.known,
Some(facet_core::KnownPointer::Box | facet_core::KnownPointer::SharedReference)
);
if is_thin_pointer {
let body_block = program.new_block();
program.emit(
block,
EncodeOp::DerefPointer {
src_offset,
body_block,
},
);
lower_encode_value(pointee_shape, cal, program, body_block, 0)?;
program.emit(body_block, EncodeOp::Return);
return Ok(());
}
if let Some(borrow_fn) = ptr_def.vtable.borrow_fn {
let body_block = program.new_block();
program.emit(
block,
EncodeOp::BorrowPointer {
src_offset,
body_block,
borrow_fn,
},
);
lower_encode_value(pointee_shape, cal, program, body_block, 0)?;
program.emit(body_block, EncodeOp::Return);
return Ok(());
}
Err(EncodeLowerError::Unsupported(format!(
"unsupported pointer: {pointee_shape}"
)))
}
fn should_inline_loop_body(shape: &'static Shape) -> bool {
if let Some(scalar) = shape.scalar_type() {
let _ = scalar;
return true;
}
match shape.def {
facet_core::Def::Pointer(ptr_def) => {
if let Some(pointee) = ptr_def.pointee() {
return pointee.scalar_type() == Some(facet_core::ScalarType::Str)
|| matches!(pointee.def, facet_core::Def::Slice(slice_def) if slice_def.t().is_type::<u8>());
}
false
}
facet_core::Def::Slice(slice_def) => slice_def.t().is_type::<u8>(),
_ => false,
}
}
fn lower_encode_slice(
shape: &'static Shape,
slice_def: facet_core::SliceDef,
program: &mut EncodeProgram,
block: usize,
src_offset: usize,
) -> Result<(), EncodeLowerError> {
if !slice_def.t().is_type::<u8>() {
return Err(EncodeLowerError::Unsupported(format!(
"unsupported slice: {shape}"
)));
}
program.emit(
block,
EncodeOp::WriteByteSlice {
src_offset,
len_fn: slice_def.vtable.len,
as_ptr_fn: slice_def.vtable.as_ptr,
},
);
Ok(())
}
fn lower_encode_option(
shape: &'static Shape,
opt_def: facet_core::OptionDef,
cal: Option<&CalibrationRegistry>,
program: &mut EncodeProgram,
block: usize,
src_offset: usize,
) -> Result<(), EncodeLowerError> {
let some_block = program.new_block();
let is_niche_optimized = shape
.layout
.sized_layout()
.ok()
.zip(opt_def.t.layout.sized_layout().ok())
.is_some_and(|(option_layout, inner_layout)| option_layout.size() == inner_layout.size());
let fallback = match calibrate_option_layout(shape, opt_def) {
Some(layout) if !is_niche_optimized && !layout.tag_bytes.is_empty() => {
program.emit(
block,
EncodeOp::EncodeOptionCalibrated {
src_offset,
inner_offset: layout.inner_offset,
some_block,
tag_bytes: layout.tag_bytes,
},
);
false
}
_ => true,
};
if fallback {
program.emit(
block,
EncodeOp::EncodeOption {
src_offset,
some_block,
is_some_fn: opt_def.vtable.is_some,
get_value_fn: opt_def.vtable.get_value,
},
);
}
lower_encode_value(opt_def.t, cal, program, some_block, 0)?;
program.emit(some_block, EncodeOp::Return);
Ok(())
}
fn lower_encode_result(
shape: &'static Shape,
result_def: facet_core::ResultDef,
cal: Option<&CalibrationRegistry>,
program: &mut EncodeProgram,
block: usize,
src_offset: usize,
) -> Result<(), EncodeLowerError> {
let ok_block = program.new_block();
let err_block = program.new_block();
program.emit(
block,
EncodeOp::EncodeResult {
shape,
src_offset,
ok_block,
err_block,
ok_shape: result_def.t,
err_shape: result_def.e,
is_ok_fn: result_def.vtable.is_ok,
get_ok_fn: result_def.vtable.get_ok,
get_err_fn: result_def.vtable.get_err,
},
);
lower_encode_value(result_def.t, cal, program, ok_block, 0)?;
program.emit(ok_block, EncodeOp::Return);
lower_encode_value(result_def.e, cal, program, err_block, 0)?;
program.emit(err_block, EncodeOp::Return);
Ok(())
}
fn lower_encode_array(
arr_def: facet_core::ArrayDef,
cal: Option<&CalibrationRegistry>,
program: &mut EncodeProgram,
block: usize,
src_offset: usize,
) -> Result<(), EncodeLowerError> {
let elem_shape = arr_def.t;
let elem_layout = elem_shape
.layout
.sized_layout()
.map_err(|_| EncodeLowerError::UnsizedShape)?;
let elem_size = elem_layout.size();
let body_block = program.new_block();
program.emit(
block,
EncodeOp::EncodeArray {
src_offset,
count: arr_def.n,
elem_size,
body_block,
},
);
if should_inline_loop_body(elem_shape) {
lower_encode_value(elem_shape, cal, program, body_block, 0)?;
} else {
program.emit(
body_block,
EncodeOp::WriteShape {
shape: elem_shape,
src_offset: 0,
},
);
}
program.emit(body_block, EncodeOp::Return);
Ok(())
}
fn lower_encode_list(
shape: &'static Shape,
list_def: facet_core::ListDef,
cal: Option<&CalibrationRegistry>,
program: &mut EncodeProgram,
block: usize,
src_offset: usize,
) -> Result<(), EncodeLowerError> {
let elem_shape = list_def.t;
let elem_layout = elem_shape
.layout
.sized_layout()
.map_err(|_| EncodeLowerError::UnsizedShape)?;
let elem_size = elem_layout.size();
let descriptor = if let Some(cal) = cal
&& let Some(h) = cal.lookup_by_shape(shape)
{
OpaqueDescriptorId(h.0)
} else {
return Err(EncodeLowerError::Unsupported(format!(
"Vec<T> without calibration: {shape}"
)));
};
let is_byte_elem = elem_shape.is_type::<u8>() || elem_shape.is_type::<i8>();
let is_bool_elem = elem_shape.is_type::<bool>();
let is_float_elem_le = cfg!(target_endian = "little")
&& (elem_shape.is_type::<f32>() || elem_shape.is_type::<f64>());
if is_byte_elem || is_bool_elem || is_float_elem_le {
program.emit(
block,
EncodeOp::WriteFixedList {
src_offset,
descriptor,
elem_size,
},
);
return Ok(());
}
let body_block = program.new_block();
program.emit(
block,
EncodeOp::EncodeList {
src_offset,
descriptor,
body_block,
elem_size,
},
);
if should_inline_loop_body(elem_shape) {
lower_encode_value(elem_shape, cal, program, body_block, 0)?;
} else {
program.emit(
body_block,
EncodeOp::WriteShape {
shape: elem_shape,
src_offset: 0,
},
);
}
program.emit(body_block, EncodeOp::Return);
Ok(())
}
fn lower_encode_enum(
_shape: &'static Shape,
et: facet_core::EnumType,
cal: Option<&CalibrationRegistry>,
program: &mut EncodeProgram,
block: usize,
src_offset: usize,
) -> Result<(), EncodeLowerError> {
let tag_width =
tag_width_from_enum_repr(et.enum_repr).ok_or(EncodeLowerError::UnstableEnumRepr)?;
let mut variant_blocks: Vec<(u64, usize)> = Vec::new();
for (i, variant) in et.variants.iter().enumerate() {
let disc = variant.discriminant.map(|d| d as u64).unwrap_or(i as u64);
let vblock = program.new_block();
variant_blocks.push((disc, vblock));
program.emit(vblock, EncodeOp::WriteVariantIndex { index: i as u64 });
for field in variant.data.fields {
let field_offset = src_offset + field.offset;
lower_encode_value(field.shape(), cal, program, vblock, field_offset)?;
}
program.emit(vblock, EncodeOp::Return);
}
program.emit(
block,
EncodeOp::BranchOnEncode {
src_offset,
tag_width,
variant_blocks,
},
);
Ok(())
}