use byteorder::WriteBytesExt;
use serde::{ser, ser::SerializeSeq, Serialize};
use static_assertions::assert_impl_all;
use std::{
io::{Seek, Write},
marker::PhantomData,
str,
};
#[cfg(unix)]
use std::os::unix::io::RawFd;
use crate::{
container_depths::ContainerDepths, signature_parser::SignatureParser, utils::*, Basic,
EncodingContext, EncodingFormat, Error, ObjectPath, Result, Signature,
};
#[cfg(unix)]
use crate::Fd;
pub struct Serializer<'ser, 'sig, B, W>(pub(crate) crate::SerializerCommon<'ser, 'sig, B, W>);
assert_impl_all!(Serializer<'_, '_, i32, i32>: Send, Sync, Unpin);
impl<'ser, 'sig, B, W> Serializer<'ser, 'sig, B, W>
where
B: byteorder::ByteOrder,
W: Write + Seek,
{
pub fn new<'w: 'ser, 'f: 'ser>(
signature: &Signature<'sig>,
writer: &'w mut W,
#[cfg(unix)] fds: &'f mut Vec<RawFd>,
ctxt: EncodingContext<B>,
) -> Self {
assert_eq!(ctxt.format(), EncodingFormat::DBus);
let sig_parser = SignatureParser::new(signature.clone());
Self(crate::SerializerCommon {
ctxt,
sig_parser,
writer,
#[cfg(unix)]
fds,
bytes_written: 0,
value_sign: None,
container_depths: Default::default(),
b: PhantomData,
})
}
}
macro_rules! serialize_basic {
($method:ident($type:ty) $write_method:ident) => {
serialize_basic!($method($type) $write_method($type));
};
($method:ident($type:ty) $write_method:ident($as:ty)) => {
fn $method(self, v: $type) -> Result<()> {
self.0.prep_serialize_basic::<$type>()?;
self.0.$write_method::<B>(v as $as).map_err(|e| Error::InputOutput(e.into()))
}
};
}
impl<'ser, 'sig, 'b, B, W> ser::Serializer for &'b mut Serializer<'ser, 'sig, B, W>
where
B: byteorder::ByteOrder,
W: Write + Seek,
{
type Ok = ();
type Error = Error;
type SerializeSeq = SeqSerializer<'ser, 'sig, 'b, B, W>;
type SerializeTuple = StructSeqSerializer<'ser, 'sig, 'b, B, W>;
type SerializeTupleStruct = StructSeqSerializer<'ser, 'sig, 'b, B, W>;
type SerializeTupleVariant = StructSeqSerializer<'ser, 'sig, 'b, B, W>;
type SerializeMap = SeqSerializer<'ser, 'sig, 'b, B, W>;
type SerializeStruct = StructSeqSerializer<'ser, 'sig, 'b, B, W>;
type SerializeStructVariant = StructSeqSerializer<'ser, 'sig, 'b, B, W>;
serialize_basic!(serialize_bool(bool) write_u32(u32));
serialize_basic!(serialize_i8(i8) write_i16(i16));
serialize_basic!(serialize_i16(i16) write_i16);
serialize_basic!(serialize_i64(i64) write_i64);
fn serialize_i32(self, v: i32) -> Result<()> {
match self.0.sig_parser.next_char()? {
#[cfg(unix)]
Fd::SIGNATURE_CHAR => {
self.0.sig_parser.skip_char()?;
self.0.add_padding(u32::alignment(EncodingFormat::DBus))?;
let v = self.0.add_fd(v);
self.0
.write_u32::<B>(v)
.map_err(|e| Error::InputOutput(e.into()))
}
_ => {
self.0.prep_serialize_basic::<i32>()?;
self.0
.write_i32::<B>(v)
.map_err(|e| Error::InputOutput(e.into()))
}
}
}
fn serialize_u8(self, v: u8) -> Result<()> {
self.0.prep_serialize_basic::<u8>()?;
self.0.write_u8(v).map_err(|e| Error::InputOutput(e.into()))
}
serialize_basic!(serialize_u16(u16) write_u16);
serialize_basic!(serialize_u32(u32) write_u32);
serialize_basic!(serialize_u64(u64) write_u64);
serialize_basic!(serialize_f32(f32) write_f64(f64));
serialize_basic!(serialize_f64(f64) write_f64);
fn serialize_char(self, v: char) -> Result<()> {
self.serialize_str(&v.to_string())
}
fn serialize_str(self, v: &str) -> Result<()> {
if v.contains('\0') {
return Err(serde::de::Error::invalid_value(
serde::de::Unexpected::Char('\0'),
&"D-Bus string type must not contain interior null bytes",
));
}
let c = self.0.sig_parser.next_char()?;
if c == VARIANT_SIGNATURE_CHAR {
self.0.value_sign = Some(signature_string!(v));
}
match c {
ObjectPath::SIGNATURE_CHAR | <&str>::SIGNATURE_CHAR => {
self.0
.add_padding(<&str>::alignment(EncodingFormat::DBus))?;
self.0
.write_u32::<B>(usize_to_u32(v.len()))
.map_err(|e| Error::InputOutput(e.into()))?;
}
Signature::SIGNATURE_CHAR | VARIANT_SIGNATURE_CHAR => {
self.0
.write_u8(usize_to_u8(v.len()))
.map_err(|e| Error::InputOutput(e.into()))?;
}
_ => {
let expected = format!(
"`{}`, `{}`, `{}` or `{}`",
<&str>::SIGNATURE_STR,
Signature::SIGNATURE_STR,
ObjectPath::SIGNATURE_STR,
VARIANT_SIGNATURE_CHAR,
);
return Err(serde::de::Error::invalid_type(
serde::de::Unexpected::Char(c),
&expected.as_str(),
));
}
}
self.0.sig_parser.skip_char()?;
self.0
.write_all(v.as_bytes())
.map_err(|e| Error::InputOutput(e.into()))?;
self.0
.write_all(&b"\0"[..])
.map_err(|e| Error::InputOutput(e.into()))?;
Ok(())
}
fn serialize_bytes(self, v: &[u8]) -> Result<()> {
let seq = self.serialize_seq(Some(v.len()))?;
seq.ser
.0
.write(v)
.map_err(|e| Error::InputOutput(e.into()))?;
seq.end()
}
fn serialize_none(self) -> Result<()> {
unreachable!("Option<T> can not be encoded in D-Bus format");
}
fn serialize_some<T>(self, _value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
unreachable!("Option<T> can not be encoded in D-Bus format");
}
fn serialize_unit(self) -> Result<()> {
Ok(())
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
self.serialize_unit()
}
fn serialize_unit_variant(
self,
_name: &'static str,
variant_index: u32,
variant: &'static str,
) -> Result<()> {
if self.0.sig_parser.next_char()? == <&str>::SIGNATURE_CHAR {
variant.serialize(self)
} else {
variant_index.serialize(self)
}
}
fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
value.serialize(self)?;
Ok(())
}
fn serialize_newtype_variant<T>(
self,
_name: &'static str,
variant_index: u32,
_variant: &'static str,
value: &T,
) -> Result<()>
where
T: ?Sized + Serialize,
{
self.0.prep_serialize_enum_variant(variant_index)?;
value.serialize(&mut *self)?;
self.0.sig_parser.skip_char()?;
Ok(())
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
self.0.sig_parser.skip_char()?;
self.0.add_padding(ARRAY_ALIGNMENT_DBUS)?;
self.0
.write_u32::<B>(0_u32)
.map_err(|e| Error::InputOutput(e.into()))?;
let element_signature = self.0.sig_parser.next_signature()?;
let element_signature_len = element_signature.len();
let element_alignment = alignment_for_signature(&element_signature, self.0.ctxt.format())?;
let first_padding = self.0.add_padding(element_alignment)?;
let start = self.0.bytes_written;
self.0.container_depths = self.0.container_depths.inc_array()?;
Ok(SeqSerializer {
ser: self,
start,
element_alignment,
element_signature_len,
first_padding,
})
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
self.serialize_struct("", len)
}
fn serialize_tuple_struct(
self,
name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct> {
self.serialize_struct(name, len)
}
fn serialize_tuple_variant(
self,
_name: &'static str,
variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant> {
self.0.prep_serialize_enum_variant(variant_index)?;
StructSerializer::enum_variant(self).map(StructSeqSerializer::Struct)
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
self.serialize_seq(len)
}
fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
if len == 0 {
return StructSerializer::unit(self).map(StructSeqSerializer::Struct);
}
match self.0.sig_parser.next_char()? {
VARIANT_SIGNATURE_CHAR => {
StructSerializer::variant(self).map(StructSeqSerializer::Struct)
}
ARRAY_SIGNATURE_CHAR => self.serialize_seq(Some(len)).map(StructSeqSerializer::Seq),
_ => StructSerializer::structure(self).map(StructSeqSerializer::Struct),
}
}
fn serialize_struct_variant(
self,
_name: &'static str,
variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant> {
self.0.prep_serialize_enum_variant(variant_index)?;
StructSerializer::enum_variant(self).map(StructSeqSerializer::Struct)
}
fn is_human_readable(&self) -> bool {
false
}
}
#[doc(hidden)]
pub struct SeqSerializer<'ser, 'sig, 'b, B, W> {
ser: &'b mut Serializer<'ser, 'sig, B, W>,
start: usize,
element_alignment: usize,
element_signature_len: usize,
first_padding: usize,
}
impl<'ser, 'sig, 'b, B, W> SeqSerializer<'ser, 'sig, 'b, B, W>
where
B: byteorder::ByteOrder,
W: Write + Seek,
{
pub(self) fn end_seq(self) -> Result<()> {
self.ser
.0
.sig_parser
.skip_chars(self.element_signature_len)?;
let array_len = self.ser.0.bytes_written - self.start;
let len = usize_to_u32(array_len);
let total_array_len = (array_len + self.first_padding + 4) as i64;
self.ser
.0
.writer
.seek(std::io::SeekFrom::Current(-total_array_len))
.map_err(|e| Error::InputOutput(e.into()))?;
self.ser
.0
.writer
.write_u32::<B>(len)
.map_err(|e| Error::InputOutput(e.into()))?;
self.ser
.0
.writer
.seek(std::io::SeekFrom::Current(total_array_len - 4))
.map_err(|e| Error::InputOutput(e.into()))?;
self.ser.0.container_depths = self.ser.0.container_depths.dec_array();
Ok(())
}
}
impl<'ser, 'sig, 'b, B, W> ser::SerializeSeq for SeqSerializer<'ser, 'sig, 'b, B, W>
where
B: byteorder::ByteOrder,
W: Write + Seek,
{
type Ok = ();
type Error = Error;
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
let sig_parser = self.ser.0.sig_parser.clone();
self.ser.0.sig_parser = sig_parser.clone();
value.serialize(&mut *self.ser)?;
self.ser.0.sig_parser = sig_parser;
Ok(())
}
fn end(self) -> Result<()> {
self.end_seq()
}
}
#[doc(hidden)]
pub struct StructSerializer<'ser, 'sig, 'b, B, W> {
ser: &'b mut Serializer<'ser, 'sig, B, W>,
end_parens: u8,
container_depths: ContainerDepths,
}
impl<'ser, 'sig, 'b, B, W> StructSerializer<'ser, 'sig, 'b, B, W>
where
B: byteorder::ByteOrder,
W: Write + Seek,
{
fn variant(ser: &'b mut Serializer<'ser, 'sig, B, W>) -> Result<Self> {
ser.0.add_padding(VARIANT_ALIGNMENT_DBUS)?;
let container_depths = ser.0.container_depths;
ser.0.container_depths = ser.0.container_depths.inc_variant()?;
Ok(Self {
ser,
end_parens: 0,
container_depths,
})
}
fn structure(ser: &'b mut Serializer<'ser, 'sig, B, W>) -> Result<Self> {
let c = ser.0.sig_parser.next_char()?;
if c != STRUCT_SIG_START_CHAR && c != DICT_ENTRY_SIG_START_CHAR {
let expected = format!("`{STRUCT_SIG_START_STR}` or `{DICT_ENTRY_SIG_START_STR}`",);
return Err(serde::de::Error::invalid_type(
serde::de::Unexpected::Char(c),
&expected.as_str(),
));
}
let signature = ser.0.sig_parser.next_signature()?;
let alignment = alignment_for_signature(&signature, EncodingFormat::DBus)?;
ser.0.add_padding(alignment)?;
ser.0.sig_parser.skip_char()?;
let container_depths = ser.0.container_depths;
ser.0.container_depths = ser.0.container_depths.inc_structure()?;
Ok(Self {
ser,
end_parens: 1,
container_depths,
})
}
fn unit(ser: &'b mut Serializer<'ser, 'sig, B, W>) -> Result<Self> {
serde::Serializer::serialize_u8(&mut *ser, 0)?;
let container_depths = ser.0.container_depths;
Ok(Self {
ser,
end_parens: 0,
container_depths,
})
}
fn enum_variant(ser: &'b mut Serializer<'ser, 'sig, B, W>) -> Result<Self> {
let mut ser = Self::structure(ser)?;
ser.end_parens += 1;
Ok(ser)
}
fn serialize_struct_element<T>(&mut self, name: Option<&'static str>, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
match name {
Some("zvariant::Value::Value") => {
let signature = self
.ser
.0
.value_sign
.take()
.expect("Incorrect Value encoding");
let sig_parser = SignatureParser::new(signature);
let bytes_written = self.ser.0.bytes_written;
let mut ser = Serializer(crate::SerializerCommon::<B, W> {
ctxt: self.ser.0.ctxt,
sig_parser,
writer: self.ser.0.writer,
#[cfg(unix)]
fds: self.ser.0.fds,
bytes_written,
value_sign: None,
container_depths: self.ser.0.container_depths,
b: PhantomData,
});
value.serialize(&mut ser)?;
self.ser.0.bytes_written = ser.0.bytes_written;
Ok(())
}
_ => value.serialize(&mut *self.ser),
}
}
fn end_struct(self) -> Result<()> {
if self.end_parens > 0 {
self.ser.0.sig_parser.skip_chars(self.end_parens as usize)?;
}
self.ser.0.container_depths = self.container_depths;
Ok(())
}
}
#[doc(hidden)]
pub enum StructSeqSerializer<'ser, 'sig, 'b, B, W> {
Struct(StructSerializer<'ser, 'sig, 'b, B, W>),
Seq(SeqSerializer<'ser, 'sig, 'b, B, W>),
}
macro_rules! serialize_struct_anon_fields {
($trait:ident $method:ident) => {
impl<'ser, 'sig, 'b, B, W> ser::$trait for StructSerializer<'ser, 'sig, 'b, B, W>
where
B: byteorder::ByteOrder,
W: Write + Seek,
{
type Ok = ();
type Error = Error;
fn $method<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
self.serialize_struct_element(None, value)
}
fn end(self) -> Result<()> {
self.end_struct()
}
}
impl<'ser, 'sig, 'b, B, W> ser::$trait for StructSeqSerializer<'ser, 'sig, 'b, B, W>
where
B: byteorder::ByteOrder,
W: Write + Seek,
{
type Ok = ();
type Error = Error;
fn $method<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
match self {
StructSeqSerializer::Struct(ser) => ser.$method(value),
StructSeqSerializer::Seq(ser) => ser.serialize_element(value),
}
}
fn end(self) -> Result<()> {
match self {
StructSeqSerializer::Struct(ser) => ser.end_struct(),
StructSeqSerializer::Seq(ser) => ser.end_seq(),
}
}
}
};
}
serialize_struct_anon_fields!(SerializeTuple serialize_element);
serialize_struct_anon_fields!(SerializeTupleStruct serialize_field);
serialize_struct_anon_fields!(SerializeTupleVariant serialize_field);
impl<'ser, 'sig, 'b, B, W> ser::SerializeMap for SeqSerializer<'ser, 'sig, 'b, B, W>
where
B: byteorder::ByteOrder,
W: Write + Seek,
{
type Ok = ();
type Error = Error;
fn serialize_key<T>(&mut self, key: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
self.ser.0.add_padding(self.element_alignment)?;
let sig_parser = self.ser.0.sig_parser.clone();
self.ser.0.sig_parser = sig_parser.clone();
self.ser.0.sig_parser.skip_char()?;
key.serialize(&mut *self.ser)?;
self.ser.0.sig_parser = sig_parser;
Ok(())
}
fn serialize_value<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
let sig_parser = self.ser.0.sig_parser.clone();
self.ser.0.sig_parser = sig_parser.clone();
self.ser.0.sig_parser.skip_chars(2)?;
value.serialize(&mut *self.ser)?;
self.ser.0.sig_parser = sig_parser;
Ok(())
}
fn end(self) -> Result<()> {
self.end_seq()
}
}
macro_rules! serialize_struct_named_fields {
($trait:ident) => {
impl<'ser, 'sig, 'b, B, W> ser::$trait for StructSerializer<'ser, 'sig, 'b, B, W>
where
B: byteorder::ByteOrder,
W: Write + Seek,
{
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
self.serialize_struct_element(Some(key), value)
}
fn end(self) -> Result<()> {
self.end_struct()
}
}
impl<'ser, 'sig, 'b, B, W> ser::$trait for StructSeqSerializer<'ser, 'sig, 'b, B, W>
where
B: byteorder::ByteOrder,
W: Write + Seek,
{
type Ok = ();
type Error = Error;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
match self {
StructSeqSerializer::Struct(ser) => ser.serialize_field(key, value),
StructSeqSerializer::Seq(ser) => ser.serialize_element(value),
}
}
fn end(self) -> Result<()> {
match self {
StructSeqSerializer::Struct(ser) => ser.end_struct(),
StructSeqSerializer::Seq(ser) => ser.end_seq(),
}
}
}
};
}
serialize_struct_named_fields!(SerializeStruct);
serialize_struct_named_fields!(SerializeStructVariant);