extern crate alloc;
use std::borrow::Cow;
use facet_core::{NumericType, PrimitiveType, ScalarType, Type, UserType};
use facet_reflect::{Partial, Span};
use crate::{DeserializeError, DeserializeErrorKind, FormatDeserializer, ScalarValue};
#[allow(clippy::result_large_err)]
pub(crate) fn set_scalar_inner<'input, const BORROW: bool>(
mut wip: Partial<'input, BORROW>,
scalar: ScalarValue<'input>,
) -> Result<Partial<'input, BORROW>, SetScalarResult<'input, BORROW>> {
let shape = wip.shape();
let scalar_type = shape.scalar_type();
match scalar {
ScalarValue::Null => {
wip = wip.set_default()?;
}
ScalarValue::Bool(b) => {
wip = wip.set(b)?;
}
ScalarValue::Char(c) => {
wip = wip.set(c)?;
}
ScalarValue::I64(n) => {
match scalar_type {
Some(ScalarType::I8) => wip = wip.set(n as i8)?,
Some(ScalarType::I16) => wip = wip.set(n as i16)?,
Some(ScalarType::I32) => wip = wip.set(n as i32)?,
Some(ScalarType::I64) => wip = wip.set(n)?,
Some(ScalarType::I128) => wip = wip.set(n as i128)?,
Some(ScalarType::ISize) => wip = wip.set(n as isize)?,
Some(ScalarType::U8) => wip = wip.set(n as u8)?,
Some(ScalarType::U16) => wip = wip.set(n as u16)?,
Some(ScalarType::U32) => wip = wip.set(n as u32)?,
Some(ScalarType::U64) => wip = wip.set(n as u64)?,
Some(ScalarType::U128) => wip = wip.set(n as u128)?,
Some(ScalarType::USize) => wip = wip.set(n as usize)?,
Some(ScalarType::F32) => wip = wip.set(n as f32)?,
Some(ScalarType::F64) => wip = wip.set(n as f64)?,
Some(ScalarType::String) => {
wip = wip.set(alloc::string::ToString::to_string(&n))?
}
_ => wip = wip.set(n)?,
}
}
ScalarValue::U64(n) => {
match scalar_type {
Some(ScalarType::U8) => wip = wip.set(n as u8)?,
Some(ScalarType::U16) => wip = wip.set(n as u16)?,
Some(ScalarType::U32) => wip = wip.set(n as u32)?,
Some(ScalarType::U64) => wip = wip.set(n)?,
Some(ScalarType::U128) => wip = wip.set(n as u128)?,
Some(ScalarType::USize) => wip = wip.set(n as usize)?,
Some(ScalarType::I8) => wip = wip.set(n as i8)?,
Some(ScalarType::I16) => wip = wip.set(n as i16)?,
Some(ScalarType::I32) => wip = wip.set(n as i32)?,
Some(ScalarType::I64) => wip = wip.set(n as i64)?,
Some(ScalarType::I128) => wip = wip.set(n as i128)?,
Some(ScalarType::ISize) => wip = wip.set(n as isize)?,
Some(ScalarType::F32) => wip = wip.set(n as f32)?,
Some(ScalarType::F64) => wip = wip.set(n as f64)?,
Some(ScalarType::String) => {
wip = wip.set(alloc::string::ToString::to_string(&n))?
}
_ => wip = wip.set(n)?,
}
}
ScalarValue::U128(n) => {
match scalar_type {
Some(ScalarType::U128) => wip = wip.set(n)?,
Some(ScalarType::I128) => wip = wip.set(n as i128)?,
_ => wip = wip.set(n as u64)?,
}
}
ScalarValue::I128(n) => {
match scalar_type {
Some(ScalarType::I128) => wip = wip.set(n)?,
Some(ScalarType::U128) => wip = wip.set(n as u128)?,
_ => wip = wip.set(n as i64)?,
}
}
ScalarValue::F64(n) => {
match scalar_type {
Some(ScalarType::F32) => wip = wip.set(n as f32)?,
Some(ScalarType::F64) => wip = wip.set(n)?,
_ if shape.vtable.has_try_from() && shape.inner.is_some() => {
let inner_shape = shape.inner.unwrap();
wip = wip.begin_inner()?;
if inner_shape.is_type::<f32>() {
wip = wip.set(n as f32)?;
} else {
wip = wip.set(n)?;
}
wip = wip.end()?;
}
_ if shape.vtable.has_parse() => {
wip = wip.parse_from_str(&alloc::string::ToString::to_string(&n))?;
}
_ => wip = wip.set(n)?,
}
}
ScalarValue::Str(s) => {
if shape.vtable.has_parse() {
wip = wip.parse_from_str(s.as_ref())?;
} else {
return Err(SetScalarResult::NeedsStringValue { wip, s });
}
}
ScalarValue::Bytes(b) => {
if shape.vtable.has_parse_bytes() {
wip = wip.parse_from_bytes(b.as_ref())?;
} else {
return Err(SetScalarResult::NeedsBytesValue { wip, b });
}
}
ScalarValue::Unit => {
wip = wip.set_default()?;
}
}
Ok(wip)
}
pub(crate) enum SetScalarResult<'input, const BORROW: bool> {
NeedsStringValue {
wip: Partial<'input, BORROW>,
s: Cow<'input, str>,
},
NeedsBytesValue {
wip: Partial<'input, BORROW>,
b: Cow<'input, [u8]>,
},
Error(DeserializeError),
}
impl<'input, const BORROW: bool> From<DeserializeError> for SetScalarResult<'input, BORROW> {
fn from(e: DeserializeError) -> Self {
SetScalarResult::Error(e)
}
}
impl<'input, const BORROW: bool> From<facet_reflect::ReflectError>
for SetScalarResult<'input, BORROW>
{
fn from(e: facet_reflect::ReflectError) -> Self {
SetScalarResult::Error(e.into())
}
}
pub(crate) enum MapKeyTerminalResult<'input, const BORROW: bool> {
NeedsSetString {
wip: Partial<'input, BORROW>,
s: Cow<'input, str>,
},
Error(DeserializeError),
}
impl<'input, const BORROW: bool> From<DeserializeError> for MapKeyTerminalResult<'input, BORROW> {
fn from(e: DeserializeError) -> Self {
MapKeyTerminalResult::Error(e)
}
}
impl<'input, const BORROW: bool> From<facet_reflect::ReflectError>
for MapKeyTerminalResult<'input, BORROW>
{
fn from(e: facet_reflect::ReflectError) -> Self {
MapKeyTerminalResult::Error(e.into())
}
}
#[allow(clippy::result_large_err)]
pub(crate) fn deserialize_map_key_terminal_inner<'input, const BORROW: bool>(
mut wip: Partial<'input, BORROW>,
key: Cow<'input, str>,
span: Span,
) -> Result<Partial<'input, BORROW>, MapKeyTerminalResult<'input, BORROW>> {
let shape = wip.shape();
if let Type::User(UserType::Enum(_)) = &shape.ty {
wip = wip.select_variant_named(&key)?;
return Ok(wip);
}
if let Type::Primitive(PrimitiveType::Numeric(num_ty)) = &shape.ty {
match num_ty {
NumericType::Integer { signed } => {
if *signed {
let n: i64 = key.parse().map_err(|_| DeserializeError {
span: Some(span),
path: None,
kind: DeserializeErrorKind::UnexpectedToken {
expected: "valid integer for map key",
got: alloc::format!("string '{}'", key).into(),
},
})?;
wip = wip.set(n)?;
} else {
let n: u64 = key.parse().map_err(|_| DeserializeError {
span: Some(span),
path: None,
kind: DeserializeErrorKind::UnexpectedToken {
expected: "valid unsigned integer for map key",
got: alloc::format!("string '{}'", key).into(),
},
})?;
wip = wip.set(n)?;
}
return Ok(wip);
}
NumericType::Float => {
let n: f64 = key.parse().map_err(|_| DeserializeError {
span: Some(span),
path: None,
kind: DeserializeErrorKind::UnexpectedToken {
expected: "valid float for map key",
got: alloc::format!("string '{}'", key).into(),
},
})?;
wip = wip.set(n)?;
return Ok(wip);
}
}
}
Err(MapKeyTerminalResult::NeedsSetString { wip, s: key })
}
impl<'parser, 'input, const BORROW: bool> FormatDeserializer<'parser, 'input, BORROW> {
pub(crate) fn set_scalar(
&mut self,
wip: Partial<'input, BORROW>,
scalar: ScalarValue<'input>,
) -> Result<Partial<'input, BORROW>, DeserializeError> {
match set_scalar_inner(wip, scalar) {
Ok(wip) => Ok(wip),
Err(SetScalarResult::NeedsStringValue { wip, s }) => self.set_string_value(wip, s),
Err(SetScalarResult::NeedsBytesValue { wip, b }) => self.set_bytes_value(wip, b),
Err(SetScalarResult::Error(e)) => Err(e),
}
}
pub(crate) fn set_string_value(
&mut self,
wip: Partial<'input, BORROW>,
s: Cow<'input, str>,
) -> Result<Partial<'input, BORROW>, DeserializeError> {
facet_dessert::set_string_value(wip, s, Some(self.last_span)).map_err(|e| match e {
facet_dessert::DessertError::Reflect { error, span } => DeserializeError {
span,
path: Some(error.path),
kind: DeserializeErrorKind::Reflect {
kind: error.kind,
context: "",
},
},
facet_dessert::DessertError::CannotBorrow { message } => DeserializeError {
span: None,
path: None,
kind: DeserializeErrorKind::CannotBorrow { reason: message },
},
})
}
pub(crate) fn set_bytes_value(
&mut self,
wip: Partial<'input, BORROW>,
b: Cow<'input, [u8]>,
) -> Result<Partial<'input, BORROW>, DeserializeError> {
facet_dessert::set_bytes_value(wip, b, Some(self.last_span)).map_err(|e| match e {
facet_dessert::DessertError::Reflect { error, span } => DeserializeError {
span,
path: Some(error.path),
kind: DeserializeErrorKind::Reflect {
kind: error.kind,
context: "",
},
},
facet_dessert::DessertError::CannotBorrow { message } => DeserializeError {
span: None,
path: None,
kind: DeserializeErrorKind::CannotBorrow { reason: message },
},
})
}
}