extern crate alloc;
use std::borrow::Cow;
use facet_core::{ScalarType, Shape, StructKind};
use facet_reflect::Partial;
use crate::{
DeserializeError, DeserializeErrorKind, EnumVariantHint, FormatDeserializer, ParseEventKind,
ScalarTypeHint, ScalarValue, SpanGuard,
};
impl<'parser, 'input, const BORROW: bool> FormatDeserializer<'parser, 'input, BORROW> {
pub(crate) fn deserialize_dynamic_value(
&mut self,
mut wip: Partial<'input, BORROW>,
) -> Result<Partial<'input, BORROW>, DeserializeError> {
let _guard = SpanGuard::new(self.last_span);
if self.is_non_self_describing() {
self.parser.hint_dynamic_value();
}
let event = self.expect_peek("value for dynamic value")?;
match event.kind {
ParseEventKind::Scalar(_) => {
let event = self.expect_event("scalar")?;
if let ParseEventKind::Scalar(scalar) = event.kind {
wip = self.set_scalar(wip, scalar)?;
}
}
ParseEventKind::SequenceStart(_) => {
self.expect_event("sequence start")?; wip = wip.init_list()?;
loop {
let event = self.expect_peek("value or end")?;
if matches!(event.kind, ParseEventKind::SequenceEnd) {
self.expect_event("sequence end")?;
break;
}
wip = wip
.begin_list_item()?
.with(|w| self.deserialize_dynamic_value(w))?
.end()?;
}
}
ParseEventKind::StructStart(_) => {
self.expect_event("struct start")?; wip = wip.init_map()?;
loop {
let event = self.expect_peek("field key or end")?;
if matches!(event.kind, ParseEventKind::StructEnd) {
self.expect_event("struct end")?;
break;
}
let key_event = self.expect_event("field key")?;
let key = match key_event.kind {
ParseEventKind::FieldKey(field_key) => {
field_key
.name()
.cloned()
.map(|n| n.into_owned())
.unwrap_or_else(|| "@".to_owned())
}
_ => {
return Err(DeserializeError {
span: Some(self.last_span),
path: Some(wip.path()),
kind: DeserializeErrorKind::UnexpectedToken {
expected: "field key",
got: key_event.kind_name().into(),
},
});
}
};
wip = wip
.begin_object_entry(&key)?
.with(|w| self.deserialize_dynamic_value(w))?
.end()?;
}
}
_ => {
return Err(DeserializeError {
span: Some(self.last_span),
path: Some(wip.path()),
kind: DeserializeErrorKind::UnexpectedToken {
expected: "scalar, sequence, or struct",
got: event.kind_name().into(),
},
});
}
}
Ok(wip)
}
pub(crate) fn deserialize_struct_dynamic(
&mut self,
mut wip: Partial<'input, BORROW>,
fields: &'static [facet_core::Field],
) -> Result<Partial<'input, BORROW>, DeserializeError> {
let _guard = SpanGuard::new(self.last_span);
if self.is_non_self_describing() {
self.parser.hint_struct_fields(fields.len());
}
let event = self.expect_event("struct start")?;
if !matches!(event.kind, ParseEventKind::StructStart(_)) {
return Err(self.mk_err(
&wip,
DeserializeErrorKind::UnexpectedToken {
expected: "struct",
got: event.kind_name().into(),
},
));
}
wip = wip.init_map()?;
for field in fields {
let field_shape = field.shape.get();
let event = self.expect_event("field")?;
match event.kind {
ParseEventKind::OrderedField | ParseEventKind::FieldKey(_) => {
let key = field.rename.unwrap_or(field.name);
wip = wip
.begin_object_entry(key)?
.with(|w| self.deserialize_value_recursive(w, field_shape))?
.end()?;
}
ParseEventKind::StructEnd => break,
_ => {
return Err(self.mk_err(
&wip,
DeserializeErrorKind::UnexpectedToken {
expected: "field or struct end",
got: event.kind_name().into(),
},
));
}
}
}
if let Ok(event) = self.expect_peek("struct end")
&& matches!(event.kind, ParseEventKind::StructEnd)
{
let _ = self.expect_event("struct end")?;
}
Ok(wip)
}
pub(crate) fn deserialize_tuple_dynamic(
&mut self,
mut wip: Partial<'input, BORROW>,
fields: &'static [facet_core::Field],
) -> Result<Partial<'input, BORROW>, DeserializeError> {
let _guard = SpanGuard::new(self.last_span);
if self.is_non_self_describing() {
self.parser.hint_struct_fields(fields.len());
}
let event = self.expect_event("tuple start")?;
if !matches!(
event.kind,
ParseEventKind::StructStart(_) | ParseEventKind::SequenceStart(_)
) {
return Err(self.mk_err(
&wip,
DeserializeErrorKind::UnexpectedToken {
expected: "tuple",
got: event.kind_name().into(),
},
));
}
wip = wip.init_list()?;
for field in fields {
let field_shape = field.shape.get();
let event = self.expect_event("tuple element")?;
match event.kind {
ParseEventKind::OrderedField | ParseEventKind::FieldKey(_) => {
wip = wip
.begin_list_item()?
.with(|w| self.deserialize_value_recursive(w, field_shape))?
.end()?;
}
ParseEventKind::StructEnd | ParseEventKind::SequenceEnd => break,
_ => {
return Err(self.mk_err(
&wip,
DeserializeErrorKind::UnexpectedToken {
expected: "tuple element or end",
got: event.kind_name().into(),
},
));
}
}
}
if let Ok(event) = self.expect_peek("tuple end")
&& matches!(
event.kind,
ParseEventKind::StructEnd | ParseEventKind::SequenceEnd
)
{
let _ = self.expect_event("tuple end")?;
}
Ok(wip)
}
pub(crate) fn deserialize_enum_dynamic(
&mut self,
mut wip: Partial<'input, BORROW>,
enum_def: &'static facet_core::EnumType,
) -> Result<Partial<'input, BORROW>, DeserializeError> {
let _guard = SpanGuard::new(self.last_span);
let variants: alloc::vec::Vec<EnumVariantHint> = enum_def
.variants
.iter()
.map(|v| EnumVariantHint {
name: v.effective_name(),
kind: v.data.kind,
field_count: v.data.fields.len(),
})
.collect();
if self.is_non_self_describing() {
self.parser.hint_enum(&variants);
}
let event = self.expect_event("enum")?;
match event.kind {
ParseEventKind::Scalar(ScalarValue::Str(s)) => {
wip = self.set_string_value(wip, s)?;
}
ParseEventKind::Scalar(ScalarValue::I64(i)) => {
wip = wip.set(i)?;
}
ParseEventKind::Scalar(ScalarValue::U64(u)) => {
wip = wip.set(u)?;
}
ParseEventKind::VariantTag(input_tag) => {
let enum_plan = wip.enum_plan().unwrap();
let (variant, is_using_other_fallback) = match input_tag {
Some(tag) => {
let found_idx = enum_plan.variant_lookup.find(tag);
let is_fallback = found_idx.is_none();
let variant_idx =
found_idx.or(enum_plan.other_variant_idx).ok_or_else(|| {
self.mk_err(
&wip,
DeserializeErrorKind::UnknownVariant {
variant: Cow::Owned(tag.to_owned()),
enum_shape: wip.shape(),
},
)
})?;
(&enum_def.variants[variant_idx], is_fallback)
}
None => {
let variant_idx = enum_plan.other_variant_idx.ok_or_else(|| {
self.mk_err(
&wip,
DeserializeErrorKind::Unsupported {
message: "unit tag requires #[facet(other)] fallback".into(),
},
)
})?;
(&enum_def.variants[variant_idx], true)
}
};
match variant.data.kind {
StructKind::Unit => {
if is_using_other_fallback {
if let Some(tag) = input_tag {
wip = self.set_string_value(wip, Cow::Borrowed(tag))?;
} else {
wip = wip.set_default()?;
}
} else {
wip = self
.set_string_value(wip, Cow::Borrowed(variant.effective_name()))?;
}
}
StructKind::TupleStruct | StructKind::Tuple => {
if variant.data.fields.len() == 1 {
wip = wip.init_map()?;
wip = wip
.begin_object_entry(variant.effective_name())?
.with(|w| {
self.deserialize_value_recursive(
w,
variant.data.fields[0].shape.get(),
)
})?
.end()?;
} else {
wip = wip.init_map()?;
wip = wip
.begin_object_entry(variant.effective_name())?
.with(|w| self.deserialize_tuple_dynamic(w, variant.data.fields))?
.end()?;
}
}
StructKind::Struct => {
wip = wip.init_map()?;
wip = wip
.begin_object_entry(variant.effective_name())?
.with(|w| self.deserialize_struct_dynamic(w, variant.data.fields))?
.end()?;
}
}
}
ParseEventKind::StructStart(_) => {
wip = self.deserialize_enum_as_struct(wip, enum_def)?;
}
_ => {
return Err(self.mk_err(
&wip,
DeserializeErrorKind::UnexpectedToken {
expected: "enum variant",
got: event.kind_name().into(),
},
));
}
}
Ok(wip)
}
pub(crate) fn deserialize_scalar_dynamic(
&mut self,
mut wip: Partial<'input, BORROW>,
hint_shape: &'static Shape,
) -> Result<Partial<'input, BORROW>, DeserializeError> {
let _guard = SpanGuard::new(self.last_span);
let hint = match hint_shape.scalar_type() {
Some(ScalarType::Bool) => Some(ScalarTypeHint::Bool),
Some(ScalarType::U8) => Some(ScalarTypeHint::U8),
Some(ScalarType::U16) => Some(ScalarTypeHint::U16),
Some(ScalarType::U32) => Some(ScalarTypeHint::U32),
Some(ScalarType::U64) => Some(ScalarTypeHint::U64),
Some(ScalarType::U128) => Some(ScalarTypeHint::U128),
Some(ScalarType::USize) => Some(ScalarTypeHint::Usize),
Some(ScalarType::I8) => Some(ScalarTypeHint::I8),
Some(ScalarType::I16) => Some(ScalarTypeHint::I16),
Some(ScalarType::I32) => Some(ScalarTypeHint::I32),
Some(ScalarType::I64) => Some(ScalarTypeHint::I64),
Some(ScalarType::I128) => Some(ScalarTypeHint::I128),
Some(ScalarType::ISize) => Some(ScalarTypeHint::Isize),
Some(ScalarType::F32) => Some(ScalarTypeHint::F32),
Some(ScalarType::F64) => Some(ScalarTypeHint::F64),
Some(ScalarType::Char) => Some(ScalarTypeHint::Char),
Some(ScalarType::String | ScalarType::CowStr) => Some(ScalarTypeHint::String),
Some(ScalarType::Str) => Some(ScalarTypeHint::String),
_ if hint_shape.is_from_str() => Some(ScalarTypeHint::String),
_ => None,
};
if self.is_non_self_describing()
&& let Some(h) = hint
{
self.parser.hint_scalar_type(h);
}
let event = self.expect_event("scalar")?;
match event.kind {
ParseEventKind::Scalar(scalar) => match scalar {
ScalarValue::Null => {
wip = wip.set_default()?;
}
ScalarValue::Bool(b) => {
wip = wip.set(b)?;
}
ScalarValue::Char(c) => {
wip = self.set_string_value(wip, Cow::Owned(c.to_string()))?;
}
ScalarValue::I64(i) => {
wip = wip.set(i)?;
}
ScalarValue::U64(u) => {
wip = wip.set(u)?;
}
ScalarValue::I128(i) => {
wip = self.set_string_value(wip, Cow::Owned(i.to_string()))?;
}
ScalarValue::U128(u) => {
wip = self.set_string_value(wip, Cow::Owned(u.to_string()))?;
}
ScalarValue::F64(f) => {
wip = wip.set(f)?;
}
ScalarValue::Str(s) => {
wip = self.set_string_value(wip, s)?;
}
ScalarValue::Bytes(b) => {
wip = self.set_bytes_value(wip, b)?;
}
ScalarValue::Unit => {
wip = wip.set_default()?;
}
},
_ => {
return Err(self.mk_err(
&wip,
DeserializeErrorKind::UnexpectedToken {
expected: "scalar",
got: event.kind_name().into(),
},
));
}
}
Ok(wip)
}
pub(crate) fn deserialize_list_dynamic(
&mut self,
mut wip: Partial<'input, BORROW>,
element_shape: &'static Shape,
) -> Result<Partial<'input, BORROW>, DeserializeError> {
let _guard = SpanGuard::new(self.last_span);
if self.is_non_self_describing() {
self.parser.hint_sequence();
}
let event = self.expect_event("sequence start")?;
if !matches!(event.kind, ParseEventKind::SequenceStart(_)) {
return Err(self.mk_err(
&wip,
DeserializeErrorKind::UnexpectedToken {
expected: "sequence",
got: event.kind_name().into(),
},
));
}
let capacity_hint = self.count_buffered_sequence_items();
wip = wip.init_list_with_capacity(capacity_hint)?;
loop {
let event = self.expect_peek("element or sequence end")?;
if matches!(event.kind, ParseEventKind::SequenceEnd) {
let _ = self.expect_event("sequence end")?;
break;
}
wip = wip
.begin_list_item()?
.with(|w| self.deserialize_value_recursive(w, element_shape))?
.end()?;
}
Ok(wip)
}
pub(crate) fn deserialize_array_dynamic(
&mut self,
mut wip: Partial<'input, BORROW>,
element_shape: &'static Shape,
len: usize,
) -> Result<Partial<'input, BORROW>, DeserializeError> {
let _guard = SpanGuard::new(self.last_span);
if self.is_non_self_describing() {
self.parser.hint_array(len);
}
let event = self.expect_event("array start")?;
if !matches!(event.kind, ParseEventKind::SequenceStart(_)) {
return Err(self.mk_err(
&wip,
DeserializeErrorKind::UnexpectedToken {
expected: "array",
got: event.kind_name().into(),
},
));
}
wip = wip.init_list()?;
for _ in 0..len {
wip = wip
.begin_list_item()?
.with(|w| self.deserialize_value_recursive(w, element_shape))?
.end()?;
}
let event = self.expect_event("array end")?;
if !matches!(event.kind, ParseEventKind::SequenceEnd) {
return Err(self.mk_err(
&wip,
DeserializeErrorKind::UnexpectedToken {
expected: "array end",
got: event.kind_name().into(),
},
));
}
Ok(wip)
}
pub(crate) fn deserialize_map_dynamic(
&mut self,
mut wip: Partial<'input, BORROW>,
key_shape: &'static Shape,
value_shape: &'static Shape,
) -> Result<Partial<'input, BORROW>, DeserializeError> {
let _guard = SpanGuard::new(self.last_span);
if self.is_non_self_describing() {
self.parser.hint_map();
}
let event = self.expect_event("map start")?;
if !matches!(
event.kind,
ParseEventKind::SequenceStart(_) | ParseEventKind::StructStart(_)
) {
return Err(self.mk_err(
&wip,
DeserializeErrorKind::UnexpectedToken {
expected: "map",
got: event.kind_name().into(),
},
));
}
wip = wip.init_map()?;
let key_hint = match key_shape.scalar_type() {
Some(ScalarType::String | ScalarType::CowStr) => Some(ScalarTypeHint::String),
Some(ScalarType::Str) => Some(ScalarTypeHint::String),
Some(
ScalarType::I64
| ScalarType::I32
| ScalarType::I16
| ScalarType::I8
| ScalarType::ISize,
) => Some(ScalarTypeHint::I64),
Some(
ScalarType::U64
| ScalarType::U32
| ScalarType::U16
| ScalarType::U8
| ScalarType::USize,
) => Some(ScalarTypeHint::U64),
_ => None,
};
loop {
let event = self.expect_peek("map entry or end")?;
if matches!(
event.kind,
ParseEventKind::SequenceEnd | ParseEventKind::StructEnd
) {
let _ = self.expect_event("map end")?;
break;
}
if self.is_non_self_describing()
&& let Some(h) = key_hint
{
self.parser.hint_scalar_type(h);
}
let key_event = self.expect_event("map key")?;
let key_str: Cow<'_, str> = match key_event.kind {
ParseEventKind::Scalar(ScalarValue::Str(s)) => s,
ParseEventKind::Scalar(ScalarValue::I64(i)) => Cow::Owned(i.to_string()),
ParseEventKind::Scalar(ScalarValue::U64(u)) => Cow::Owned(u.to_string()),
ParseEventKind::FieldKey(k) => k.name().cloned().unwrap_or(Cow::Borrowed("@")),
_ => {
return Err(self.mk_err(
&wip,
DeserializeErrorKind::UnexpectedToken {
expected: "map key",
got: key_event.kind_name().into(),
},
));
}
};
wip = wip
.begin_object_entry(&key_str)?
.with(|w| self.deserialize_value_recursive(w, value_shape))?
.end()?;
}
Ok(wip)
}
}