use std::fmt::Write;
use solana_idl::{EnumFields, IdlEnumVariant, IdlType};
use crate::{
errors::ChainsawResult,
json::json_serialization_opts::JsonSerializationOpts, ChainsawError,
};
use super::{
json_common::{deserialize_fields_to_object, write_quoted},
json_idl_field_de::JsonIdlFieldDeserializer,
json_idl_type_de::JsonIdlTypeDeserializer,
JsonTypeDefinitionDeserializerMap,
};
#[derive(Clone)]
pub struct JsonIdlEnumVariantDeserializer<'opts> {
pub name: String,
pub named_fields: Option<Vec<JsonIdlFieldDeserializer<'opts>>>,
pub tuple_types: Option<(JsonIdlTypeDeserializer<'opts>, IdlType)>,
pub type_map: JsonTypeDefinitionDeserializerMap<'opts>,
}
impl<'opts> JsonIdlEnumVariantDeserializer<'opts> {
pub fn new(
variant: &IdlEnumVariant,
type_map: JsonTypeDefinitionDeserializerMap<'opts>,
opts: &'opts JsonSerializationOpts,
) -> Self {
let name = variant.name.clone();
use EnumFields::*;
match &variant.fields {
Some(Named(fields)) => {
let named_fields = fields
.iter()
.map(|f| {
JsonIdlFieldDeserializer::new(f, type_map.clone(), opts)
})
.collect();
Self {
name,
named_fields: Some(named_fields),
tuple_types: None,
type_map,
}
}
Some(Tuple(types)) => {
let tuple_ty_de =
JsonIdlTypeDeserializer::new(type_map.clone(), opts);
Self {
name,
named_fields: None,
tuple_types: Some((
tuple_ty_de,
IdlType::Tuple(types.clone()),
)),
type_map,
}
}
None => Self {
name,
named_fields: None,
tuple_types: None,
type_map,
},
}
}
pub fn deserialize<W: Write>(
&self,
f: &mut W,
buf: &mut &[u8],
) -> ChainsawResult<()> {
if let Some(named_fields) = &self.named_fields {
f.write_char('{')?;
{
self.write_key(f)?;
deserialize_fields_to_object(f, buf, named_fields).map_err(
|e| {
ChainsawError::EnumVariantDeserializeError(
self.name.to_string(),
Box::new(e),
)
},
)?;
}
f.write_char('}')?;
} else if let Some((tuple_ty_de, ty)) = &self.tuple_types {
f.write_char('{')?;
{
self.write_key(f)?;
self.deserialize_tuple_fields(f, buf, tuple_ty_de, ty)
.map_err(|e| {
ChainsawError::EnumVariantDeserializeError(
self.name.to_string(),
Box::new(e),
)
})?;
}
f.write_char('}')?;
} else {
write_quoted(f, &self.name)?;
}
Ok(())
}
fn deserialize_tuple_fields<W: Write>(
&self,
f: &mut W,
buf: &mut &[u8],
tuple_el_de: &JsonIdlTypeDeserializer<'opts>,
ty: &IdlType,
) -> ChainsawResult<()> {
tuple_el_de.deserialize(ty, f, buf)
}
fn write_key<W: Write>(&self, f: &mut W) -> ChainsawResult<()> {
f.write_char('"')?;
f.write_str(&self.name)?;
f.write_str("\":")?;
Ok(())
}
}