use super::{field, Field, ValueType};
use crate::{
amino::{msg::Tag, TypeName},
Error,
};
use eyre::{Result, WrapErr};
use serde::Deserialize;
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct Definition {
type_name: TypeName,
#[serde(deserialize_with = "field::deserialize_vec")]
fields: Vec<Field>,
}
impl Definition {
pub fn new(type_name: TypeName, fields: impl Into<Vec<Field>>) -> Result<Self> {
let fields = fields.into();
if let Err(e) = field::validate(&fields) {
return Err(Error::Parse).wrap_err_with(|| e.to_string());
}
Ok(Self { type_name, fields })
}
pub fn type_name(&self) -> &TypeName {
&self.type_name
}
pub fn fields(&self) -> &[Field] {
self.fields.as_slice()
}
pub fn get_field(&self, field_name: &TypeName) -> Option<&Field> {
self.fields.iter().find(|field| field.name() == field_name)
}
pub fn get_field_tag(&self, field_name: &TypeName, value_type: ValueType) -> Result<Tag> {
let field = self
.get_field(field_name)
.ok_or(Error::Type)
.wrap_err_with(|| {
format!(
"field name not found in `{}` schema: `{}`",
&self.type_name, field_name
)
})?;
if field.value_type() != value_type {
return Err(Error::Type).wrap_err_with(|| {
format!(
"field `{}` of `{}` is not an {} (expected {})",
field_name,
&self.type_name,
value_type,
field.value_type()
)
});
}
Ok(field.tag())
}
}