Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/sfv/src/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 10 kB image not shown  

Quelle  ref_serializer.rs   Sprache: unbekannt

 
use crate::serializer::Serializer;
use crate::{RefBareItem, SFVResult};
use std::marker::PhantomData;

/// Serializes `Item` field value components incrementally.
/// ```
/// use sfv::{RefBareItem, RefItemSerializer};
///
/// let mut serialized_item = String::new();
/// let serializer = RefItemSerializer::new(&mut serialized_item);
/// serializer
/// .bare_item(&RefBareItem::Integer(11))
/// .unwrap()
/// .parameter("foo", &RefBareItem::Boolean(true))
/// .unwrap();
/// assert_eq!(serialized_item, "11;foo");
/// ```
#[derive(Debug)]
pub struct RefItemSerializer<'a> {
    pub buffer: &'a mut String,
}

impl<'a> RefItemSerializer<'a> {
    pub fn new(buffer: &'a mut String) -> Self {
        RefItemSerializer { buffer }
    }

    pub fn bare_item(self, bare_item: &RefBareItem) -> SFVResult<RefParameterSerializer<'a>> {
        Serializer::serialize_ref_bare_item(bare_item, self.buffer)?;
        Ok(RefParameterSerializer {
            buffer: self.buffer,
        })
    }
}

/// Used by `RefItemSerializer`, `RefListSerializer`, `RefDictSerializer` to serialize a single `Parameter`.
#[derive(Debug)]
pub struct RefParameterSerializer<'a> {
    buffer: &'a mut String,
}

impl<'a> RefParameterSerializer<'a> {
    pub fn parameter(self, name: &str, value: &RefBareItem) -> SFVResult<Self> {
        Serializer::serialize_ref_parameter(name, value, self.buffer)?;
        Ok(self)
    }
}

/// Serializes `List` field value components incrementally.
/// ```
/// use sfv::{RefBareItem, RefListSerializer};
///
/// let mut serialized_item = String::new();
/// let serializer = RefListSerializer::new(&mut serialized_item);
/// serializer
///     .bare_item(&RefBareItem::Integer(11))
///     .unwrap()
///     .parameter("foo", &RefBareItem::Boolean(true))
///     .unwrap()
///     .open_inner_list()
///     .inner_list_bare_item(&RefBareItem::Token("abc"))
///     .unwrap()
///     .inner_list_parameter("abc_param", &RefBareItem::Boolean(false))
///     .unwrap()
///     .inner_list_bare_item(&RefBareItem::Token("def"))
///     .unwrap()
///     .close_inner_list()
///     .parameter("bar", &RefBareItem::String("val"))
///     .unwrap();
/// assert_eq!(
///     serialized_item,
///     "11;foo, (abc;abc_param=?0 def);bar=\"val\""
/// );
/// ```
#[derive(Debug)]
pub struct RefListSerializer<'a> {
    buffer: &'a mut String,
}

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

    pub fn bare_item(self, bare_item: &RefBareItem) -> SFVResult<Self> {
        if !self.buffer.is_empty() {
            self.buffer.push_str(", ");
        }
        Serializer::serialize_ref_bare_item(bare_item, self.buffer)?;
        Ok(RefListSerializer {
            buffer: self.buffer,
        })
    }

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

