use super::ValueType;
use crate::amino::{msg::Tag, type_name::TypeName};
use serde::{de, Deserialize};
use std::collections::BTreeSet as Set;
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct Field {
name: TypeName,
#[serde(rename = "type")]
value_type: ValueType,
tag: Option<Tag>,
}
impl Field {
pub fn new(name: TypeName, value_type: ValueType, tag: Tag) -> Self {
Self {
name,
tag: Some(tag),
value_type,
}
}
pub fn name(&self) -> &TypeName {
&self.name
}
pub fn value_type(&self) -> ValueType {
self.value_type
}
pub fn tag(&self) -> Tag {
self.tag.unwrap()
}
}
pub(crate) fn deserialize_vec<'de, D>(deserializer: D) -> Result<Vec<Field>, D::Error>
where
D: de::Deserializer<'de>,
{
let mut fields: Vec<Field> = Vec::deserialize(deserializer)?;
populate_tags(&mut fields).map_err(de::Error::custom)?;
validate(&fields).map_err(de::Error::custom)?;
Ok(fields)
}
fn populate_tags(fields: &mut [Field]) -> Result<(), &str> {
let mut tag = 1;
for field in fields {
match field.tag {
Some(t) => {
if t == 0 {
return Err("invalid field tag: 0");
}
tag = t + 1
}
None => {
field.tag = Some(tag);
tag += 1;
}
}
}
Ok(())
}
pub(crate) fn validate(fields: &[Field]) -> Result<(), String> {
let mut names = Set::new();
let mut tags = Set::new();
for field in fields {
let tag = field.tag.expect("field with unpopulated tag!");
if !names.insert(&field.name) {
return Err(format!("duplicate field name: `{}`", &field.name));
}
if !tags.insert(tag) {
return Err(format!("duplicate field tag: {}", tag));
}
}
Ok(())
}