Source code

Revision control

Copy as Markdown

Other Tools

use serde::ser;
use std::{
fmt::Display,
fs::File,
io::{BufWriter, Write},
mem,
path::Path,
};
use crate::{
date::serde_impls::DATE_NEWTYPE_STRUCT_NAME,
error::{self, Error, ErrorKind},
stream::{self, Writer},
uid::serde_impls::UID_NEWTYPE_STRUCT_NAME,
Date, Integer, Uid, XmlWriteOptions,
};
#[doc(hidden)]
impl ser::Error for Error {
fn custom<T: Display>(msg: T) -> Self {
ErrorKind::Serde(msg.to_string()).without_position()
}
}
enum OptionMode {
Root,
StructField(&'static str),
StructFieldNameWritten,
Explicit,
}
/// A structure that serializes Rust values plist event streams.
pub struct Serializer<W: Writer> {
writer: W,
option_mode: OptionMode,
}
impl<W: Writer> Serializer<W> {
pub fn new(writer: W) -> Serializer<W> {
Serializer {
writer,
option_mode: OptionMode::Root,
}
}
pub fn into_inner(self) -> W {
self.writer
}
fn serialize_with_option_mode<T: ?Sized + ser::Serialize>(
&mut self,
option_mode: OptionMode,
value: &T,
) -> Result<(), Error> {
let prev_option_mode = mem::replace(&mut self.option_mode, option_mode);
let result = value.serialize(&mut *self);
self.option_mode = prev_option_mode;
result
}
fn maybe_write_pending_struct_field_name(&mut self) -> Result<(), Error> {
if let OptionMode::StructField(field_name) = self.option_mode {
self.option_mode = OptionMode::StructFieldNameWritten;
self.writer.write_string(field_name)?;
}
Ok(())
}
fn write_start_array(&mut self, len: Option<u64>) -> Result<(), Error> {
self.maybe_write_pending_struct_field_name()?;
self.writer.write_start_array(len)
}
fn write_start_dictionary(&mut self, len: Option<u64>) -> Result<(), Error> {
self.maybe_write_pending_struct_field_name()?;
self.writer.write_start_dictionary(len)
}
fn write_end_collection(&mut self) -> Result<(), Error> {
self.maybe_write_pending_struct_field_name()?;
self.writer.write_end_collection()
}
fn write_boolean(&mut self, value: bool) -> Result<(), Error> {
self.maybe_write_pending_struct_field_name()?;
self.writer.write_boolean(value)
}
fn write_data(&mut self, value: &[u8]) -> Result<(), Error> {
self.maybe_write_pending_struct_field_name()?;
self.writer.write_data(value)
}
fn write_date(&mut self, value: Date) -> Result<(), Error> {
self.maybe_write_pending_struct_field_name()?;
self.writer.write_date(value)
}
fn write_integer(&mut self, value: Integer) -> Result<(), Error> {
self.maybe_write_pending_struct_field_name()?;
self.writer.write_integer(value)
}
fn write_real(&mut self, value: f64) -> Result<(), Error> {
self.maybe_write_pending_struct_field_name()?;
self.writer.write_real(value)
}
fn write_string(&mut self, value: &str) -> Result<(), Error> {
self.maybe_write_pending_struct_field_name()?;
self.writer.write_string(value)
}
fn write_uid(&mut self, value: Uid) -> Result<(), Error> {
self.maybe_write_pending_struct_field_name()?;
self.writer.write_uid(value)
}
}
impl<'a, W: Writer> ser::Serializer for &'a mut Serializer<W> {
type Ok = ();
type Error = Error;
type SerializeSeq = Compound<'a, W>;
type SerializeTuple = Compound<'a, W>;
type SerializeTupleStruct = Compound<'a, W>;
type SerializeTupleVariant = Compound<'a, W>;
type SerializeMap = Compound<'a, W>;
type SerializeStruct = Compound<'a, W>;
type SerializeStructVariant = Compound<'a, W>;
fn serialize_bool(self, v: bool) -> Result<(), Self::Error> {
self.write_boolean(v)
}
fn serialize_i8(self, v: i8) -> Result<(), Error> {
self.serialize_i64(v.into())
}
fn serialize_i16(self, v: i16) -> Result<(), Error> {
self.serialize_i64(v.into())
}
fn serialize_i32(self, v: i32) -> Result<(), Error> {
self.serialize_i64(v.into())
}
fn serialize_i64(self, v: i64) -> Result<(), Self::Error> {
self.write_integer(v.into())
}
fn serialize_u8(self, v: u8) -> Result<(), Error> {
self.serialize_u64(v.into())
}
fn serialize_u16(self, v: u16) -> Result<(), Error> {
self.serialize_u64(v.into())
}
fn serialize_u32(self, v: u32) -> Result<(), Error> {
self.serialize_u64(v.into())
}
fn serialize_u64(self, v: u64) -> Result<(), Self::Error> {
self.write_integer(v.into())
}
fn serialize_f32(self, v: f32) -> Result<(), Error> {
self.serialize_f64(v.into())
}
fn serialize_f64(self, v: f64) -> Result<(), Error> {
self.write_real(v)
}
fn serialize_char(self, v: char) -> Result<(), Self::Error> {
let mut buf = [0; 4];
let v = v.encode_utf8(&mut buf);
self.write_string(v)
}
fn serialize_str(self, v: &str) -> Result<(), Error> {
self.write_string(v)
}
fn serialize_bytes(self, v: &[u8]) -> Result<(), Error> {
self.write_data(v)
}
fn serialize_none(self) -> Result<(), Error> {
match self.option_mode {
OptionMode::Root | OptionMode::StructField(_) => (),
OptionMode::StructFieldNameWritten => unreachable!(),
OptionMode::Explicit => {
self.write_start_dictionary(Some(1))?;
self.write_string("None")?;
self.serialize_unit()?;
self.write_end_collection()?;
}
}
Ok(())
}
fn serialize_some<T: ?Sized + ser::Serialize>(self, value: &T) -> Result<(), Error> {
match self.option_mode {
OptionMode::Root => self.serialize_with_option_mode(OptionMode::Explicit, value)?,
OptionMode::StructField(field_name) => {
self.option_mode = OptionMode::StructFieldNameWritten;
self.write_string(field_name)?;
self.serialize_with_option_mode(OptionMode::Explicit, value)?;
}
OptionMode::StructFieldNameWritten => unreachable!(),
OptionMode::Explicit => {
self.write_start_dictionary(Some(1))?;
self.write_string("Some")?;
value.serialize(&mut *self)?;
self.write_end_collection()?;
}
}
Ok(())
}
fn serialize_unit(self) -> Result<(), Error> {
self.write_string("")
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<(), Error> {
self.serialize_unit()
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> Result<(), Error> {
// `plist` since v1.1 serialises unit enum variants as plain strings.
self.write_string(variant)
}
fn serialize_newtype_struct<T: ?Sized + ser::Serialize>(
self,
name: &'static str,
value: &T,
) -> Result<(), Error> {
match name {
DATE_NEWTYPE_STRUCT_NAME => value.serialize(DateSerializer { ser: &mut *self }),
UID_NEWTYPE_STRUCT_NAME => value.serialize(UidSerializer { ser: &mut *self }),
_ => value.serialize(self),
}
}
fn serialize_newtype_variant<T: ?Sized + ser::Serialize>(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<(), Error> {
self.write_start_dictionary(Some(1))?;
self.write_string(variant)?;
value.serialize(&mut *self)?;
self.write_end_collection()
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Error> {
let len = len.map(|len| len as u64);
self.write_start_array(len)?;
Ok(Compound { ser: self })
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Error> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_struct(
self,
_name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct, Error> {
self.serialize_tuple(len)
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, Error> {
self.write_start_dictionary(Some(1))?;
self.write_string(variant)?;
self.serialize_tuple(len)
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Error> {
let len = len.map(|len| len as u64);
self.write_start_dictionary(len)?;
Ok(Compound { ser: self })
}
fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeStruct, Error> {
// The number of struct fields is not known as fields with None values are ignored.
self.serialize_map(None)
}
fn serialize_struct_variant(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeStructVariant, Error> {
self.write_start_dictionary(Some(1))?;
self.write_string(variant)?;
self.serialize_struct(name, len)
}
}
struct DateSerializer<'a, W: 'a + Writer> {
ser: &'a mut Serializer<W>,
}
impl<'a, W: Writer> DateSerializer<'a, W> {
fn expecting_date_error(&self) -> Error {
ser::Error::custom("plist date string expected")
}
}
impl<'a, W: Writer> ser::Serializer for DateSerializer<'a, W> {
type Ok = ();
type Error = Error;
type SerializeSeq = ser::Impossible<(), Error>;
type SerializeTuple = ser::Impossible<(), Error>;
type SerializeTupleStruct = ser::Impossible<(), Error>;
type SerializeTupleVariant = ser::Impossible<(), Error>;
type SerializeMap = ser::Impossible<(), Error>;
type SerializeStruct = ser::Impossible<(), Error>;
type SerializeStructVariant = ser::Impossible<(), Error>;
fn serialize_bool(self, _: bool) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_i8(self, _: i8) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_i16(self, _: i16) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_i32(self, _: i32) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_i64(self, _: i64) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_u8(self, _: u8) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_u16(self, _: u16) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_u32(self, _: u32) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_u64(self, _: u64) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_f32(self, _: f32) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_f64(self, _: f64) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_char(self, _: char) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_str(self, v: &str) -> Result<(), Error> {
let date = Date::from_rfc3339(v).map_err(|()| self.expecting_date_error())?;
self.ser.write_date(date)
}
fn serialize_bytes(self, _: &[u8]) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_none(self) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_some<T: ?Sized + ser::Serialize>(self, _: &T) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_unit(self) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_unit_struct(self, _: &'static str) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_unit_variant(self, _: &'static str, _: u32, _: &'static str) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_newtype_struct<T: ?Sized + ser::Serialize>(
self,
_: &'static str,
_: &T,
) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_newtype_variant<T: ?Sized + ser::Serialize>(
self,
_: &'static str,
_: u32,
_: &'static str,
_: &T,
) -> Result<(), Error> {
Err(self.expecting_date_error())
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Error> {
Err(self.expecting_date_error())
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Error> {
Err(self.expecting_date_error())
}
fn serialize_tuple_struct(
self,
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleStruct, Error> {
Err(self.expecting_date_error())
}
fn serialize_tuple_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleVariant, Error> {
Err(self.expecting_date_error())
}
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Error> {
Err(self.expecting_date_error())
}
fn serialize_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeStruct, Error> {
Err(self.expecting_date_error())
}
fn serialize_struct_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<Self::SerializeStructVariant, Error> {
Err(self.expecting_date_error())
}
}
struct UidSerializer<'a, W: 'a + Writer> {
ser: &'a mut Serializer<W>,
}
impl<'a, W: Writer> UidSerializer<'a, W> {
fn expecting_uid_error(&self) -> Error {
ser::Error::custom("plist uid expected")
}
}
impl<'a, W: Writer> ser::Serializer for UidSerializer<'a, W> {
type Ok = ();
type Error = Error;
type SerializeSeq = ser::Impossible<(), Error>;
type SerializeTuple = ser::Impossible<(), Error>;
type SerializeTupleStruct = ser::Impossible<(), Error>;
type SerializeTupleVariant = ser::Impossible<(), Error>;
type SerializeMap = ser::Impossible<(), Error>;
type SerializeStruct = ser::Impossible<(), Error>;
type SerializeStructVariant = ser::Impossible<(), Error>;
fn serialize_bool(self, _: bool) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_i8(self, _: i8) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_i16(self, _: i16) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_i32(self, _: i32) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_i64(self, _: i64) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_u8(self, _: u8) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_u16(self, _: u16) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_u32(self, _: u32) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_u64(self, v: u64) -> Result<(), Error> {
self.ser.write_uid(Uid::new(v))
}
fn serialize_f32(self, _: f32) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_f64(self, _: f64) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_char(self, _: char) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_str(self, _: &str) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_bytes(self, _: &[u8]) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_none(self) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_some<T: ?Sized + ser::Serialize>(self, _: &T) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_unit(self) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_unit_struct(self, _: &'static str) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_unit_variant(self, _: &'static str, _: u32, _: &'static str) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_newtype_struct<T: ?Sized + ser::Serialize>(
self,
_: &'static str,
_: &T,
) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_newtype_variant<T: ?Sized + ser::Serialize>(
self,
_: &'static str,
_: u32,
_: &'static str,
_: &T,
) -> Result<(), Error> {
Err(self.expecting_uid_error())
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Error> {
Err(self.expecting_uid_error())
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Error> {
Err(self.expecting_uid_error())
}
fn serialize_tuple_struct(
self,
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleStruct, Error> {
Err(self.expecting_uid_error())
}
fn serialize_tuple_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleVariant, Error> {
Err(self.expecting_uid_error())
}
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Error> {
Err(self.expecting_uid_error())
}
fn serialize_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeStruct, Error> {
Err(self.expecting_uid_error())
}
fn serialize_struct_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<Self::SerializeStructVariant, Error> {
Err(self.expecting_uid_error())
}
}
#[doc(hidden)]
pub struct Compound<'a, W: 'a + Writer> {
ser: &'a mut Serializer<W>,
}
impl<'a, W: Writer> ser::SerializeSeq for Compound<'a, W> {
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized + ser::Serialize>(&mut self, value: &T) -> Result<(), Error> {
self.ser
.serialize_with_option_mode(OptionMode::Explicit, value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
self.ser.write_end_collection()
}
}
impl<'a, W: Writer> ser::SerializeTuple for Compound<'a, W> {
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized + ser::Serialize>(&mut self, value: &T) -> Result<(), Error> {
self.ser
.serialize_with_option_mode(OptionMode::Explicit, value)
}
fn end(self) -> Result<(), Error> {
self.ser.write_end_collection()
}
}
impl<'a, W: Writer> ser::SerializeTupleStruct for Compound<'a, W> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized + ser::Serialize>(&mut self, value: &T) -> Result<(), Error> {
self.ser
.serialize_with_option_mode(OptionMode::Explicit, value)
}
fn end(self) -> Result<(), Error> {
self.ser.write_end_collection()
}
}
impl<'a, W: Writer> ser::SerializeTupleVariant for Compound<'a, W> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized + ser::Serialize>(&mut self, value: &T) -> Result<(), Error> {
self.ser
.serialize_with_option_mode(OptionMode::Explicit, value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
self.ser.write_end_collection()?;
self.ser.write_end_collection()
}
}
impl<'a, W: Writer> ser::SerializeMap for Compound<'a, W> {
type Ok = ();
type Error = Error;
fn serialize_key<T: ?Sized + ser::Serialize>(&mut self, key: &T) -> Result<(), Error> {
self.ser
.serialize_with_option_mode(OptionMode::Explicit, key)
}
fn serialize_value<T: ?Sized + ser::Serialize>(&mut self, value: &T) -> Result<(), Error> {
self.ser
.serialize_with_option_mode(OptionMode::Explicit, value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
self.ser.write_end_collection()
}
}
impl<'a, W: Writer> ser::SerializeStruct for Compound<'a, W> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized + ser::Serialize>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Error> {
// We don't want to serialize None if the Option is a struct field as this is how null
// fields are represented in plists.
self.ser
.serialize_with_option_mode(OptionMode::StructField(key), value)
}
fn end(self) -> Result<(), Error> {
self.ser.write_end_collection()
}
}
impl<'a, W: Writer> ser::SerializeStructVariant for Compound<'a, W> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized + ser::Serialize>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Error> {
self.ser
.serialize_with_option_mode(OptionMode::StructField(key), value)
}
fn end(self) -> Result<(), Error> {
self.ser.write_end_collection()?;
self.ser.write_end_collection()
}
}
/// Serializes the given data structure to a file as a binary encoded plist.
pub fn to_file_binary<P: AsRef<Path>, T: ser::Serialize>(path: P, value: &T) -> Result<(), Error> {
let mut file = File::create(path).map_err(error::from_io_without_position)?;
to_writer_binary(BufWriter::new(&mut file), value)?;
file.sync_all().map_err(error::from_io_without_position)?;
Ok(())
}
/// Serializes the given data structure to a file as an XML encoded plist.
pub fn to_file_xml<P: AsRef<Path>, T: ser::Serialize>(path: P, value: &T) -> Result<(), Error> {
let mut file = File::create(path).map_err(error::from_io_without_position)?;
to_writer_xml(BufWriter::new(&mut file), value)?;
file.sync_all().map_err(error::from_io_without_position)?;
Ok(())
}
/// Serializes the given data structure to a byte stream as a binary encoded plist.
pub fn to_writer_binary<W: Write, T: ser::Serialize>(writer: W, value: &T) -> Result<(), Error> {
let writer = stream::BinaryWriter::new(writer);
let mut ser = Serializer::new(writer);
value.serialize(&mut ser)
}
/// Serializes the given data structure to a byte stream as an XML encoded plist.
pub fn to_writer_xml<W: Write, T: ser::Serialize>(writer: W, value: &T) -> Result<(), Error> {
to_writer_xml_with_options(writer, value, &XmlWriteOptions::default())
}
/// Serializes to a byte stream as an XML encoded plist, using custom [`XmlWriteOptions`].
pub fn to_writer_xml_with_options<W: Write, T: ser::Serialize>(
writer: W,
value: &T,
options: &XmlWriteOptions,
) -> Result<(), Error> {
let writer = stream::XmlWriter::new_with_options(writer, options);
let mut ser = Serializer::new(writer);
value.serialize(&mut ser)
}