/// Serializes `Dictionary` field value components incrementally.
/// ```
/// use sfv::{RefBareItem, RefDictSerializer, Decimal, FromPrimitive};
///
/// let mut serialized_item = String::new();
/// let serializer = RefDictSerializer::new(&mut serialized_item);
/// serializer
///    .bare_item_member("member1", &RefBareItem::Integer(11))
///    .unwrap()
///    .parameter("foo", &RefBareItem::Boolean(true))
///    .unwrap()
///    .open_inner_list("member2")
///    .unwrap()
///    .inner_list_bare_item(&RefBareItem::Token("abc"))
///    .unwrap()
///    .inner_list_parameter("abc_param", &RefBareItem::Boolean(false))
///    .unwrap()
///    .inner_list_bare_item(&RefBareItem::Token("def"))
///    .unwrap()
///    .close_inner_list()
///    .parameter("bar", &RefBareItem::String("val"))
///    .unwrap()
///    .bare_item_member(
///         "member3",
///         &RefBareItem::Decimal(Decimal::from_f64(12.34566).unwrap()),
///    )
///    .unwrap();
/// assert_eq!(
///    serialized_item,
///    "member1=11;foo, member2=(abc;abc_param=?0 def);bar=\"val\", member3=12.346"
/// );
/// ```
#[derive(Debug)]
pub struct RefDictSerializer<'a> {
    buffer: &'a mut String,
}

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

    pub fn bare_item_member(self, name: &str, value: &RefBareItem) -> SFVResult<Self> {
        if !self.buffer.is_empty() {
            self.buffer.push_str(", ");
        }
        Serializer::serialize_key(name, self.buffer)?;
        if value != &RefBareItem::Boolean(true) {
            self.buffer.push('=');
            Serializer::serialize_ref_bare_item(value, self.buffer)?;
        }
        Ok(self)
    }

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

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

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

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

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

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

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

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

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

#[cfg(test)]
mod alternative_serializer_tests {
    use super::*;
    use crate::{Decimal, FromPrimitive};

    #[test]
    fn test_fast_serialize_item() -> SFVResult<()> {
        let mut output = String::new();
        let ser = RefItemSerializer::new(&mut output);
        ser.bare_item(&RefBareItem::Token("hello"))?
            .parameter("abc", &RefBareItem::Boolean(true))?;
        assert_eq!("hello;abc", output);
        Ok(())
    }

    #[test]
    fn test_fast_serialize_list() -> SFVResult<()> {
        let mut output = String::new();
        let ser = RefListSerializer::new(&mut output);
        ser.bare_item(&RefBareItem::Token("hello"))?
            .parameter("key1", &RefBareItem::Boolean(true))?
            .parameter("key2", &RefBareItem::Boolean(false))?
            .open_inner_list()
            .inner_list_bare_item(&RefBareItem::String("some_string"))?
            .inner_list_bare_item(&RefBareItem::Integer(12))?
            .inner_list_parameter("inner-member-key", &RefBareItem::Boolean(true))?
            .close_inner_list()
            .parameter("inner-list-param", &RefBareItem::Token("*"))?;
        assert_eq!(
            "hello;key1;key2=?0, (\"some_string\" 12;inner-member-key);inner-list-param=*",
            output
        );
        Ok(())
    }

    #[test]
    fn test_fast_serialize_dict() -> SFVResult<()> {
        let mut output = String::new();
        let ser = RefDictSerializer::new(&mut output);
        ser.bare_item_member("member1", &RefBareItem::Token("hello"))?
            .parameter("key1", &RefBareItem::Boolean(true))?
            .parameter("key2", &RefBareItem::Boolean(false))?
            .bare_item_member("member2", &RefBareItem::Boolean(true))?
            .parameter(
                "key3",
                &RefBareItem::Decimal(Decimal::from_f64(45.4586).unwrap()),
            )?
            .parameter("key4", &RefBareItem::String("str"))?
            .open_inner_list("key5")?
            .inner_list_bare_item(&RefBareItem::Integer(45))?
            .inner_list_bare_item(&RefBareItem::Integer(0))?
            .close_inner_list()
            .bare_item_member("key6", &RefBareItem::String("foo"))?
            .open_inner_list("key7")?
            .inner_list_bare_item(&RefBareItem::ByteSeq("some_string".as_bytes()))?
            .inner_list_bare_item(&RefBareItem::ByteSeq("other_string".as_bytes()))?
            .close_inner_list()
            .parameter("lparam", &RefBareItem::Integer(10))?
            .bare_item_member("key8", &RefBareItem::Boolean(true))?;
        assert_eq!(
            "member1=hello;key1;key2=?0, member2;key3=45.459;key4=\"str\", key5=(45 0), key6=\"foo\", key7=(:c29tZV9zdHJpbmc=: :b3RoZXJfc3RyaW5n:);lparam=10, key8",
            output
        );
        Ok(())
    }
}

[ Dauer der Verarbeitung: 0.20 Sekunden  (vorverarbeitet)  ]