use std::borrow::BorrowMut;
use crate::{serializer::Serializer, KeyRef, RefBareItem};
#[cfg(feature = "parsed-types")]
use crate::{Item, ListEntry};
#[derive(Debug)]
#[must_use]
pub struct ItemSerializer<W> {
buffer: W,
}
impl Default for ItemSerializer<String> {
fn default() -> Self {
Self::new()
}
}
impl ItemSerializer<String> {
pub fn new() -> Self {
Self {
buffer: String::new(),
}
}
}
impl<'a> ItemSerializer<&'a mut String> {
pub fn with_buffer(buffer: &'a mut String) -> Self {
Self { buffer }
}
}
impl<W: BorrowMut<String>> ItemSerializer<W> {
pub fn bare_item<'b>(
mut self,
bare_item: impl Into<RefBareItem<'b>>,
) -> ParameterSerializer<W> {
Serializer::serialize_bare_item(bare_item, self.buffer.borrow_mut());
ParameterSerializer {
buffer: self.buffer,
}
}
}
#[derive(Debug)]
#[must_use]
pub struct ParameterSerializer<W> {
buffer: W,
}
impl<W: BorrowMut<String>> ParameterSerializer<W> {
pub fn parameter<'b>(mut self, name: &KeyRef, value: impl Into<RefBareItem<'b>>) -> Self {
Serializer::serialize_parameter(name, value, self.buffer.borrow_mut());
self
}
pub fn parameters<'b>(
mut self,
params: impl IntoIterator<Item = (impl AsRef<KeyRef>, impl Into<RefBareItem<'b>>)>,
) -> Self {
for (name, value) in params {
Serializer::serialize_parameter(name.as_ref(), value, self.buffer.borrow_mut());
}
self
}
#[must_use]
pub fn finish(self) -> W {
self.buffer
}
}
fn maybe_write_separator(buffer: &mut String, first: &mut bool) {
if *first {
*first = false;
} else {
buffer.push_str(", ");
}
}
#[derive(Debug)]
#[must_use]
pub struct ListSerializer<W> {
buffer: W,
first: bool,
}
impl Default for ListSerializer<String> {
fn default() -> Self {
Self::new()
}
}
impl ListSerializer<String> {
pub fn new() -> Self {
Self {
buffer: String::new(),
first: true,
}
}
}
impl<'a> ListSerializer<&'a mut String> {
pub fn with_buffer(buffer: &'a mut String) -> Self {
Self {
buffer,
first: true,
}
}
}
impl<W: BorrowMut<String>> ListSerializer<W> {
pub fn bare_item<'b>(
&mut self,
bare_item: impl Into<RefBareItem<'b>>,
) -> ParameterSerializer<&mut String> {
let buffer = self.buffer.borrow_mut();
maybe_write_separator(buffer, &mut self.first);
Serializer::serialize_bare_item(bare_item, buffer);
ParameterSerializer { buffer }
}
pub fn inner_list(&mut self) -> InnerListSerializer {
let buffer = self.buffer.borrow_mut();
maybe_write_separator(buffer, &mut self.first);
buffer.push('(');
InnerListSerializer {
buffer: Some(buffer),
}
}
#[cfg(feature = "parsed-types")]
pub fn members<'b>(&mut self, members: impl IntoIterator<Item = &'b ListEntry>) {
for value in members {
match value {
ListEntry::Item(value) => {
_ = self.bare_item(&value.bare_item).parameters(&value.params);
}
ListEntry::InnerList(value) => {
let mut ser = self.inner_list();
ser.items(&value.items);
_ = ser.finish().parameters(&value.params);
}
}
}
}
#[must_use]
pub fn finish(self) -> Option<W> {
if self.first {
None
} else {
Some(self.buffer)
}
}
}
#[derive(Debug)]
#[must_use]
pub struct DictSerializer<W> {
buffer: W,
first: bool,
}
impl Default for DictSerializer<String> {
fn default() -> Self {
Self::new()
}
}
impl DictSerializer<String> {
pub fn new() -> Self {
Self {
buffer: String::new(),
first: true,
}
}
}
impl<'a> DictSerializer<&'a mut String> {
pub fn with_buffer(buffer: &'a mut String) -> Self {
Self {
buffer,
first: true,
}
}
}
impl<W: BorrowMut<String>> DictSerializer<W> {
pub fn bare_item<'b>(
&mut self,
name: &KeyRef,
value: impl Into<RefBareItem<'b>>,
) -> ParameterSerializer<&mut String> {
let buffer = self.buffer.borrow_mut();
maybe_write_separator(buffer, &mut self.first);
Serializer::serialize_key(name, buffer);
let value = value.into();
if value != RefBareItem::Boolean(true) {
buffer.push('=');
Serializer::serialize_bare_item(value, buffer);
}
ParameterSerializer { buffer }
}
pub fn inner_list(&mut self, name: &KeyRef) -> InnerListSerializer {
let buffer = self.buffer.borrow_mut();
maybe_write_separator(buffer, &mut self.first);
Serializer::serialize_key(name, buffer);
buffer.push_str("=(");
InnerListSerializer {
buffer: Some(buffer),
}
}
#[cfg(feature = "parsed-types")]
pub fn members<'b>(
&mut self,
members: impl IntoIterator<Item = (impl AsRef<KeyRef>, &'b ListEntry)>,
) {
for (name, value) in members {
match value {
ListEntry::Item(value) => {
_ = self
.bare_item(name.as_ref(), &value.bare_item)
.parameters(&value.params);
}
ListEntry::InnerList(value) => {
let mut ser = self.inner_list(name.as_ref());
ser.items(&value.items);
_ = ser.finish().parameters(&value.params);
}
}
}
}
#[must_use]
pub fn finish(self) -> Option<W> {
if self.first {
None
} else {
Some(self.buffer)
}
}
}
#[derive(Debug)]
#[must_use]
pub struct InnerListSerializer<'a> {
buffer: Option<&'a mut String>,
}
impl Drop for InnerListSerializer<'_> {
fn drop(&mut self) {
if let Some(ref mut buffer) = self.buffer {
buffer.push(')');
}
}
}
impl<'a> InnerListSerializer<'a> {
#[allow(clippy::missing_panics_doc)] pub fn bare_item<'b>(
&mut self,
bare_item: impl Into<RefBareItem<'b>>,
) -> ParameterSerializer<&mut String> {
let buffer = self.buffer.as_mut().unwrap();
if !buffer.is_empty() && !buffer.ends_with('(') {
buffer.push(' ');
}
Serializer::serialize_bare_item(bare_item, buffer);
ParameterSerializer { buffer }
}
#[cfg(feature = "parsed-types")]
pub fn items<'b>(&mut self, items: impl IntoIterator<Item = &'b Item>) {
for item in items {
_ = self.bare_item(&item.bare_item).parameters(&item.params);
}
}
#[allow(clippy::missing_panics_doc)]
pub fn finish(mut self) -> ParameterSerializer<&'a mut String> {
let buffer = self.buffer.take().unwrap();
buffer.push(')');
ParameterSerializer { buffer }
}
}