1
0
Fork 0
forked from wry/wry
wry/src/dbus/formatter.rs
2022-04-07 17:31:31 +02:00

111 lines
3.6 KiB
Rust

use {
crate::dbus::{types::Variant, DbusType, Formatter},
std::rc::Rc,
uapi::{OwnedFd, Packed},
};
impl<'a> Formatter<'a> {
pub fn new(fds: &'a mut Vec<Rc<OwnedFd>>, buf: &'a mut Vec<u8>) -> Self {
Self { fds, buf }
}
pub fn marshal<'b, T: DbusType<'b>>(&mut self, t: &T) {
t.marshal(self)
}
pub fn pad_to(&mut self, alignment: usize) {
static BUF: [u8; 8] = [0; 8];
let len = self.buf.len().wrapping_neg() & (alignment - 1);
self.buf.extend_from_slice(&BUF[..len]);
}
pub fn len(&self) -> usize {
self.buf.len()
}
pub fn write_packed<'b, T: DbusType<'b> + Packed>(&mut self, t: &T) {
self.pad_to(T::ALIGNMENT);
self.buf.extend_from_slice(uapi::as_bytes(t));
}
pub fn write_str(&mut self, s: &str) {
self.write_packed(&(s.len() as u32));
self.buf.extend_from_slice(s.as_bytes());
self.buf.push(0);
}
pub fn write_signature(&mut self, s: &[u8]) {
self.write_packed(&(s.len() as u8));
self.buf.extend_from_slice(s);
self.buf.push(0);
}
pub fn write_array<'b, T: DbusType<'b>>(&mut self, a: &[T]) {
self.pad_to(4);
let len_pos = self.buf.len();
self.write_packed(&0u32);
self.pad_to(T::ALIGNMENT);
let start = self.buf.len();
for v in a {
v.marshal(self);
}
let len = (self.buf.len() - start) as u32;
self.buf[len_pos..len_pos + 4].copy_from_slice(uapi::as_bytes(&len));
}
pub fn write_fd(&mut self, fd: &Rc<OwnedFd>) {
self.write_packed(&(self.fds.len() as u32));
self.fds.push(fd.clone());
}
pub fn write_variant(&mut self, variant: &Variant) {
let pos = self.buf.len();
self.buf.push(0);
variant.write_signature(self.buf);
self.buf.push(0);
self.buf[pos] = (self.buf.len() - pos - 2) as u8;
self.write_variant_body(variant);
}
pub fn write_variant_body(&mut self, variant: &Variant) {
match variant {
Variant::U8(v) => v.marshal(self),
Variant::Bool(v) => v.marshal(self),
Variant::I16(v) => v.marshal(self),
Variant::U16(v) => v.marshal(self),
Variant::I32(v) => v.marshal(self),
Variant::U32(v) => v.marshal(self),
Variant::I64(v) => v.marshal(self),
Variant::U64(v) => v.marshal(self),
Variant::F64(v) => v.marshal(self),
Variant::String(v) => v.marshal(self),
Variant::ObjectPath(v) => v.marshal(self),
Variant::Signature(v) => v.marshal(self),
Variant::Variant(v) => v.marshal(self),
Variant::Fd(f) => f.marshal(self),
Variant::Array(el, v) => {
self.pad_to(4);
let len_pos = self.buf.len();
self.write_packed(&0u32);
self.pad_to(el.alignment());
let start = self.buf.len();
for v in v {
self.write_variant_body(v);
}
let len = (self.buf.len() - start) as u32;
self.buf[len_pos..len_pos + 4].copy_from_slice(uapi::as_bytes(&len));
}
Variant::DictEntry(k, v) => {
self.pad_to(8);
self.write_variant_body(k);
self.write_variant_body(v);
}
Variant::Struct(f) => {
self.pad_to(8);
for v in f {
self.write_variant_body(v);
}
}
}
}
}