Skip to content

Commit

Permalink
Touch up on API, add some docs, fix inline call to indent
Browse files Browse the repository at this point in the history
  • Loading branch information
voidentente committed Aug 6, 2024
1 parent 4edf360 commit 1664ad1
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 37 deletions.
72 changes: 51 additions & 21 deletions src/meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,96 @@ use std::collections::HashMap;

use serde_derive::{Deserialize, Serialize};

/// The metadata and inner [Fields] of a field
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct Field {
meta: String,
inner: Option<Fields>,
fields: Option<Fields>,
}

impl Field {
pub const fn new() -> Self {
/// Create a new empty field metadata
pub const fn empty() -> Self {
Self {
meta: String::new(),
inner: None,
fields: None,
}
}

pub fn get_meta(&self) -> &str {
self.meta.as_str()
/// Create a new field metadata
pub fn new(meta: impl Into<String>, fields: Option<Fields>) -> Self {
Self {
meta: meta.into(),
fields,
}
}

pub fn set_meta(&mut self, meta: impl Into<String>) {
/// Set the metadata of this field
pub fn with_meta(&mut self, meta: impl Into<String>) -> &mut Self {
self.meta = meta.into();
self
}

pub fn has_inner(&self) -> bool {
self.inner.is_some()
/// Set the inner fields of this field
pub fn with_fields(&mut self, fields: Option<Fields>) -> &mut Self {
self.fields = fields;
self
}

/// Get the metadata of this field
pub fn get_meta(&self) -> &str {
self.meta.as_str()
}

pub fn set_inner(&mut self, fields: Fields) {
self.inner = Some(fields);
/// Return whether this field has inner fields
pub fn has_fields(&self) -> bool {
self.fields.is_some()
}

pub fn inner(&self) -> Option<&Fields> {
self.inner.as_ref()
/// Get a reference to the inner fields of this field, if it has any
pub fn fields(&self) -> Option<&Fields> {
self.fields.as_ref()
}

pub fn inner_mut(&mut self) -> Option<&mut Fields> {
self.inner.as_mut()
/// Get a mutable reference to the inner fields of this field, if it has any
pub fn fields_mut(&mut self) -> Option<&mut Fields> {
self.fields.as_mut()
}
}

/// Mapping of names to [Field]s
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct Fields {
fields: HashMap<String, Field>,
}

impl Fields {
/// Return a new, empty metadata field map
pub fn new() -> Self {
Self {
fields: HashMap::default(),
}
Self::default()
}

pub fn field(&self, name: impl AsRef<str>) -> Option<&Field> {
/// Get a reference to the field with the provided `name`, if it exists
pub fn get_field(&self, name: impl AsRef<str>) -> Option<&Field> {
self.fields.get(name.as_ref())
}

pub fn field_mut(&mut self, name: impl AsRef<str>) -> Option<&mut Field> {
/// Get a mutable reference to the field with the provided `name`, if it exists
pub fn get_field_mut(&mut self, name: impl AsRef<str>) -> Option<&mut Field> {
self.fields.get_mut(name.as_ref())
}

pub fn field_mut_or_default(&mut self, name: impl Into<String>) -> &mut Field {
self.fields.entry(name.into()).or_default()
/// Get a mutable reference to the field with the provided `name`,
/// inserting an empty [`Field`] if it didn't exist
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: HashMap::from_iter(iter.into_iter().map(|(k, v)| (k.into(), v))),
}
}
}
28 changes: 12 additions & 16 deletions src/ser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1344,33 +1344,29 @@ impl<'a, W: fmt::Write> ser::SerializeStruct for Compound<'a, W> {
let name = iter.next().expect(
"is always at least one, because we push one at the beginning of this function",
);
let mut field = config.meta.field(name);
let mut field = config.meta.get_field(name);

while let Some(name) = iter.next() {
let Some(some_field) = field else { break };

let Some(fields) = some_field.inner() else {
let Some(fields) = some_field.fields() else {
field = None;
break;
};

field = fields.field(name);
field = fields.get_field(name);
}

if let Some(field) = field {
for line in field.get_meta().lines() {
let s = format!("/// {line}\n");
self.ser.output.write_str(&s)?;

// FIXME: Can't call `self.ser.indent` because we immutably borrow ser via field,
// but we don't need the entire ser mutable, only ser.output so this works
if let Some((ref config, ref pretty)) = self.ser.pretty {
if pretty.indent <= config.depth_limit {
for _ in 0..pretty.indent {
self.ser.output.write_str(&config.indentor)?;
}
}
}
let lines: Vec<_> = field
.get_meta()
.lines()
.map(|line| format!("/// {line}\n"))
.collect();

for line in lines {
self.ser.output.write_str(&line)?;
self.ser.indent()?;
}
}
}
Expand Down

0 comments on commit 1664ad1

Please sign in to comment.