dbus: move protocol core into workspace crate
This commit is contained in:
parent
9e428510ca
commit
61ec13def0
11 changed files with 286 additions and 258 deletions
229
src/dbus.rs
229
src/dbus.rs
|
|
@ -1,16 +1,13 @@
|
|||
pub use types::*;
|
||||
pub use jay_dbus_core::*;
|
||||
use {
|
||||
crate::{
|
||||
async_engine::{AsyncEngine, SpawnedFuture},
|
||||
dbus::{property::GetReply, types::{ObjectPath, Signature, Variant}},
|
||||
io_uring::{IoUring, IoUringError},
|
||||
io_uring::IoUring,
|
||||
utils::{
|
||||
buf::DynamicBuf,
|
||||
bufio::{BufIo, BufIoError},
|
||||
bufio::BufIo,
|
||||
clonecell::CloneCell,
|
||||
copyhashmap::CopyHashMap,
|
||||
numcell::NumCell,
|
||||
oserror::OsError,
|
||||
run_toplevel::RunToplevel,
|
||||
stack::Stack,
|
||||
vecstorage::VecStorage,
|
||||
|
|
@ -21,7 +18,7 @@ use {
|
|||
std::{
|
||||
borrow::Cow,
|
||||
cell::{Cell, RefCell},
|
||||
fmt::{Debug, Display},
|
||||
fmt::Debug,
|
||||
future::Future,
|
||||
marker::PhantomData,
|
||||
mem,
|
||||
|
|
@ -29,109 +26,14 @@ use {
|
|||
rc::Rc,
|
||||
task::{Context, Poll, Waker},
|
||||
},
|
||||
thiserror::Error,
|
||||
uapi::OwnedFd,
|
||||
};
|
||||
|
||||
mod auth;
|
||||
mod dynamic_type;
|
||||
mod formatter;
|
||||
mod holder;
|
||||
mod incoming;
|
||||
mod outgoing;
|
||||
mod parser;
|
||||
mod property;
|
||||
mod socket;
|
||||
mod types;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CallError {
|
||||
pub name: String,
|
||||
pub msg: Option<String>,
|
||||
}
|
||||
|
||||
impl Display for CallError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if let Some(msg) = &self.msg {
|
||||
write!(f, "{}: {}", self.name, msg)
|
||||
} else {
|
||||
write!(f, "{}", self.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DbusError {
|
||||
#[error("Encountered an unknown type in a signature")]
|
||||
UnknownType,
|
||||
#[error("Function call reply does not contain a reply serial")]
|
||||
NoReplySerial,
|
||||
#[error("Signal message contains no interface or member or path")]
|
||||
MissingSignalHeaders,
|
||||
#[error("Method call message contains no interface or member or path")]
|
||||
MissingMethodCallHeaders,
|
||||
#[error("Error has no error name")]
|
||||
NoErrorName,
|
||||
#[error("The socket was killed")]
|
||||
Killed,
|
||||
#[error("{0}")]
|
||||
CallError(CallError),
|
||||
#[error("FD index is out of bounds")]
|
||||
OobFds,
|
||||
#[error("Variant has an invalid type")]
|
||||
InvalidVariantType,
|
||||
#[error("Could not create a socket")]
|
||||
Socket(#[source] OsError),
|
||||
#[error("Could not connect")]
|
||||
Connect(#[source] IoUringError),
|
||||
#[error("Could not write to the dbus socket")]
|
||||
WriteError(#[source] IoUringError),
|
||||
#[error("Could not read from the dbus socket")]
|
||||
ReadError(#[source] IoUringError),
|
||||
#[error("timeout")]
|
||||
IoUringError(#[source] Box<IoUringError>),
|
||||
#[error("Server did not send auth challenge")]
|
||||
NoChallenge,
|
||||
#[error("Server did not accept our authentication")]
|
||||
Auth,
|
||||
#[error("Array length is not a multiple of the element size")]
|
||||
PodArrayLength,
|
||||
#[error("Peer did not send enough fds")]
|
||||
TooFewFds,
|
||||
#[error("Variant signature is not a single type")]
|
||||
TrailingVariantSignature,
|
||||
#[error("Dict signature does not contain a terminating '}}'")]
|
||||
UnterminatedDict,
|
||||
#[error("Struct signature does not contain a terminating '}}'")]
|
||||
UnterminatedStruct,
|
||||
#[error("Dict signature contains trailing types")]
|
||||
DictTrailing,
|
||||
#[error("String does not contain valid UTF-8")]
|
||||
InvalidUtf8,
|
||||
#[error("Unexpected end of message")]
|
||||
UnexpectedEof,
|
||||
#[error("Boolean value was not 0 or 1")]
|
||||
InvalidBoolValue,
|
||||
#[error("Signature is empty")]
|
||||
EmptySignature,
|
||||
#[error("The session bus address is not set")]
|
||||
SessionBusAddressNotSet,
|
||||
#[error("Server does not support FD passing")]
|
||||
UnixFd,
|
||||
#[error("Server message has a different endianess than ourselves")]
|
||||
InvalidEndianess,
|
||||
#[error("Server speaks an unexpected protocol version")]
|
||||
InvalidProtocol,
|
||||
#[error("Signature contains an invalid type")]
|
||||
InvalidSignatureType,
|
||||
#[error("The signal already has a handler")]
|
||||
AlreadyHandled,
|
||||
#[error(transparent)]
|
||||
BufIoError(#[from] BufIoError),
|
||||
#[error(transparent)]
|
||||
DbusError(Rc<DbusError>),
|
||||
}
|
||||
efrom!(DbusError, IoUringError);
|
||||
|
||||
const DBUS_SESSION_BUS_ADDRESS: &str = "DBUS_SESSION_BUS_ADDRESS";
|
||||
|
||||
|
|
@ -274,22 +176,6 @@ pub struct DbusSocket {
|
|||
signal_handlers: RefCell<AHashMap<(&'static str, &'static str), InterfaceSignalHandlers>>,
|
||||
}
|
||||
|
||||
const TY_BYTE: u8 = b'y';
|
||||
const TY_BOOLEAN: u8 = b'b';
|
||||
const TY_INT16: u8 = b'n';
|
||||
const TY_UINT16: u8 = b'q';
|
||||
const TY_INT32: u8 = b'i';
|
||||
const TY_UINT32: u8 = b'u';
|
||||
const TY_INT64: u8 = b'x';
|
||||
const TY_UINT64: u8 = b't';
|
||||
const TY_DOUBLE: u8 = b'd';
|
||||
const TY_STRING: u8 = b's';
|
||||
const TY_OBJECT_PATH: u8 = b'o';
|
||||
const TY_SIGNATURE: u8 = b'g';
|
||||
const TY_ARRAY: u8 = b'a';
|
||||
const TY_VARIANT: u8 = b'v';
|
||||
const TY_UNIX_FD: u8 = b'h';
|
||||
|
||||
const HDR_PATH: u8 = 1;
|
||||
const HDR_INTERFACE: u8 = 2;
|
||||
const HDR_MEMBER: u8 = 3;
|
||||
|
|
@ -357,102 +243,6 @@ impl Drop for DbusHolder {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum DynamicType {
|
||||
U8,
|
||||
Bool,
|
||||
I16,
|
||||
U16,
|
||||
I32,
|
||||
U32,
|
||||
I64,
|
||||
U64,
|
||||
F64,
|
||||
String,
|
||||
ObjectPath,
|
||||
Signature,
|
||||
Variant,
|
||||
Fd,
|
||||
Array(Box<DynamicType>),
|
||||
DictEntry(Box<DynamicType>, Box<DynamicType>),
|
||||
Struct(Vec<DynamicType>),
|
||||
}
|
||||
|
||||
pub struct Parser<'a> {
|
||||
buf: &'a [u8],
|
||||
pos: usize,
|
||||
fds: &'a [Rc<OwnedFd>],
|
||||
}
|
||||
|
||||
pub struct Formatter<'a> {
|
||||
fds: &'a mut Vec<Rc<OwnedFd>>,
|
||||
buf: &'a mut DynamicBuf,
|
||||
}
|
||||
|
||||
pub unsafe trait Message<'a>: Sized + 'a {
|
||||
const SIGNATURE: &'static str;
|
||||
const INTERFACE: &'static str;
|
||||
const MEMBER: &'static str;
|
||||
type Generic<'b>: Message<'b>;
|
||||
|
||||
fn marshal(&self, w: &mut Formatter);
|
||||
fn unmarshal(p: &mut Parser<'a>) -> Result<Self, DbusError>;
|
||||
fn num_fds(&self) -> u32;
|
||||
}
|
||||
|
||||
pub struct ErrorMessage<'a> {
|
||||
pub msg: Cow<'a, str>,
|
||||
}
|
||||
|
||||
unsafe impl<'a> Message<'a> for ErrorMessage<'a> {
|
||||
const SIGNATURE: &'static str = "s";
|
||||
const INTERFACE: &'static str = "";
|
||||
const MEMBER: &'static str = "";
|
||||
type Generic<'b> = ErrorMessage<'b>;
|
||||
|
||||
fn marshal(&self, w: &mut Formatter) {
|
||||
self.msg.marshal(w)
|
||||
}
|
||||
|
||||
fn unmarshal(p: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
Ok(Self {
|
||||
msg: p.unmarshal()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn num_fds(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Property {
|
||||
const INTERFACE: &'static str;
|
||||
const PROPERTY: &'static str;
|
||||
type Type: DbusType<'static>;
|
||||
}
|
||||
|
||||
pub trait Signal<'a>: Message<'a> {}
|
||||
|
||||
pub trait MethodCall<'a>: Message<'a> {
|
||||
type Reply: Message<'static>;
|
||||
}
|
||||
|
||||
pub unsafe trait DbusType<'a>: Clone + 'a {
|
||||
const ALIGNMENT: usize;
|
||||
const IS_POD: bool;
|
||||
type Generic<'b>: DbusType<'b> + 'b;
|
||||
|
||||
fn consume_signature(s: &mut &[u8]) -> Result<(), DbusError>;
|
||||
#[allow(clippy::allow_attributes, dead_code)]
|
||||
fn write_signature(w: &mut Vec<u8>);
|
||||
fn marshal(&self, fmt: &mut Formatter);
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError>;
|
||||
|
||||
fn num_fds(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Reply<T: Message<'static>> {
|
||||
socket: Rc<DbusSocket>,
|
||||
buf: Vec<u8>,
|
||||
|
|
@ -609,14 +399,3 @@ struct InterfaceSignalHandlers {
|
|||
unconditional: Option<Rc<dyn SignalHandlerApi>>,
|
||||
conditional: AHashMap<String, Rc<dyn SignalHandlerApi>>,
|
||||
}
|
||||
|
||||
pub mod prelude {
|
||||
pub use {
|
||||
super::{
|
||||
DbusError, DbusType, Formatter, Message, MethodCall, Parser, Property, Signal,
|
||||
types::{Bool, DictEntry, ObjectPath, Variant},
|
||||
},
|
||||
std::{borrow::Cow, rc::Rc},
|
||||
uapi::OwnedFd,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,186 +0,0 @@
|
|||
use {
|
||||
super::{
|
||||
TY_ARRAY, TY_BOOLEAN, TY_BYTE, TY_DOUBLE, TY_INT16, TY_INT32, TY_INT64, TY_OBJECT_PATH,
|
||||
TY_SIGNATURE, TY_STRING, TY_UINT16, TY_UINT32, TY_UINT64, TY_UNIX_FD, TY_VARIANT,
|
||||
},
|
||||
crate::{
|
||||
dbus::{DbusError, DynamicType, Parser, types::Variant},
|
||||
utils::buf::DynamicBuf,
|
||||
},
|
||||
std::ops::Deref,
|
||||
};
|
||||
|
||||
impl DynamicType {
|
||||
pub fn from_signature<'a>(mut s: &'a [u8]) -> Result<(DynamicType, &'a [u8]), DbusError> {
|
||||
if s.is_empty() {
|
||||
return Err(DbusError::EmptySignature);
|
||||
}
|
||||
let first = s[0];
|
||||
s = &s[1..];
|
||||
let dp = match first {
|
||||
TY_BYTE => DynamicType::U8,
|
||||
TY_BOOLEAN => DynamicType::Bool,
|
||||
TY_INT16 => DynamicType::I16,
|
||||
TY_UINT16 => DynamicType::U16,
|
||||
TY_INT32 => DynamicType::I32,
|
||||
TY_UINT32 => DynamicType::U32,
|
||||
TY_INT64 => DynamicType::I64,
|
||||
TY_UINT64 => DynamicType::U64,
|
||||
TY_DOUBLE => DynamicType::F64,
|
||||
TY_STRING => DynamicType::String,
|
||||
TY_OBJECT_PATH => DynamicType::ObjectPath,
|
||||
TY_SIGNATURE => DynamicType::Signature,
|
||||
TY_VARIANT => DynamicType::Variant,
|
||||
TY_UNIX_FD => DynamicType::Fd,
|
||||
TY_ARRAY => {
|
||||
let (elty, rem) = Self::from_signature(s)?;
|
||||
s = rem;
|
||||
DynamicType::Array(Box::new(elty))
|
||||
}
|
||||
b'{' => {
|
||||
let (keyty, rem) = Self::from_signature(s)?;
|
||||
let (valty, rem) = Self::from_signature(rem)?;
|
||||
if rem.is_empty() {
|
||||
return Err(DbusError::UnterminatedDict);
|
||||
}
|
||||
if rem[0] != b'}' {
|
||||
return Err(DbusError::DictTrailing);
|
||||
}
|
||||
s = &rem[1..];
|
||||
DynamicType::DictEntry(Box::new(keyty), Box::new(valty))
|
||||
}
|
||||
b'(' => {
|
||||
let mut fields = vec![];
|
||||
loop {
|
||||
if s.is_empty() {
|
||||
return Err(DbusError::UnterminatedStruct);
|
||||
}
|
||||
if s[0] == b')' {
|
||||
s = &s[1..];
|
||||
break DynamicType::Struct(fields);
|
||||
}
|
||||
let (fieldty, rem) = Self::from_signature(s)?;
|
||||
s = rem;
|
||||
fields.push(fieldty);
|
||||
}
|
||||
}
|
||||
_ => return Err(DbusError::UnknownType),
|
||||
};
|
||||
Ok((dp, s))
|
||||
}
|
||||
|
||||
pub fn alignment(&self) -> usize {
|
||||
match self {
|
||||
DynamicType::U8 => 1,
|
||||
DynamicType::Bool => 4,
|
||||
DynamicType::I16 => 2,
|
||||
DynamicType::U16 => 2,
|
||||
DynamicType::I32 => 4,
|
||||
DynamicType::U32 => 4,
|
||||
DynamicType::I64 => 8,
|
||||
DynamicType::U64 => 8,
|
||||
DynamicType::F64 => 8,
|
||||
DynamicType::String => 4,
|
||||
DynamicType::ObjectPath => 4,
|
||||
DynamicType::Signature => 1,
|
||||
DynamicType::Variant => 1,
|
||||
DynamicType::Array(_) => 4,
|
||||
DynamicType::DictEntry(_, _) => 8,
|
||||
DynamicType::Struct(_) => 8,
|
||||
DynamicType::Fd => 4,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_signature(&self, w: &mut DynamicBuf) {
|
||||
let c = match self {
|
||||
DynamicType::U8 => TY_BYTE,
|
||||
DynamicType::Bool => TY_BOOLEAN,
|
||||
DynamicType::I16 => TY_INT16,
|
||||
DynamicType::U16 => TY_UINT16,
|
||||
DynamicType::I32 => TY_INT32,
|
||||
DynamicType::U32 => TY_UINT32,
|
||||
DynamicType::I64 => TY_INT64,
|
||||
DynamicType::U64 => TY_UINT64,
|
||||
DynamicType::F64 => TY_DOUBLE,
|
||||
DynamicType::String => TY_STRING,
|
||||
DynamicType::ObjectPath => TY_OBJECT_PATH,
|
||||
DynamicType::Signature => TY_SIGNATURE,
|
||||
DynamicType::Variant => TY_VARIANT,
|
||||
DynamicType::Fd => TY_UNIX_FD,
|
||||
DynamicType::Array(el) => {
|
||||
w.push(TY_ARRAY);
|
||||
el.write_signature(w);
|
||||
return;
|
||||
}
|
||||
DynamicType::DictEntry(k, v) => {
|
||||
w.push(b'{');
|
||||
k.write_signature(w);
|
||||
v.write_signature(w);
|
||||
w.push(b'}');
|
||||
return;
|
||||
}
|
||||
DynamicType::Struct(f) => {
|
||||
w.push(b'(');
|
||||
for f in f {
|
||||
f.write_signature(w);
|
||||
}
|
||||
w.push(b')');
|
||||
return;
|
||||
}
|
||||
};
|
||||
w.push(c);
|
||||
}
|
||||
|
||||
pub fn parse<'a>(&self, parser: &mut Parser<'a>) -> Result<Variant<'a>, DbusError> {
|
||||
let var = match self {
|
||||
DynamicType::U8 => Variant::U8(parser.read_pod()?),
|
||||
DynamicType::Bool => Variant::Bool(parser.read_bool()?),
|
||||
DynamicType::I16 => Variant::I16(parser.read_pod()?),
|
||||
DynamicType::U16 => Variant::U16(parser.read_pod()?),
|
||||
DynamicType::I32 => Variant::I32(parser.read_pod()?),
|
||||
DynamicType::U32 => Variant::U32(parser.read_pod()?),
|
||||
DynamicType::I64 => Variant::I64(parser.read_pod()?),
|
||||
DynamicType::U64 => Variant::U64(parser.read_pod()?),
|
||||
DynamicType::F64 => Variant::F64(f64::from_bits(parser.read_pod()?)),
|
||||
DynamicType::String => Variant::String(parser.read_string()?),
|
||||
DynamicType::ObjectPath => Variant::ObjectPath(parser.read_object_path()?),
|
||||
DynamicType::Signature => Variant::Signature(parser.read_signature()?),
|
||||
DynamicType::Variant => Variant::Variant(Box::new(parser.read_variant()?)),
|
||||
DynamicType::Fd => Variant::Fd(parser.read_fd()?),
|
||||
DynamicType::Array(el) => {
|
||||
let len: u32 = parser.read_pod()?;
|
||||
parser.align_to(el.alignment())?;
|
||||
let len = len as usize;
|
||||
if parser.buf.len() - parser.pos < len {
|
||||
return Err(DbusError::UnexpectedEof);
|
||||
}
|
||||
let mut vals = vec![];
|
||||
{
|
||||
let mut parser = Parser {
|
||||
buf: &parser.buf[..parser.pos + len],
|
||||
pos: parser.pos,
|
||||
fds: parser.fds,
|
||||
};
|
||||
while !parser.eof() {
|
||||
vals.push(el.parse(&mut parser)?);
|
||||
}
|
||||
}
|
||||
parser.pos += len;
|
||||
Variant::Array(el.deref().clone(), vals)
|
||||
}
|
||||
DynamicType::DictEntry(k, v) => {
|
||||
parser.align_to(8)?;
|
||||
Variant::DictEntry(Box::new(k.parse(parser)?), Box::new(v.parse(parser)?))
|
||||
}
|
||||
DynamicType::Struct(fields) => {
|
||||
let mut vals = vec![];
|
||||
parser.align_to(8)?;
|
||||
for field in fields {
|
||||
vals.push(field.parse(parser)?);
|
||||
}
|
||||
Variant::Struct(vals)
|
||||
}
|
||||
};
|
||||
Ok(var)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
use {
|
||||
crate::{
|
||||
dbus::{DbusType, Formatter, types::Variant},
|
||||
utils::buf::DynamicBuf,
|
||||
},
|
||||
std::rc::Rc,
|
||||
uapi::{OwnedFd, Packed},
|
||||
};
|
||||
|
||||
impl<'a> Formatter<'a> {
|
||||
pub fn new(fds: &'a mut Vec<Rc<OwnedFd>>, buf: &'a mut DynamicBuf) -> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -83,11 +83,8 @@ impl Incoming {
|
|||
return Err(DbusError::TooFewFds);
|
||||
}
|
||||
let fds: Vec<_> = self.incoming.fds.drain(..unix_fds).collect();
|
||||
let mut parser = Parser {
|
||||
buf: msg_buf,
|
||||
pos: FIXED_HEADER_SIZE + dyn_header_len as usize,
|
||||
fds: &fds,
|
||||
};
|
||||
let mut parser =
|
||||
Parser::new_at(msg_buf, FIXED_HEADER_SIZE + dyn_header_len as usize, &fds);
|
||||
match msg_ty {
|
||||
MSG_METHOD_CALL => {
|
||||
let sender = match &headers.sender {
|
||||
|
|
|
|||
|
|
@ -1,143 +0,0 @@
|
|||
use {
|
||||
crate::dbus::{
|
||||
DbusError, DbusType, DynamicType, Parser,
|
||||
types::{Bool, FALSE, ObjectPath, Signature, TRUE, Variant},
|
||||
},
|
||||
bstr::ByteSlice,
|
||||
std::{borrow::Cow, rc::Rc},
|
||||
uapi::{OwnedFd, Pod},
|
||||
};
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
pub fn new(buf: &'a [u8], fds: &'a [Rc<OwnedFd>]) -> Self {
|
||||
Self { buf, pos: 0, fds }
|
||||
}
|
||||
|
||||
pub fn eof(&self) -> bool {
|
||||
self.pos == self.buf.len()
|
||||
}
|
||||
|
||||
pub fn unmarshal<T: DbusType<'a>>(&mut self) -> Result<T, DbusError> {
|
||||
T::unmarshal(self)
|
||||
}
|
||||
|
||||
pub fn align_to(&mut self, n: usize) -> Result<(), DbusError> {
|
||||
let new = self.pos + (self.pos.wrapping_neg() & (n - 1));
|
||||
if new > self.buf.len() {
|
||||
return Err(DbusError::UnexpectedEof);
|
||||
}
|
||||
self.pos = new;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_fd(&mut self) -> Result<Rc<OwnedFd>, DbusError> {
|
||||
let idx: u32 = self.read_pod()?;
|
||||
let idx = idx as usize;
|
||||
if idx >= self.fds.len() {
|
||||
return Err(DbusError::OobFds);
|
||||
}
|
||||
Ok(self.fds[idx].clone())
|
||||
}
|
||||
|
||||
pub fn read_pod<'b, T: DbusType<'b> + Pod>(&mut self) -> Result<T, DbusError> {
|
||||
self.align_to(T::ALIGNMENT)?;
|
||||
match uapi::pod_read_init(&self.buf[self.pos..]) {
|
||||
Ok(v) => {
|
||||
self.pos += size_of::<T>();
|
||||
Ok(v)
|
||||
}
|
||||
_ => Err(DbusError::UnexpectedEof),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_bool(&mut self) -> Result<Bool, DbusError> {
|
||||
let v: u32 = self.read_pod()?;
|
||||
match v {
|
||||
0 => Ok(FALSE),
|
||||
1 => Ok(TRUE),
|
||||
_ => Err(DbusError::InvalidBoolValue),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_object_path(&mut self) -> Result<ObjectPath<'a>, DbusError> {
|
||||
self.read_string().map(ObjectPath)
|
||||
}
|
||||
|
||||
pub fn read_string(&mut self) -> Result<Cow<'a, str>, DbusError> {
|
||||
let len: u32 = self.read_pod()?;
|
||||
let s = self.read_string_(len as usize)?;
|
||||
Ok(Cow::Borrowed(s))
|
||||
}
|
||||
|
||||
pub fn read_signature(&mut self) -> Result<Signature<'a>, DbusError> {
|
||||
let len: u8 = self.read_pod()?;
|
||||
let s = self.read_string_(len as usize)?;
|
||||
Ok(Signature(Cow::Borrowed(s)))
|
||||
}
|
||||
|
||||
fn read_string_(&mut self, len: usize) -> Result<&'a str, DbusError> {
|
||||
if len == usize::MAX || self.buf.len() - self.pos < len + 1 {
|
||||
return Err(DbusError::UnexpectedEof);
|
||||
}
|
||||
let s = &self.buf[self.pos..self.pos + len];
|
||||
self.pos += len + 1;
|
||||
match s.to_str() {
|
||||
Ok(s) => Ok(s),
|
||||
_ => Err(DbusError::InvalidUtf8),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_array<T: DbusType<'a>>(&mut self) -> Result<Cow<'a, [T]>, DbusError> {
|
||||
let len: u32 = self.read_pod()?;
|
||||
let len = len as usize;
|
||||
self.align_to(T::ALIGNMENT)?;
|
||||
if self.buf.len() - self.pos < len {
|
||||
return Err(DbusError::UnexpectedEof);
|
||||
}
|
||||
if T::IS_POD {
|
||||
if len % size_of::<T>() != 0 {
|
||||
return Err(DbusError::PodArrayLength);
|
||||
}
|
||||
let slice = unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
self.buf[self.pos..].as_ptr() as *const T,
|
||||
len / size_of::<T>(),
|
||||
)
|
||||
};
|
||||
self.pos += len;
|
||||
Ok(Cow::Borrowed(slice))
|
||||
} else {
|
||||
let mut parser = Parser {
|
||||
buf: &self.buf[..self.pos + len],
|
||||
pos: self.pos,
|
||||
fds: self.fds,
|
||||
};
|
||||
self.pos += len;
|
||||
let mut res = vec![];
|
||||
while !parser.eof() {
|
||||
res.push(T::unmarshal(&mut parser)?);
|
||||
}
|
||||
Ok(Cow::Owned(res))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_variant(&mut self) -> Result<Variant<'a>, DbusError> {
|
||||
let sig = self.read_signature()?;
|
||||
let sig = sig.0.as_bytes();
|
||||
let (parser, rem) = DynamicType::from_signature(sig)?;
|
||||
if rem.len() > 0 {
|
||||
return Err(DbusError::TrailingVariantSignature);
|
||||
}
|
||||
parser.parse(self)
|
||||
}
|
||||
|
||||
pub fn read_variant_as<T: DbusType<'a>>(&mut self) -> Result<T, DbusError> {
|
||||
let sig = self.read_signature()?;
|
||||
let mut sig = sig.0.as_bytes();
|
||||
T::consume_signature(&mut sig)?;
|
||||
if sig.len() > 0 {
|
||||
return Err(DbusError::TrailingVariantSignature);
|
||||
}
|
||||
T::unmarshal(self)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
use {
|
||||
crate::dbus::{DbusError, DbusType, Formatter, Message, MethodCall, Parser},
|
||||
std::{borrow::Cow, marker::PhantomData},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Get<'a, T: DbusType<'static>> {
|
||||
pub interface_name: Cow<'a, str>,
|
||||
pub property_name: Cow<'a, str>,
|
||||
pub _phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: DbusType<'static>> Message<'a> for Get<'a, T> {
|
||||
const SIGNATURE: &'static str = "ss";
|
||||
const INTERFACE: &'static str = "org.freedesktop.DBus.Properties";
|
||||
const MEMBER: &'static str = "Get";
|
||||
type Generic<'b> = Get<'b, T>;
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.marshal(&self.interface_name);
|
||||
fmt.marshal(&self.property_name);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
Ok(Self {
|
||||
interface_name: parser.unmarshal()?,
|
||||
property_name: parser.unmarshal()?,
|
||||
_phantom: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
fn num_fds(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: DbusType<'static>> MethodCall<'a> for Get<'a, T> {
|
||||
type Reply = GetReply<'static, T>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GetReply<'a, T: DbusType<'a>> {
|
||||
pub value: T,
|
||||
pub _phantom: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: DbusType<'a>> Message<'a> for GetReply<'a, T> {
|
||||
const SIGNATURE: &'static str = "v";
|
||||
const INTERFACE: &'static str = "org.freedesktop.DBus.Properties";
|
||||
const MEMBER: &'static str = "Get";
|
||||
type Generic<'b> = GetReply<'b, T::Generic<'b>>;
|
||||
|
||||
fn marshal(&self, _fmt: &mut Formatter) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
Ok(Self {
|
||||
value: parser.read_variant_as()?,
|
||||
_phantom: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
fn num_fds(&self) -> u32 {
|
||||
self.value.num_fds()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,542 +0,0 @@
|
|||
use {
|
||||
crate::{
|
||||
dbus::{
|
||||
DbusError, DbusType, DynamicType, Formatter, Parser, TY_ARRAY, TY_BOOLEAN, TY_BYTE,
|
||||
TY_DOUBLE, TY_INT16, TY_INT32, TY_INT64, TY_OBJECT_PATH, TY_SIGNATURE, TY_STRING,
|
||||
TY_UINT16, TY_UINT32, TY_UINT64, TY_UNIX_FD, TY_VARIANT,
|
||||
},
|
||||
utils::buf::DynamicBuf,
|
||||
},
|
||||
std::{borrow::Cow, ops::Deref, rc::Rc},
|
||||
uapi::{OwnedFd, Packed, Pod},
|
||||
};
|
||||
|
||||
macro_rules! consume_signature_body {
|
||||
($s:expr, $ty:expr) => {{
|
||||
if $s.is_empty() {
|
||||
return Err(DbusError::EmptySignature);
|
||||
}
|
||||
if $s[0] != $ty {
|
||||
return Err(DbusError::InvalidSignatureType);
|
||||
}
|
||||
*$s = &(*$s)[1..];
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! signature {
|
||||
($ty:expr) => {
|
||||
fn consume_signature(s: &mut &[u8]) -> Result<(), DbusError> {
|
||||
consume_signature_body!(s, $ty);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_BYTE);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for u8 {
|
||||
const ALIGNMENT: usize = 1;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
signature!(TY_BYTE);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_pod()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[repr(transparent)]
|
||||
pub struct Bool(u32);
|
||||
pub const FALSE: Bool = Bool(0);
|
||||
pub const TRUE: Bool = Bool(1);
|
||||
|
||||
unsafe impl Pod for Bool {}
|
||||
unsafe impl Packed for Bool {}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for Bool {
|
||||
const ALIGNMENT: usize = 4;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
signature!(TY_BOOLEAN);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_bool()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for i16 {
|
||||
const ALIGNMENT: usize = 2;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
signature!(TY_INT16);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_pod()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for u16 {
|
||||
const ALIGNMENT: usize = 2;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
signature!(TY_UINT16);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_pod()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for i32 {
|
||||
const ALIGNMENT: usize = 4;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
signature!(TY_INT32);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_pod()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for u32 {
|
||||
const ALIGNMENT: usize = 4;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
signature!(TY_UINT32);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_pod()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for i64 {
|
||||
const ALIGNMENT: usize = 8;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
signature!(TY_INT64);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_pod()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for u64 {
|
||||
const ALIGNMENT: usize = 8;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
signature!(TY_UINT64);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_pod()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for f64 {
|
||||
const ALIGNMENT: usize = 8;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
signature!(TY_DOUBLE);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(&self.to_bits());
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
Ok(f64::from_bits(parser.read_pod()?))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for Cow<'a, str> {
|
||||
const ALIGNMENT: usize = 4;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = Cow<'b, str>;
|
||||
|
||||
signature!(TY_STRING);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_str(self);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Signature<'a>(pub Cow<'a, str>);
|
||||
|
||||
impl<'a> Deref for Signature<'a> {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for Signature<'a> {
|
||||
const ALIGNMENT: usize = 1;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = Signature<'b>;
|
||||
|
||||
signature!(TY_SIGNATURE);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_signature(self.0.as_bytes());
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_signature()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ObjectPath<'a>(pub Cow<'a, str>);
|
||||
|
||||
impl<'a> Deref for ObjectPath<'a> {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for ObjectPath<'a> {
|
||||
const ALIGNMENT: usize = 4;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = ObjectPath<'b>;
|
||||
|
||||
signature!(TY_OBJECT_PATH);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_str(&self.0);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_object_path()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for Rc<OwnedFd> {
|
||||
const ALIGNMENT: usize = 4;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
signature!(TY_UNIX_FD);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_fd(self)
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_fd()
|
||||
}
|
||||
|
||||
fn num_fds(&self) -> u32 {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: DbusType<'a>> DbusType<'a> for Cow<'a, [T]> {
|
||||
const ALIGNMENT: usize = 4;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = Cow<'b, [T::Generic<'b>]>;
|
||||
|
||||
fn consume_signature(s: &mut &[u8]) -> Result<(), DbusError> {
|
||||
consume_signature_body!(s, TY_ARRAY);
|
||||
T::consume_signature(s)
|
||||
}
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_ARRAY);
|
||||
T::write_signature(w);
|
||||
}
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_array(self);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_array()
|
||||
}
|
||||
|
||||
fn num_fds(&self) -> u32 {
|
||||
let mut res = 0;
|
||||
for t in self.deref() {
|
||||
res += t.num_fds();
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct DictEntry<K, V> {
|
||||
pub key: K,
|
||||
pub value: V,
|
||||
}
|
||||
|
||||
unsafe impl<'a, K: DbusType<'a>, V: DbusType<'a>> DbusType<'a> for DictEntry<K, V> {
|
||||
const ALIGNMENT: usize = 8;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = DictEntry<K::Generic<'b>, V::Generic<'b>>;
|
||||
|
||||
fn consume_signature(s: &mut &[u8]) -> Result<(), DbusError> {
|
||||
consume_signature_body!(s, b'{');
|
||||
K::consume_signature(s)?;
|
||||
V::consume_signature(s)?;
|
||||
consume_signature_body!(s, b'}');
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(b'{');
|
||||
K::write_signature(w);
|
||||
V::write_signature(w);
|
||||
w.push(b'}');
|
||||
}
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.pad_to(8);
|
||||
self.key.marshal(fmt);
|
||||
self.value.marshal(fmt);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.align_to(8)?;
|
||||
Ok(Self {
|
||||
key: K::unmarshal(parser)?,
|
||||
value: V::unmarshal(parser)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! tuple {
|
||||
($($p:ident),*) => {
|
||||
#[expect(non_snake_case)]
|
||||
unsafe impl<'a, $($p: DbusType<'a>),*> DbusType<'a> for ($($p,)*) {
|
||||
const ALIGNMENT: usize = 8;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = ($($p::Generic<'b>,)*);
|
||||
|
||||
fn consume_signature(s: &mut &[u8]) -> Result<(), DbusError> {
|
||||
consume_signature_body!(s, b'(');
|
||||
$(
|
||||
$p::consume_signature(s)?;
|
||||
)*
|
||||
consume_signature_body!(s, b')');
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(b'(');
|
||||
$(
|
||||
$p::write_signature(w);
|
||||
)*
|
||||
w.push(b')');
|
||||
}
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
let ($($p,)*) = self;
|
||||
fmt.pad_to(8);
|
||||
$(
|
||||
$p.marshal(fmt);
|
||||
)*
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.align_to(8)?;
|
||||
Ok(($($p::unmarshal(parser)?,)*))
|
||||
}
|
||||
|
||||
fn num_fds(&self) -> u32 {
|
||||
let mut res = 0;
|
||||
let ($($p,)*) = self;
|
||||
$(
|
||||
res += $p.num_fds();
|
||||
)*
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tuple!(A);
|
||||
tuple!(A, B);
|
||||
tuple!(A, B, C);
|
||||
tuple!(A, B, C, D);
|
||||
tuple!(A, B, C, D, E);
|
||||
tuple!(A, B, C, D, E, F);
|
||||
tuple!(A, B, C, D, E, F, G);
|
||||
tuple!(A, B, C, D, E, F, G, H);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Variant<'a> {
|
||||
U8(u8),
|
||||
Bool(Bool),
|
||||
I16(i16),
|
||||
U16(u16),
|
||||
I32(i32),
|
||||
U32(u32),
|
||||
I64(i64),
|
||||
U64(u64),
|
||||
F64(f64),
|
||||
String(Cow<'a, str>),
|
||||
ObjectPath(ObjectPath<'a>),
|
||||
Signature(Signature<'a>),
|
||||
Variant(Box<Variant<'a>>),
|
||||
Fd(Rc<OwnedFd>),
|
||||
Array(DynamicType, Vec<Variant<'a>>),
|
||||
DictEntry(Box<Variant<'a>>, Box<Variant<'a>>),
|
||||
Struct(Vec<Variant<'a>>),
|
||||
}
|
||||
|
||||
impl<'a> Variant<'a> {
|
||||
pub fn into_string(self) -> Result<Cow<'a, str>, DbusError> {
|
||||
match self {
|
||||
Variant::String(s) => Ok(s),
|
||||
_ => Err(DbusError::InvalidVariantType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_object_path(self) -> Result<ObjectPath<'a>, DbusError> {
|
||||
match self {
|
||||
Variant::ObjectPath(s) => Ok(s),
|
||||
_ => Err(DbusError::InvalidVariantType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_signature(self) -> Result<Signature<'a>, DbusError> {
|
||||
match self {
|
||||
Variant::Signature(s) => Ok(s),
|
||||
_ => Err(DbusError::InvalidVariantType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_u32(self) -> Result<u32, DbusError> {
|
||||
match self {
|
||||
Variant::U32(s) => Ok(s),
|
||||
_ => Err(DbusError::InvalidVariantType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_signature(&self, w: &mut DynamicBuf) {
|
||||
let c = match self {
|
||||
Variant::U8(..) => TY_BYTE,
|
||||
Variant::Bool(..) => TY_BOOLEAN,
|
||||
Variant::I16(..) => TY_INT16,
|
||||
Variant::U16(..) => TY_UINT16,
|
||||
Variant::I32(..) => TY_INT32,
|
||||
Variant::U32(..) => TY_UINT32,
|
||||
Variant::I64(..) => TY_INT64,
|
||||
Variant::U64(..) => TY_UINT64,
|
||||
Variant::F64(..) => TY_DOUBLE,
|
||||
Variant::String(..) => TY_STRING,
|
||||
Variant::ObjectPath(..) => TY_OBJECT_PATH,
|
||||
Variant::Signature(..) => TY_SIGNATURE,
|
||||
Variant::Variant(..) => TY_VARIANT,
|
||||
Variant::Fd(..) => TY_UNIX_FD,
|
||||
Variant::Array(el, _) => {
|
||||
w.push(TY_ARRAY);
|
||||
el.write_signature(w);
|
||||
return;
|
||||
}
|
||||
Variant::DictEntry(k, v) => {
|
||||
w.push(b'{');
|
||||
k.write_signature(w);
|
||||
v.write_signature(w);
|
||||
w.push(b'}');
|
||||
return;
|
||||
}
|
||||
Variant::Struct(f) => {
|
||||
w.push(b'(');
|
||||
for f in f {
|
||||
f.write_signature(w);
|
||||
}
|
||||
w.push(b')');
|
||||
return;
|
||||
}
|
||||
};
|
||||
w.push(c);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for Variant<'a> {
|
||||
const ALIGNMENT: usize = 1;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = Variant<'b>;
|
||||
|
||||
signature!(TY_VARIANT);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_variant(self);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_variant()
|
||||
}
|
||||
|
||||
fn num_fds(&self) -> u32 {
|
||||
match self {
|
||||
Variant::U8(_) => 0,
|
||||
Variant::Bool(_) => 0,
|
||||
Variant::I16(_) => 0,
|
||||
Variant::U16(_) => 0,
|
||||
Variant::I32(_) => 0,
|
||||
Variant::U32(_) => 0,
|
||||
Variant::I64(_) => 0,
|
||||
Variant::U64(_) => 0,
|
||||
Variant::F64(_) => 0,
|
||||
Variant::String(_) => 0,
|
||||
Variant::ObjectPath(_) => 0,
|
||||
Variant::Signature(_) => 0,
|
||||
Variant::Variant(v) => v.num_fds(),
|
||||
Variant::Array(_, a) => a.iter().map(|e| e.num_fds()).sum(),
|
||||
Variant::DictEntry(k, v) => k.num_fds() + v.num_fds(),
|
||||
Variant::Struct(f) => f.iter().map(|f| f.num_fds()).sum(),
|
||||
Variant::Fd(_) => 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue