use alloc::string::String;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "std")]
use std::collections::HashMap as FieldsInner;
#[cfg(not(feature = "std"))]
use alloc::collections::BTreeMap as FieldsInner;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct Field {
doc: String,
fields: Option<Fields>,
}
impl Field {
#[must_use]
pub const fn empty() -> Self {
Self {
doc: String::new(),
fields: None,
}
}
pub fn new(doc: impl Into<String>, fields: Option<Fields>) -> Self {
Self {
doc: doc.into(),
fields,
}
}
#[inline]
#[must_use]
pub fn doc(&self) -> &str {
self.doc.as_str()
}
#[inline]
#[must_use]
pub fn doc_mut(&mut self) -> &mut String {
&mut self.doc
}
pub fn with_doc(&mut self, doc: impl Into<String>) -> &mut Self {
self.doc = doc.into();
self
}
#[must_use]
pub fn fields(&self) -> Option<&Fields> {
self.fields.as_ref()
}
pub fn fields_mut(&mut self) -> Option<&mut Fields> {
self.fields.as_mut()
}
#[must_use]
pub fn has_fields(&self) -> bool {
self.fields.is_some()
}
pub fn with_fields(&mut self, fields: Option<Fields>) -> &mut Self {
self.fields = fields;
self
}
pub fn build_fields(&mut self, builder: impl FnOnce(&mut Fields)) -> &mut Self {
let mut fields = Fields::default();
builder(&mut fields);
self.with_fields(Some(fields));
self
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct Fields {
fields: FieldsInner<String, Field>,
}
impl Fields {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.fields.is_empty()
}
pub fn contains(&self, name: impl AsRef<str>) -> bool {
self.fields.contains_key(name.as_ref())
}
pub fn get(&self, name: impl AsRef<str>) -> Option<&Field> {
self.fields.get(name.as_ref())
}
pub fn get_mut(&mut self, name: impl AsRef<str>) -> Option<&mut Field> {
self.fields.get_mut(name.as_ref())
}
pub fn insert(&mut self, name: impl Into<String>, field: Field) -> Option<Field> {
self.fields.insert(name.into(), field)
}
pub fn remove(&mut self, name: impl AsRef<str>) -> Option<Field> {
self.fields.remove(name.as_ref())
}
pub fn field(&mut self, name: impl Into<String>) -> &mut Field {
self.fields.entry(name.into()).or_insert_with(Field::empty)
}
}
impl<K: Into<String>> FromIterator<(K, Field)> for Fields {
fn from_iter<T: IntoIterator<Item = (K, Field)>>(iter: T) -> Self {
Self {
fields: iter.into_iter().map(|(k, v)| (k.into(), v)).collect(),
}
}
}