Skip to content

Commit

Permalink
Emit separator based on whether list/dict member is first
Browse files Browse the repository at this point in the history
Rather than whether the underlying buffer is empty.
  • Loading branch information
apasel422 committed Feb 18, 2025
1 parent 38faf07 commit e55deee
Showing 1 changed file with 65 additions and 72 deletions.
137 changes: 65 additions & 72 deletions src/ref_serializer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::serializer::Serializer;
use crate::{AsRefBareItem, RefBareItem, SFVResult};
use std::marker::PhantomData;

/// Serializes `Item` field value components incrementally.
/// ```
Expand Down Expand Up @@ -46,6 +45,14 @@ impl<'a> RefParameterSerializer<'a> {
}
}

fn write_separator(buffer: &mut String, is_first: &mut bool) {
if *is_first {
*is_first = false;
} else {
buffer.push_str(", ");
}
}

/// Serializes `List` field value components incrementally.
/// ```
/// use sfv::{RefBareItem, RefListSerializer};
Expand Down Expand Up @@ -75,41 +82,35 @@ impl<'a> RefParameterSerializer<'a> {
#[derive(Debug)]
pub struct RefListSerializer<'a> {
buffer: &'a mut String,
is_first: bool,
}

impl<'a> RefListSerializer<'a> {
pub fn new(buffer: &'a mut String) -> Self {
RefListSerializer { buffer }
RefListSerializer {
buffer,
is_first: true,
}
}

pub fn bare_item(self, bare_item: impl AsRefBareItem) -> SFVResult<Self> {
if !self.buffer.is_empty() {
self.buffer.push_str(", ");
}
pub fn bare_item(mut self, bare_item: impl AsRefBareItem) -> SFVResult<Self> {
write_separator(self.buffer, &mut self.is_first);
Serializer::serialize_bare_item(bare_item, self.buffer)?;
Ok(RefListSerializer {
buffer: self.buffer,
})
Ok(self)
}

pub fn parameter(self, name: &str, value: impl AsRefBareItem) -> SFVResult<Self> {
if self.buffer.is_empty() {
if self.is_first {
return Err("parameters must be serialized after bare item or inner list");
}
Serializer::serialize_parameter(name, value, self.buffer)?;
Ok(RefListSerializer {
buffer: self.buffer,
})
Ok(self)
}
pub fn open_inner_list(self) -> RefInnerListSerializer<'a, Self> {
if !self.buffer.is_empty() {
self.buffer.push_str(", ");
}

pub fn open_inner_list(mut self) -> RefInnerListSerializer<Self> {
write_separator(self.buffer, &mut self.is_first);
self.buffer.push('(');
RefInnerListSerializer::<RefListSerializer> {
buffer: self.buffer,
caller_type: PhantomData,
}
RefInnerListSerializer { buffer: self }
}
}

Expand Down Expand Up @@ -148,17 +149,19 @@ impl<'a> RefListSerializer<'a> {
#[derive(Debug)]
pub struct RefDictSerializer<'a> {
buffer: &'a mut String,
is_first: bool,
}

impl<'a> RefDictSerializer<'a> {
pub fn new(buffer: &'a mut String) -> Self {
RefDictSerializer { buffer }
RefDictSerializer {
buffer,
is_first: true,
}
}

pub fn bare_item_member(self, name: &str, value: impl AsRefBareItem) -> SFVResult<Self> {
if !self.buffer.is_empty() {
self.buffer.push_str(", ");
}
pub fn bare_item_member(mut self, name: &str, value: impl AsRefBareItem) -> SFVResult<Self> {
write_separator(self.buffer, &mut self.is_first);
Serializer::serialize_key(name, self.buffer)?;
let value = value.as_ref_bare_item();
if value != RefBareItem::Boolean(true) {
Expand All @@ -169,77 +172,69 @@ impl<'a> RefDictSerializer<'a> {
}

pub fn parameter(self, name: &str, value: impl AsRefBareItem) -> SFVResult<Self> {
if self.buffer.is_empty() {
if self.is_first {
return Err("parameters must be serialized after bare item or inner list");
}
Serializer::serialize_parameter(name, value, self.buffer)?;
Ok(RefDictSerializer {
buffer: self.buffer,
})
Ok(self)
}

pub fn open_inner_list(self, name: &str) -> SFVResult<RefInnerListSerializer<'a, Self>> {
if !self.buffer.is_empty() {
self.buffer.push_str(", ");
}
pub fn open_inner_list(mut self, name: &str) -> SFVResult<RefInnerListSerializer<Self>> {
write_separator(self.buffer, &mut self.is_first);
Serializer::serialize_key(name, self.buffer)?;
self.buffer.push_str("=(");
Ok(RefInnerListSerializer::<RefDictSerializer> {
buffer: self.buffer,
caller_type: PhantomData,
})
Ok(RefInnerListSerializer { buffer: self })
}
}

/// Used by `RefItemSerializer`, `RefListSerializer`, `RefDictSerializer` to serialize `InnerList`.
#[derive(Debug)]
pub struct RefInnerListSerializer<'a, T> {
buffer: &'a mut String,
caller_type: PhantomData<T>,
pub struct RefInnerListSerializer<T> {
buffer: T,
}

impl<'a, T: Container<'a>> RefInnerListSerializer<'a, T> {
pub fn inner_list_bare_item(self, bare_item: impl AsRefBareItem) -> SFVResult<Self> {
if !self.buffer.is_empty() & !self.buffer.ends_with('(') {
self.buffer.push(' ');
impl<T: BufferHolder> RefInnerListSerializer<T> {
pub fn inner_list_bare_item(mut self, bare_item: impl AsRefBareItem) -> SFVResult<Self> {
let buffer = self.buffer.get_mut();
if !buffer.is_empty() & !buffer.ends_with('(') {
buffer.push(' ');
}
Serializer::serialize_bare_item(bare_item, self.buffer)?;
Ok(RefInnerListSerializer {
buffer: self.buffer,
caller_type: PhantomData,
})
Serializer::serialize_bare_item(bare_item, buffer)?;
Ok(self)
}

pub fn inner_list_parameter(self, name: &str, value: impl AsRefBareItem) -> SFVResult<Self> {
if self.buffer.is_empty() {
pub fn inner_list_parameter(
mut self,
name: &str,
value: impl AsRefBareItem,
) -> SFVResult<Self> {
let buffer = self.buffer.get_mut();
if buffer.is_empty() {
return Err("parameters must be serialized after bare item or inner list");
}
Serializer::serialize_parameter(name, value, self.buffer)?;
Ok(RefInnerListSerializer {
buffer: self.buffer,
caller_type: PhantomData,
})
Serializer::serialize_parameter(name, value, buffer)?;
Ok(self)
}

pub fn close_inner_list(self) -> T {
self.buffer.push(')');
T::new(self.buffer)
pub fn close_inner_list(mut self) -> T {
self.buffer.get_mut().push(')');
self.buffer
}
}

pub trait Container<'a> {
fn new(buffer: &'a mut String) -> Self;
pub trait BufferHolder {
fn get_mut(&mut self) -> &mut String;
}

impl<'a> Container<'a> for RefListSerializer<'a> {
fn new(buffer: &mut String) -> RefListSerializer {
RefListSerializer { buffer }
impl BufferHolder for RefListSerializer<'_> {
fn get_mut(&mut self) -> &mut String {
self.buffer
}
}

impl<'a> Container<'a> for RefDictSerializer<'a> {
fn new(buffer: &mut String) -> RefDictSerializer {
RefDictSerializer { buffer }
impl BufferHolder for RefDictSerializer<'_> {
fn get_mut(&mut self) -> &mut String {
self.buffer
}
}

Expand Down Expand Up @@ -311,8 +306,7 @@ mod alternative_serializer_tests {
let mut output = String::from(" ");
let ser = RefListSerializer::new(&mut output);
ser.bare_item(1)?;
// TODO(https://github.com/undef1nd/sfv/issues/131): This is wrong.
assert_eq!(output, " , 1");
assert_eq!(output, " 1");
Ok(())
}

Expand All @@ -321,8 +315,7 @@ mod alternative_serializer_tests {
let mut output = String::from(" ");
let ser = RefDictSerializer::new(&mut output);
ser.bare_item_member("key1", 1)?;
// TODO(https://github.com/undef1nd/sfv/issues/131): This is wrong.
assert_eq!(output, " , key1=1");
assert_eq!(output, " key1=1");
Ok(())
}
}

0 comments on commit e55deee

Please sign in to comment.