#[cfg(unix)]
use crate::wire::{Fd, OwnedFd};
use std::{
borrow::Cow,
ops::{Bound, Deref, Range, RangeBounds},
sync::Arc,
};
use serde::{Deserialize, de::DeserializeSeed};
use crate::{
Error, Result,
wire::{
DynamicDeserialize, DynamicType, Signature, Type, de::Deserializer, serialized::Context,
},
};
#[derive(Clone, Debug)]
pub struct Data<'bytes, 'fds> {
inner: Arc<Inner<'bytes, 'fds>>,
context: Context,
range: Range<usize>,
}
#[derive(Debug)]
pub struct Inner<'bytes, 'fds> {
bytes: Cow<'bytes, [u8]>,
#[cfg(unix)]
fds: Vec<Fd<'fds>>,
#[cfg(not(unix))]
_fds: std::marker::PhantomData<&'fds ()>,
}
impl<'bytes, 'fds> Data<'bytes, 'fds> {
#[cfg(unix)]
pub fn new_borrowed_fds<T>(
bytes: T,
context: Context,
fds: impl IntoIterator<Item = impl Into<Fd<'fds>>>,
) -> Self
where
T: Into<Cow<'bytes, [u8]>>,
{
let bytes = bytes.into();
let range = Range {
start: 0,
end: bytes.len(),
};
Data {
inner: Arc::new(Inner {
bytes,
fds: fds.into_iter().map(Into::into).collect(),
}),
range,
context,
}
}
pub fn bytes(&self) -> &[u8] {
&self.inner.bytes[self.range.start..self.range.end]
}
pub fn context(&self) -> Context {
self.context
}
#[cfg(unix)]
pub fn fds(&self) -> &[Fd<'fds>] {
&self.inner.fds
}
pub fn slice(&self, range: impl RangeBounds<usize>) -> Data<'bytes, 'fds> {
let len = self.range.end - self.range.start;
let start = match range.start_bound() {
Bound::Included(&n) => n,
Bound::Excluded(&n) => n + 1,
Bound::Unbounded => 0,
};
let end = match range.end_bound() {
Bound::Included(&n) => n + 1,
Bound::Excluded(&n) => n,
Bound::Unbounded => len,
};
assert!(
start <= end,
"range start must not be greater than end: {start:?} > {end:?}",
);
assert!(end <= len, "range end out of bounds: {end:?} > {len:?}");
let context = Context::new(self.context.endian(), self.context.position() + start);
let range = Range {
start: self.range.start + start,
end: self.range.start + end,
};
Data {
inner: self.inner.clone(),
context,
range,
}
}
pub fn deserialize<'d, T>(&'d self) -> Result<(T, usize)>
where
T: Deserialize<'d> + Type,
{
self.deserialize_for_signature(T::SIGNATURE)
}
pub fn deserialize_for_signature<'d, S, T>(&'d self, signature: S) -> Result<(T, usize)>
where
T: Deserialize<'d>,
S: TryInto<Signature>,
S::Error: Into<Error>,
{
let signature = signature.try_into().map_err(Into::into)?;
#[cfg(unix)]
let fds = &self.inner.fds;
let mut de = {
#[cfg(unix)]
{
crate::wire::dbus::Deserializer::new(
self.bytes(),
Some(fds),
&signature,
self.context,
)
}
#[cfg(not(unix))]
{
crate::wire::dbus::Deserializer::<()>::new(self.bytes(), &signature, self.context)
}
}
.map(Deserializer::DBus)?;
T::deserialize(&mut de).map(|t| match de {
Deserializer::DBus(de) => (t, de.0.pos),
})
}
pub fn deserialize_for_dynamic_signature<'d, S, T>(&'d self, signature: S) -> Result<(T, usize)>
where
T: DynamicDeserialize<'d>,
S: TryInto<Signature>,
S::Error: Into<Error>,
{
let signature = signature.try_into().map_err(Into::into)?;
let seed = T::deserializer_for_signature(&signature)?;
self.deserialize_with_seed(seed)
}
pub fn deserialize_with_seed<'d, S>(&'d self, seed: S) -> Result<(S::Value, usize)>
where
S: DeserializeSeed<'d> + DynamicType,
{
let signature = S::signature(&seed);
#[cfg(unix)]
let fds = &self.inner.fds;
let mut de = {
#[cfg(unix)]
{
crate::wire::dbus::Deserializer::new(
self.bytes(),
Some(fds),
&signature,
self.context,
)
}
#[cfg(not(unix))]
{
crate::wire::dbus::Deserializer::<()>::new(self.bytes(), &signature, self.context)
}
}
.map(Deserializer::DBus)?;
seed.deserialize(&mut de).map(|t| match de {
Deserializer::DBus(de) => (t, de.0.pos),
})
}
}
impl<'bytes> Data<'bytes, 'static> {
pub fn new<T>(bytes: T, context: Context) -> Self
where
T: Into<Cow<'bytes, [u8]>>,
{
let bytes = bytes.into();
let range = Range {
start: 0,
end: bytes.len(),
};
Data {
inner: Arc::new(Inner {
bytes,
#[cfg(unix)]
fds: vec![],
#[cfg(not(unix))]
_fds: std::marker::PhantomData,
}),
context,
range,
}
}
#[cfg(unix)]
pub fn new_fds<T>(
bytes: T,
context: Context,
fds: impl IntoIterator<Item = impl Into<OwnedFd>>,
) -> Self
where
T: Into<Cow<'bytes, [u8]>>,
{
let bytes = bytes.into();
let range = Range {
start: 0,
end: bytes.len(),
};
Data {
inner: Arc::new(Inner {
bytes,
fds: fds.into_iter().map(Into::into).map(Fd::from).collect(),
}),
context,
range,
}
}
}
impl Deref for Data<'_, '_> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.bytes()
}
}
impl<T> AsRef<T> for Data<'_, '_>
where
T: ?Sized,
for<'bytes, 'fds> <Data<'bytes, 'fds> as Deref>::Target: AsRef<T>,
{
fn as_ref(&self) -> &T {
self.deref().as_ref()
}
}