diff --git a/rustbus/Cargo.toml b/rustbus/Cargo.toml index b023859..24cd194 100644 --- a/rustbus/Cargo.toml +++ b/rustbus/Cargo.toml @@ -11,7 +11,7 @@ homepage = "https://github.com/KillingSpark/rustbus" [dependencies] nix = { version = "0.28", features = ["fs", "poll", "socket", "uio", "user"] } -rustbus_derive = {version = "0.5.0", path = "../rustbus_derive"} +rustbus_derive = {version = "0.6.0", path = "../rustbus_derive"} thiserror = "1.0" [dev-dependencies] diff --git a/rustbus/benches/marshal_benchmark.rs b/rustbus/benches/marshal_benchmark.rs index db81f8f..bf3470e 100644 --- a/rustbus/benches/marshal_benchmark.rs +++ b/rustbus/benches/marshal_benchmark.rs @@ -6,16 +6,19 @@ use rustbus::wire::marshal::marshal; use rustbus::wire::unmarshal::unmarshal_dynamic_header; use rustbus::wire::unmarshal::unmarshal_header; use rustbus::wire::unmarshal::unmarshal_next_message; +use rustbus::wire::unmarshal_context::Cursor; fn marsh(msg: &rustbus::message_builder::MarshalledMessage, buf: &mut Vec) { marshal(msg, 0, buf).unwrap(); } fn unmarshal(buf: &[u8]) { - let (hdrbytes, header) = unmarshal_header(buf, 0).unwrap(); - let (dynhdrbytes, dynheader) = unmarshal_dynamic_header(&header, buf, hdrbytes).unwrap(); - let (_, _unmarshed_msg) = - unmarshal_next_message(&header, dynheader, buf.to_vec(), hdrbytes + dynhdrbytes).unwrap(); + let mut cursor = Cursor::new(buf); + let header = unmarshal_header(&mut cursor).unwrap(); + let dynheader = unmarshal_dynamic_header(&header, &mut cursor).unwrap(); + let _unmarshed_msg = + unmarshal_next_message(&header, dynheader, buf.to_vec(), cursor.consumed(), vec![]) + .unwrap(); } fn criterion_benchmark(c: &mut Criterion) { diff --git a/rustbus/fuzz/fuzz_targets/fuzz_unmarshal.rs b/rustbus/fuzz/fuzz_targets/fuzz_unmarshal.rs index 1c88bfe..1cb0cee 100644 --- a/rustbus/fuzz/fuzz_targets/fuzz_unmarshal.rs +++ b/rustbus/fuzz/fuzz_targets/fuzz_unmarshal.rs @@ -4,24 +4,22 @@ extern crate libfuzzer_sys; extern crate rustbus; fuzz_target!(|data: &[u8]| { - let (hdrbytes, header) = match rustbus::wire::unmarshal::unmarshal_header(data, 0) { - Ok(head) => head, - Err(_) => return, + let mut cursor = rustbus::wire::unmarshal_context::Cursor::new(data); + let Ok(header) = rustbus::wire::unmarshal::unmarshal_header(&mut cursor) else { + return; + }; + let Ok(dynheader) = rustbus::wire::unmarshal::unmarshal_dynamic_header(&header, &mut cursor) else { + return; }; - let (dynhdrbytes, dynheader) = - match rustbus::wire::unmarshal::unmarshal_dynamic_header(&header, data, hdrbytes) { - Ok(head) => head, - Err(_) => return, - }; - let (_bytes_used, msg) = match rustbus::wire::unmarshal::unmarshal_next_message( + let Ok(msg) = rustbus::wire::unmarshal::unmarshal_next_message( &header, dynheader, data.to_vec(), - hdrbytes + dynhdrbytes, - ) { - Ok(msg) => msg, - Err(_) => return, + cursor.consumed(), + vec![], + ) else { + return; }; try_unmarhal_traits(&msg); msg.unmarshall_all().ok(); diff --git a/rustbus/src/bin/fuzz_artifact.rs b/rustbus/src/bin/fuzz_artifact.rs index 8bdebfc..44f0191 100644 --- a/rustbus/src/bin/fuzz_artifact.rs +++ b/rustbus/src/bin/fuzz_artifact.rs @@ -2,6 +2,8 @@ use std::io::Read; +use rustbus::wire::unmarshal_context::Cursor; + fn main() { for path in std::env::args().skip(1) { println!("Run artifact: {}", path); @@ -16,29 +18,28 @@ fn run_artifact(path: &str) { file.read_to_end(&mut data).unwrap(); let data = &data; - let (hdrbytes, header) = match rustbus::wire::unmarshal::unmarshal_header(data, 0) { - Ok(head) => head, - Err(_) => return, + let mut cursor = Cursor::new(data); + let Ok(header) = rustbus::wire::unmarshal::unmarshal_header(&mut cursor) else { + return; }; println!("Header: {:?}", header); - let (dynhdrbytes, dynheader) = - match rustbus::wire::unmarshal::unmarshal_dynamic_header(&header, data, hdrbytes) { - Ok(head) => head, - Err(_) => return, - }; + let Ok(dynheader) = rustbus::wire::unmarshal::unmarshal_dynamic_header(&header, &mut cursor) + else { + return; + }; println!("Dynheader: {:?}", dynheader); - let (_bytes_used, msg) = match rustbus::wire::unmarshal::unmarshal_next_message( + let Ok(msg) = rustbus::wire::unmarshal::unmarshal_next_message( &header, dynheader, data.clone(), - hdrbytes + dynhdrbytes, - ) { - Ok(msg) => msg, - Err(_) => return, + cursor.consumed(), + vec![], + ) else { + return; }; println!("Message: {:?}", msg); diff --git a/rustbus/src/connection/ll_conn.rs b/rustbus/src/connection/ll_conn.rs index b3b2a66..a3fc154 100644 --- a/rustbus/src/connection/ll_conn.rs +++ b/rustbus/src/connection/ll_conn.rs @@ -18,6 +18,8 @@ use nix::sys::socket::{ SockaddrStorage, UnixAddr, }; +use crate::wire::unmarshal_context::Cursor; + /// A lowlevel abstraction over the raw unix socket #[derive(Debug)] pub struct SendConn { @@ -166,8 +168,8 @@ impl RecvConn { return Ok(16); } let msg_buf_in = &self.msg_buf_in.peek(); - let (_, header) = unmarshal::unmarshal_header(msg_buf_in, 0)?; - let (_, header_fields_len) = + let header = unmarshal::unmarshal_header(&mut Cursor::new(msg_buf_in))?; + let header_fields_len = crate::wire::util::parse_u32(&msg_buf_in[unmarshal::HEADER_LEN..], header.byteorder)?; let complete_header_size = unmarshal::HEADER_LEN + header_fields_len as usize + 4; // +4 because the length of the header fields does not count @@ -225,22 +227,22 @@ impl RecvConn { /// Blocks until a message has been read from the conn or the timeout has been reached pub fn get_next_message(&mut self, timeout: Timeout) -> Result { self.read_whole_message(timeout)?; - let (hdrbytes, header) = unmarshal::unmarshal_header(self.msg_buf_in.peek(), 0)?; - let (dynhdrbytes, dynheader) = - unmarshal::unmarshal_dynamic_header(&header, self.msg_buf_in.peek(), hdrbytes)?; - - let buf = self.msg_buf_in.take(); - let buf_len = buf.len(); - let (bytes_used, mut msg) = - unmarshal::unmarshal_next_message(&header, dynheader, buf, hdrbytes + dynhdrbytes)?; - msg.body.raw_fds = std::mem::take(&mut self.fds_in); + let mut cursor = Cursor::new(self.msg_buf_in.peek()); + let header = unmarshal::unmarshal_header(&mut cursor)?; + let dynheader = unmarshal::unmarshal_dynamic_header(&header, &mut cursor)?; + let header_bytes_consumed = cursor.consumed(); - if buf_len != bytes_used + hdrbytes + dynhdrbytes { - return Err(Error::UnmarshalError(UnmarshalError::NotAllBytesUsed)); - } + let buf = self.msg_buf_in.take(); + let raw_fds = std::mem::take(&mut self.fds_in); - Ok(msg) + Ok(unmarshal::unmarshal_next_message( + &header, + dynheader, + buf, + header_bytes_consumed, + raw_fds, + )?) } } @@ -454,12 +456,7 @@ impl SendMessageContext<'_> { // if this is not the first write for this message do not send the raw_fds again. This would lead to unexpected // duplicated FDs on the other end! let raw_fds = if self.state.bytes_sent == 0 { - self.msg - .body - .raw_fds - .iter() - .filter_map(|fd| fd.get_raw_fd()) - .collect::>() + self.msg.body.get_raw_fds() } else { vec![] }; diff --git a/rustbus/src/message_builder.rs b/rustbus/src/message_builder.rs index da9b9c7..42c289f 100644 --- a/rustbus/src/message_builder.rs +++ b/rustbus/src/message_builder.rs @@ -1,11 +1,13 @@ //! Build new messages that you want to send over a connection +use std::os::fd::RawFd; + use crate::params::message; use crate::signature::SignatureIter; use crate::wire::errors::MarshalError; use crate::wire::errors::UnmarshalError; use crate::wire::marshal::traits::{Marshal, SignatureBuffer}; use crate::wire::marshal::MarshalContext; -use crate::wire::unmarshal::UnmarshalContext; +use crate::wire::unmarshal_context::UnmarshalContext; use crate::wire::validate_raw; use crate::wire::UnixFd; use crate::ByteOrder; @@ -269,14 +271,13 @@ impl MarshalledMessage { } else { let sigs: Vec<_> = crate::signature::Type::parse_description(&self.body.sig)?; - let (_, params) = crate::wire::unmarshal::unmarshal_body( + crate::wire::unmarshal::unmarshal_body( self.body.byteorder, &sigs, self.body.get_buf(), &self.body.raw_fds, 0, - )?; - params + )? }; Ok(message::Message { dynheader: self.dynheader, @@ -295,10 +296,10 @@ pub struct MarshalledMessageBody { buf_offset: usize, // out of band data - pub(crate) raw_fds: Vec, + raw_fds: Vec, sig: SignatureBuffer, - pub(crate) byteorder: ByteOrder, + byteorder: ByteOrder, } impl Default for MarshalledMessageBody { @@ -377,11 +378,22 @@ impl MarshalledMessageBody { &self.buf[self.buf_offset..] } + pub fn get_raw_fds(&self) -> Vec { + self.raw_fds + .iter() + .filter_map(|fd| fd.get_raw_fd()) + .collect::>() + } + + pub fn byteorder(&self) -> ByteOrder { + self.byteorder + } + /// Get a clone of all the `UnixFd`s in the body. /// /// Some of the `UnixFd`s may already have their `RawFd`s taken. - pub fn get_fds(&self) -> Vec { - self.raw_fds.clone() + pub fn get_fds(&self) -> &[UnixFd] { + &self.raw_fds } /// Clears the buffer and signature but holds on to the memory allocations. You can now start pushing new /// params as if this were a new message. This allows to reuse the OutMessage for the same dbus-message with different @@ -790,15 +802,15 @@ impl<'fds, 'body: 'fds> MessageBodyParser<'body> { return Err(UnmarshalError::WrongSignature); } - let mut ctx = UnmarshalContext { - byteorder: self.body.byteorder, - buf: self.body.get_buf(), - offset: self.buf_idx, - fds: &self.body.raw_fds, - }; + let mut ctx = UnmarshalContext::new( + &self.body.raw_fds, + self.body.byteorder, + self.body.get_buf(), + self.buf_idx, + ); match T::unmarshal(&mut ctx) { - Ok((bytes, res)) => { - self.buf_idx += bytes; + Ok(res) => { + self.buf_idx = self.body.get_buf().len() - ctx.remainder().len(); self.sig_idx += expected_sig.len(); Ok(res) } @@ -904,18 +916,18 @@ impl<'fds, 'body: 'fds> MessageBodyParser<'body> { /// This checks if there are params left in the message and if the type you requested fits the signature of the message. pub fn get_param(&mut self) -> Result { if let Some(sig_str) = self.get_next_sig() { - let mut ctx = UnmarshalContext { - byteorder: self.body.byteorder, - buf: self.body.get_buf(), - offset: self.buf_idx, - fds: &self.body.raw_fds, - }; + let mut ctx = UnmarshalContext::new( + &self.body.raw_fds, + self.body.byteorder, + self.body.get_buf(), + self.buf_idx, + ); let sig = &crate::signature::Type::parse_description(sig_str).unwrap()[0]; match crate::wire::unmarshal::container::unmarshal_with_sig(sig, &mut ctx) { - Ok((bytes, res)) => { - self.buf_idx += bytes; + Ok(res) => { + self.buf_idx = self.body.get_buf().len() - ctx.remainder().len(); self.sig_idx += sig_str.len(); Ok(res) } diff --git a/rustbus/src/params/types.rs b/rustbus/src/params/types.rs index 9cab444..749d807 100644 --- a/rustbus/src/params/types.rs +++ b/rustbus/src/params/types.rs @@ -227,7 +227,7 @@ impl Marshal for Variant<'_, '_> { } impl<'buf, 'fds> Unmarshal<'buf, 'fds> for Variant<'buf, 'fds> { fn unmarshal( - ctx: &mut crate::wire::unmarshal::UnmarshalContext<'fds, 'buf>, + ctx: &mut crate::wire::unmarshal_context::UnmarshalContext<'fds, 'buf>, ) -> crate::wire::unmarshal::UnmarshalResult { crate::wire::unmarshal::container::unmarshal_variant(ctx) } diff --git a/rustbus/src/tests.rs b/rustbus/src/tests.rs index 30e3586..6186656 100644 --- a/rustbus/src/tests.rs +++ b/rustbus/src/tests.rs @@ -4,6 +4,7 @@ use crate::wire::marshal::marshal; use crate::wire::unmarshal::unmarshal_dynamic_header; use crate::wire::unmarshal::unmarshal_header; use crate::wire::unmarshal::unmarshal_next_message; +use crate::wire::unmarshal_context::Cursor; mod dbus_send; mod fdpassing; @@ -42,14 +43,16 @@ fn test_marshal_unmarshal() { msg.dynheader.serial = Some(1); let mut buf = Vec::new(); marshal(&msg, 0, &mut buf).unwrap(); - let (hdrbytes, header) = unmarshal_header(&buf, 0).unwrap(); - let (dynhdrbytes, dynheader) = unmarshal_dynamic_header(&header, &buf, hdrbytes).unwrap(); - let headers_plus_padding = hdrbytes + dynhdrbytes + (8 - ((hdrbytes + dynhdrbytes) % 8)); + let mut cursor = Cursor::new(&buf); + let header = unmarshal_header(&mut cursor).unwrap(); + let dynheader = unmarshal_dynamic_header(&header, &mut cursor).unwrap(); + + let headers_plus_padding = cursor.consumed() + (8 - ((cursor.consumed()) % 8)); assert_eq!(headers_plus_padding, buf.len()); - let (_, unmarshed_msg) = - unmarshal_next_message(&header, dynheader, msg.get_buf().to_vec(), 0).unwrap(); + let unmarshed_msg = + unmarshal_next_message(&header, dynheader, msg.get_buf().to_vec(), 0, vec![]).unwrap(); let msg = unmarshed_msg.unmarshall_all().unwrap(); diff --git a/rustbus/src/tests/fdpassing.rs b/rustbus/src/tests/fdpassing.rs index 21840cf..80f2d84 100644 --- a/rustbus/src/tests/fdpassing.rs +++ b/rustbus/src/tests/fdpassing.rs @@ -9,8 +9,10 @@ const TEST_STRING: &str = "This will be sent over the fd\n"; #[test] fn test_fd_passing() { - let mut con1 = - connection::rpc_conn::RpcConn::system_conn(connection::Timeout::Infinite).unwrap(); + let Ok(mut con1) = connection::rpc_conn::RpcConn::system_conn(connection::Timeout::Infinite) + else { + return; + }; let mut con2 = connection::rpc_conn::RpcConn::system_conn(connection::Timeout::Infinite).unwrap(); con1.send_message(&mut crate::standard_messages::hello()) @@ -108,9 +110,9 @@ fn test_fd_marshalling() { // assert the correct representation, where fds have been put into the fd array and the index is marshalled in the message assert_eq!(sig.body.get_buf(), &[0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0]); - assert_ne!(&sig.body.raw_fds[0], &test_fd1); - assert_ne!(&sig.body.raw_fds[1], &test_fd2); - assert_ne!(&sig.body.raw_fds[2], &test_fd3); + assert_ne!(&sig.body.get_fds()[0], &test_fd1); + assert_ne!(&sig.body.get_fds()[1], &test_fd2); + assert_ne!(&sig.body.get_fds()[2], &test_fd3); // assert that unmarshalling yields the correct fds let mut parser = sig.body.parser(); diff --git a/rustbus/src/wire.rs b/rustbus/src/wire.rs index 522b91d..1b22795 100644 --- a/rustbus/src/wire.rs +++ b/rustbus/src/wire.rs @@ -3,6 +3,7 @@ pub mod errors; pub mod marshal; pub mod unmarshal; +pub mod unmarshal_context; pub mod util; pub mod validate_raw; pub mod variant_macros; diff --git a/rustbus/src/wire/marshal.rs b/rustbus/src/wire/marshal.rs index d9f1cf9..1588f31 100644 --- a/rustbus/src/wire/marshal.rs +++ b/rustbus/src/wire/marshal.rs @@ -42,7 +42,7 @@ pub fn marshal( // set the correct message length insert_u32( - msg.body.byteorder, + msg.body.byteorder(), msg.get_buf().len() as u32, &mut buf[4..8], ); @@ -54,7 +54,7 @@ fn marshal_header( chosen_serial: u32, buf: &mut Vec, ) -> MarshalResult<()> { - let byteorder = msg.body.byteorder; + let byteorder = msg.body.byteorder(); match byteorder { ByteOrder::BigEndian => { @@ -105,10 +105,10 @@ fn marshal_header( if let Some(obj) = &msg.dynheader.object { marshal_header_field(byteorder, &HeaderField::Path(obj.clone()), buf)?; } - if !msg.body.raw_fds.is_empty() { + if !msg.body.get_fds().is_empty() { marshal_header_field( byteorder, - &HeaderField::UnixFds(msg.body.raw_fds.len() as u32), + &HeaderField::UnixFds(msg.body.get_fds().len() as u32), buf, )?; } diff --git a/rustbus/src/wire/marshal/traits/container.rs b/rustbus/src/wire/marshal/traits/container.rs index e63258c..1d4b1a4 100644 --- a/rustbus/src/wire/marshal/traits/container.rs +++ b/rustbus/src/wire/marshal/traits/container.rs @@ -241,7 +241,7 @@ impl Marshal impl Marshal for Vec { fn marshal(&self, ctx: &mut MarshalContext) -> Result<(), MarshalError> { - self.as_slice().marshal(ctx) + <&[E] as Marshal>::marshal(&self.as_slice(), ctx) } } @@ -270,7 +270,30 @@ impl Signature for [E] { } impl Marshal for [E] { fn marshal(&self, ctx: &mut MarshalContext) -> Result<(), MarshalError> { - (&self).marshal(ctx) + <&[E] as Marshal>::marshal(&self, ctx) + } +} + +impl Signature for [E; N] { + #[inline] + fn signature() -> crate::signature::Type { + <[E]>::signature() + } + #[inline] + fn alignment() -> usize { + <[E]>::alignment() + } + #[inline] + fn sig_str(s_buf: &mut SignatureBuffer) { + <[E]>::sig_str(s_buf) + } + fn has_sig(sig: &str) -> bool { + <[E]>::has_sig(sig) + } +} +impl Marshal for [E; N] { + fn marshal(&self, ctx: &mut MarshalContext) -> Result<(), MarshalError> { + <&[E] as Marshal>::marshal(&self.as_slice(), ctx) } } diff --git a/rustbus/src/wire/unmarshal.rs b/rustbus/src/wire/unmarshal.rs index 4dbcbec..117ac54 100644 --- a/rustbus/src/wire/unmarshal.rs +++ b/rustbus/src/wire/unmarshal.rs @@ -23,6 +23,9 @@ pub mod traits; use container::*; +use super::unmarshal_context::{Cursor, UnmarshalContext}; +use super::UnixFd; + #[derive(Debug, Clone, Copy)] pub struct Header { pub byteorder: ByteOrder, @@ -33,26 +36,6 @@ pub struct Header { pub serial: u32, } -pub struct UnmarshalContext<'fds, 'buf> { - pub fds: &'fds [crate::wire::UnixFd], - pub buf: &'buf [u8], - pub byteorder: ByteOrder, - pub offset: usize, -} - -impl UnmarshalContext<'_, '_> { - pub fn align_to(&mut self, alignment: usize) -> Result { - let padding = crate::wire::util::align_offset(alignment, self.buf, self.offset)?; - - if self.offset + padding > self.buf.len() { - Err(UnmarshalError::NotEnoughBytes) - } else { - self.offset += padding; - Ok(padding) - } - } -} - impl From for UnmarshalError { fn from(e: crate::signature::Error) -> Self { UnmarshalError::Validation(crate::params::validation::Error::InvalidSignature(e)) @@ -67,82 +50,70 @@ impl UnmarshalError { } } -pub const HEADER_LEN: usize = 12; +pub type UnmarshalResult = std::result::Result; -pub type UnmarshalResult = std::result::Result<(usize, T), UnmarshalError>; +pub const HEADER_LEN: usize = 12; -pub fn unmarshal_header(buf: &[u8], offset: usize) -> UnmarshalResult
{ - if buf.len() < offset + HEADER_LEN { +pub fn unmarshal_header(cursor: &mut Cursor) -> UnmarshalResult
{ + if cursor.remainder().len() < HEADER_LEN { return Err(UnmarshalError::NotEnoughBytes); } - let header_slice = &buf[offset..offset + HEADER_LEN]; - let byteorder = match header_slice[0] { + let byteorder = match cursor.read_u8()? { b'l' => ByteOrder::LittleEndian, b'B' => ByteOrder::BigEndian, _ => return Err(UnmarshalError::InvalidByteOrder), }; - let typ = match header_slice[1] { + let typ = match cursor.read_u8()? { 1 => MessageType::Call, 2 => MessageType::Reply, 3 => MessageType::Error, 4 => MessageType::Signal, _ => return Err(UnmarshalError::InvalidMessageType), }; - let flags = header_slice[2]; - let version = header_slice[3]; - let (_, body_len) = parse_u32(&header_slice[4..8], byteorder)?; - let (_, serial) = parse_u32(&header_slice[8..12], byteorder)?; + let flags = cursor.read_u8()?; + let version = cursor.read_u8()?; + let body_len = cursor.read_u32(byteorder)?; + let serial = cursor.read_u32(byteorder)?; - Ok(( - HEADER_LEN, - Header { - byteorder, - typ, - flags, - version, - body_len, - serial, - }, - )) + Ok(Header { + byteorder, + typ, + flags, + version, + body_len, + serial, + }) } pub fn unmarshal_dynamic_header( header: &Header, - buf: &[u8], - offset: usize, + cursor: &mut Cursor, ) -> UnmarshalResult { - let (fields_bytes_used, fields) = unmarshal_header_fields(header, buf, offset)?; + let fields = unmarshal_header_fields(header, cursor)?; let mut hdr = DynamicHeader { serial: Some(header.serial), ..Default::default() }; collect_header_fields(&fields, &mut hdr); - Ok((fields_bytes_used, hdr)) + Ok(hdr) } -pub fn unmarshal_body<'a, 'e>( +pub fn unmarshal_body( byteorder: ByteOrder, sigs: &[crate::signature::Type], buf: &[u8], fds: &[crate::wire::UnixFd], offset: usize, -) -> UnmarshalResult>> { +) -> UnmarshalResult>> { let mut params = Vec::new(); - let mut body_bytes_used = 0; - let mut ctx = UnmarshalContext { - fds, - buf, - byteorder, - offset, - }; + let mut ctx = UnmarshalContext::new(fds, byteorder, buf, offset); for param_sig in sigs { - let (bytes, new_param) = unmarshal_with_sig(param_sig, &mut ctx)?; + let new_param = unmarshal_with_sig(param_sig, &mut ctx)?; params.push(new_param); - body_bytes_used += bytes; } - Ok((body_bytes_used, params)) + Ok(params) } pub fn unmarshal_next_message( @@ -150,6 +121,7 @@ pub fn unmarshal_next_message( dynheader: DynamicHeader, buf: Vec, offset: usize, + raw_fds: Vec, ) -> UnmarshalResult { let sig = dynheader.signature.clone().unwrap_or_else(|| "".to_owned()); let padding = align_offset(8, &buf, offset)?; @@ -157,64 +129,61 @@ pub fn unmarshal_next_message( if header.body_len == 0 { let msg = MarshalledMessage { dynheader, - body: MarshalledMessageBody::from_parts(vec![], 0, vec![], sig, header.byteorder), + body: MarshalledMessageBody::from_parts(vec![], 0, raw_fds, sig, header.byteorder), typ: header.typ, flags: header.flags, }; - Ok((padding, msg)) + Ok(msg) } else { let offset = offset + padding; if buf[offset..].len() < (header.body_len as usize) { return Err(UnmarshalError::NotEnoughBytes); } + if buf[offset..].len() != header.body_len as usize { + return Err(UnmarshalError::NotAllBytesUsed); + } let msg = MarshalledMessage { dynheader, - body: MarshalledMessageBody::from_parts(buf, offset, vec![], sig, header.byteorder), + body: MarshalledMessageBody::from_parts(buf, offset, raw_fds, sig, header.byteorder), typ: header.typ, flags: header.flags, }; - Ok((padding + header.body_len as usize, msg)) + Ok(msg) } } fn unmarshal_header_fields( header: &Header, - buf: &[u8], - offset: usize, + cursor: &mut Cursor, ) -> UnmarshalResult> { - let (_, header_fields_bytes) = parse_u32(&buf[offset..], header.byteorder)?; - let offset = offset + 4; + let header_fields_bytes = cursor.read_u32(header.byteorder)?; - if offset + header_fields_bytes as usize > buf.len() { + if cursor.remainder().len() < header_fields_bytes as usize { return Err(UnmarshalError::NotEnoughBytes); } + let mut cursor = Cursor::new(cursor.read_raw(header_fields_bytes as usize)?); let mut fields = Vec::new(); - let mut bytes_used_counter = 0; - while bytes_used_counter < header_fields_bytes as usize { - match unmarshal_header_field(header, buf, offset + bytes_used_counter) { - Ok((bytes_used, field)) => { + while !cursor.remainder().is_empty() { + match unmarshal_header_field(header, &mut cursor) { + Ok(field) => { fields.push(field); - bytes_used_counter += bytes_used; } Err(UnmarshalError::UnknownHeaderField) => { - // for the unknown header field code which is always one byte - bytes_used_counter += 1; - // try to validate that there is indeed a valid dbus variant. This is mandatory so the message follows the spec, // even if we just ignore the contents. match crate::wire::validate_raw::validate_marshalled( header.byteorder, - offset + bytes_used_counter, - buf, + 0, + cursor.remainder(), &crate::signature::Type::Container(crate::signature::Container::Variant), ) { Ok(bytes) => { // ignore happy path, but increase counter. - bytes_used_counter += bytes; + cursor.advance(bytes); } // if the unknown header contains invalid values this is still an error, and the message should be treated as unreadable Err((_bytes, err)) => return Err(err), @@ -226,112 +195,88 @@ fn unmarshal_header_fields( params::validate_header_fields(header.typ, &fields) .map_err(|_| UnmarshalError::InvalidHeaderFields)?; - Ok((header_fields_bytes as usize + 4, fields)) + Ok(fields) } -fn unmarshal_header_field( - header: &Header, - buf: &[u8], - offset: usize, -) -> UnmarshalResult { - // align to 8 because the header fields are an array structs `a(yv)` - let padding = align_offset(8, buf, offset)?; - let offset = offset + padding; +fn unmarshal_header_field(header: &Header, cursor: &mut Cursor) -> UnmarshalResult { + // align to 8 because the header fields are an array of structs `a(yv)` + cursor.align_to(8)?; - // check that there is enough bytes in the buffer after padding - if buf.len() <= offset { - return Err(UnmarshalError::NotEnoughBytes); - } - let typ = buf[offset]; - let typ_bytes_used = 1; - let offset = offset + typ_bytes_used; + let typ = cursor.read_u8()?; - let (sig_bytes_used, sig_str) = unmarshal_signature(&buf[offset..])?; + let sig_str = cursor.read_signature()?; let mut sig = signature::Type::parse_description(sig_str).map_err(|_| UnmarshalError::NoSignature)?; - let offset = offset + sig_bytes_used; if sig.len() != 1 { // There must be exactly one type in the signature! return Err(UnmarshalError::NoSignature); } let sig = sig.remove(0); - let (field_bytes_used, field) = match typ { + match typ { 1 => match sig { signature::Type::Base(signature::Base::ObjectPath) => { - let (b, objpath) = unmarshal_string(header.byteorder, &buf[offset..])?; - crate::params::validate_object_path(&objpath)?; - (b, Ok(HeaderField::Path(objpath))) + let objpath = cursor.read_str(header.byteorder)?; + crate::params::validate_object_path(objpath)?; + Ok(HeaderField::Path(objpath.to_owned())) } - _ => (0, Err(UnmarshalError::WrongSignature)), + _ => Err(UnmarshalError::WrongSignature), }, 2 => match sig { - signature::Type::Base(signature::Base::String) => { - let (b, int) = unmarshal_string(header.byteorder, &buf[offset..])?; - (b, Ok(HeaderField::Interface(int))) - } - _ => (0, Err(UnmarshalError::WrongSignature)), + signature::Type::Base(signature::Base::String) => Ok(HeaderField::Interface( + cursor.read_str(header.byteorder)?.to_owned(), + )), + _ => Err(UnmarshalError::WrongSignature), }, 3 => match sig { - signature::Type::Base(signature::Base::String) => { - let (b, mem) = unmarshal_string(header.byteorder, &buf[offset..])?; - (b, Ok(HeaderField::Member(mem))) - } - _ => (0, Err(UnmarshalError::WrongSignature)), + signature::Type::Base(signature::Base::String) => Ok(HeaderField::Member( + cursor.read_str(header.byteorder)?.to_owned(), + )), + _ => Err(UnmarshalError::WrongSignature), }, 4 => match sig { - signature::Type::Base(signature::Base::String) => { - let (b, name) = unmarshal_string(header.byteorder, &buf[offset..])?; - (b, Ok(HeaderField::ErrorName(name))) - } - _ => (0, Err(UnmarshalError::WrongSignature)), + signature::Type::Base(signature::Base::String) => Ok(HeaderField::ErrorName( + cursor.read_str(header.byteorder)?.to_owned(), + )), + _ => Err(UnmarshalError::WrongSignature), }, 5 => match sig { signature::Type::Base(signature::Base::Uint32) => { - let (b, serial) = parse_u32(&buf[offset..], header.byteorder)?; - (b, Ok(HeaderField::ReplySerial(serial))) + Ok(HeaderField::ReplySerial(cursor.read_u32(header.byteorder)?)) } - _ => (0, Err(UnmarshalError::WrongSignature)), + _ => Err(UnmarshalError::WrongSignature), }, 6 => match sig { - signature::Type::Base(signature::Base::String) => { - let (b, dest) = unmarshal_string(header.byteorder, &buf[offset..])?; - (b, Ok(HeaderField::Destination(dest))) - } - _ => (0, Err(UnmarshalError::WrongSignature)), + signature::Type::Base(signature::Base::String) => Ok(HeaderField::Destination( + cursor.read_str(header.byteorder)?.to_owned(), + )), + _ => Err(UnmarshalError::WrongSignature), }, 7 => match sig { - signature::Type::Base(signature::Base::String) => { - let (b, snd) = unmarshal_string(header.byteorder, &buf[offset..])?; - (b, Ok(HeaderField::Sender(snd))) - } - _ => (0, Err(UnmarshalError::WrongSignature)), + signature::Type::Base(signature::Base::String) => Ok(HeaderField::Sender( + cursor.read_str(header.byteorder)?.to_owned(), + )), + _ => Err(UnmarshalError::WrongSignature), }, 8 => match sig { signature::Type::Base(signature::Base::Signature) => { - let (b, sig) = unmarshal_signature(&buf[offset..])?; + let sig = cursor.read_signature()?; // empty signature is allowed here if !sig.is_empty() { crate::params::validate_signature(sig)?; } - (b, Ok(HeaderField::Signature(sig.to_owned()))) + Ok(HeaderField::Signature(sig.to_owned())) } - _ => (0, Err(UnmarshalError::WrongSignature)), + _ => Err(UnmarshalError::WrongSignature), }, 9 => match sig { signature::Type::Base(signature::Base::Uint32) => { - let (b, fds) = parse_u32(&buf[offset..], header.byteorder)?; - (b, Ok(HeaderField::UnixFds(fds))) + Ok(HeaderField::UnixFds(cursor.read_u32(header.byteorder)?)) } - _ => (0, Err(UnmarshalError::WrongSignature)), + _ => Err(UnmarshalError::WrongSignature), }, - 0 => (0, Err(UnmarshalError::InvalidHeaderField)), - _ => (0, Err(UnmarshalError::UnknownHeaderField)), - }; - let sum_bytes_used = padding + typ_bytes_used + sig_bytes_used + field_bytes_used; - match field { - Ok(field) => Ok((sum_bytes_used, field)), - Err(e) => Err(e), + 0 => Err(UnmarshalError::InvalidHeaderField), + _ => Err(UnmarshalError::UnknownHeaderField), } } diff --git a/rustbus/src/wire/unmarshal/iter.rs b/rustbus/src/wire/unmarshal/iter.rs index a9d35e1..d85612b 100644 --- a/rustbus/src/wire/unmarshal/iter.rs +++ b/rustbus/src/wire/unmarshal/iter.rs @@ -5,7 +5,7 @@ use crate::params; use crate::signature; use crate::wire::errors::UnmarshalError; use crate::wire::unmarshal::base::unmarshal_base; -use crate::wire::unmarshal::UnmarshalContext; +use crate::wire::unmarshal_context::UnmarshalContext; use crate::ByteOrder; pub struct MessageIter<'a> { @@ -55,17 +55,17 @@ impl<'a> MessageIter<'a> { if self.counter >= self.sig.len() { None } else { - let ctx = &mut crate::wire::unmarshal::UnmarshalContext { - buf: self.source, - fds: &[], - byteorder: self.byteorder, - offset: *self.current_offset, - }; - let (bytes, val) = match T::unmarshal(ctx) { + let ctx = &mut crate::wire::unmarshal::UnmarshalContext::new( + &[], + self.byteorder, + self.source, + *self.current_offset, + ); + let val = match T::unmarshal(ctx) { Err(e) => return Some(Err(e)), Ok(t) => t, }; - *self.current_offset += bytes; + *self.current_offset = self.source.len() - ctx.remainder().len(); Some(Ok(val)) } } @@ -143,16 +143,12 @@ impl<'a, 'parent> DictEntryIter<'a> { let iter = if self.counter == 0 { // read the key value - let mut ctx = UnmarshalContext { - byteorder: self.byteorder, - buf: self.source, - offset: *self.current_offset, - fds: &Vec::new(), - }; + let mut ctx = + UnmarshalContext::new(&[], self.byteorder, self.source, *self.current_offset); match unmarshal_base(self.key_sig, &mut ctx) { - Ok((bytes, param)) => { - *self.current_offset += bytes; + Ok(param) => { + *self.current_offset = self.source.len() - ctx.remainder().len(); Some(Ok(ParamIter::Base(param))) } Err(e) => Some(Err(e)), @@ -241,15 +237,10 @@ impl<'a, 'parent> ParamIter<'a> { match new_sig { signature::Type::Base(b) => { - let mut ctx = UnmarshalContext { - byteorder, - buf: source, - offset: *offset, - fds: &Vec::new(), - }; + let mut ctx = UnmarshalContext::new(&[], byteorder, source, *offset); match unmarshal_base(*b, &mut ctx) { - Ok((bytes, param)) => { - *offset += bytes; + Ok(param) => { + *offset = source.len() - ctx.remainder().len(); Some(Ok(ParamIter::Base(param))) } Err(e) => Some(Err(e)), @@ -334,8 +325,7 @@ fn make_new_array_iter<'a>( el_sig: &'a signature::Type, ) -> Result, UnmarshalError> { // get child array size - let (bytes, array_len_bytes) = crate::wire::util::parse_u32(&source[*offset..], byteorder)?; - debug_assert_eq!(bytes, 4); + let array_len_bytes = crate::wire::util::parse_u32(&source[*offset..], byteorder)?; // move offset *offset += 4; @@ -386,8 +376,7 @@ fn make_new_dict_iter<'a>( val_sig: &'a signature::Type, ) -> Result, UnmarshalError> { // get child array size - let (bytes, array_len_bytes) = crate::wire::util::parse_u32(&source[*offset..], byteorder)?; - debug_assert_eq!(bytes, 4); + let array_len_bytes = crate::wire::util::parse_u32(&source[*offset..], byteorder)?; // move offset *offset += 4; diff --git a/rustbus/src/wire/unmarshal/param/base.rs b/rustbus/src/wire/unmarshal/param/base.rs index 35597f4..7a4fe04 100644 --- a/rustbus/src/wire/unmarshal/param/base.rs +++ b/rustbus/src/wire/unmarshal/param/base.rs @@ -3,92 +3,71 @@ use crate::params; use crate::signature; use crate::wire::errors::UnmarshalError; -use crate::wire::unmarshal::UnmarshalContext; use crate::wire::unmarshal::UnmarshalResult; -use crate::wire::util::*; +use crate::wire::unmarshal_context::UnmarshalContext; -pub fn unmarshal_base<'a>( +pub fn unmarshal_base( typ: signature::Base, ctx: &mut UnmarshalContext, -) -> UnmarshalResult> { - let padding = ctx.align_to(typ.get_alignment())?; - - let (bytes, param) = match typ { +) -> UnmarshalResult> { + match typ { signature::Base::Byte => { - if ctx.offset >= ctx.buf.len() { - return Err(UnmarshalError::NotEnoughBytes); - } - Ok((1, params::Base::Byte(ctx.buf[ctx.offset]))) + let val = ctx.read_u8()?; + Ok(params::Base::Byte(val)) } signature::Base::Uint16 => { - let slice = &ctx.buf[ctx.offset..]; - let (bytes, val) = parse_u16(slice, ctx.byteorder)?; - Ok((bytes, params::Base::Uint16(val))) + let val = ctx.read_u16()?; + Ok(params::Base::Uint16(val)) } signature::Base::Int16 => { - let slice = &ctx.buf[ctx.offset..]; - let (bytes, val) = parse_u16(slice, ctx.byteorder)?; - Ok((bytes, params::Base::Int16(val as i16))) + let val = ctx.read_i16()?; + Ok(params::Base::Int16(val)) } signature::Base::Uint32 => { - let slice = &ctx.buf[ctx.offset..]; - let (bytes, val) = parse_u32(slice, ctx.byteorder)?; - Ok((bytes, params::Base::Uint32(val))) + let val = ctx.read_u32()?; + Ok(params::Base::Uint32(val)) } signature::Base::UnixFd => { - let slice = &ctx.buf[ctx.offset..]; - let (bytes, idx) = parse_u32(slice, ctx.byteorder)?; - if ctx.fds.len() <= idx as usize { - Err(UnmarshalError::BadFdIndex(idx as usize)) - } else { - let val = &ctx.fds[idx as usize]; - Ok((bytes, params::Base::UnixFd(val.clone()))) - } + let val = ctx.read_unixfd()?; + Ok(params::Base::UnixFd(val)) } signature::Base::Int32 => { - let slice = &ctx.buf[ctx.offset..]; - let (bytes, val) = parse_u32(slice, ctx.byteorder)?; - Ok((bytes, params::Base::Int32(val as i32))) + let val = ctx.read_i32()?; + Ok(params::Base::Int32(val)) } signature::Base::Uint64 => { - let slice = &ctx.buf[ctx.offset..]; - let (bytes, val) = parse_u64(slice, ctx.byteorder)?; - Ok((bytes, params::Base::Uint64(val))) + let val = ctx.read_u64()?; + Ok(params::Base::Uint64(val)) } signature::Base::Int64 => { - let slice = &ctx.buf[ctx.offset..]; - let (bytes, val) = parse_u64(slice, ctx.byteorder)?; - Ok((bytes, params::Base::Int64(val as i64))) + let val = ctx.read_i64()?; + Ok(params::Base::Int64(val)) } signature::Base::Double => { - let slice = &ctx.buf[ctx.offset..]; - let (bytes, val) = parse_u64(slice, ctx.byteorder)?; - Ok((bytes, params::Base::Double(val))) + let val = ctx.read_u64()?; + Ok(params::Base::Double(val)) } signature::Base::Boolean => { - let slice = &ctx.buf[ctx.offset..]; - let (bytes, val) = parse_u32(slice, ctx.byteorder)?; + let val = ctx.read_u32()?; match val { - 0 => Ok((bytes, params::Base::Boolean(false))), - 1 => Ok((bytes, params::Base::Boolean(true))), + 0 => Ok(params::Base::Boolean(false)), + 1 => Ok(params::Base::Boolean(true)), _ => Err(UnmarshalError::InvalidBoolean), } } signature::Base::String => { - let (bytes, string) = unmarshal_string(ctx.byteorder, &ctx.buf[ctx.offset..])?; - Ok((bytes, params::Base::String(string))) + let string = ctx.read_str()?; + Ok(params::Base::String(string.into())) } signature::Base::ObjectPath => { - let (bytes, string) = unmarshal_string(ctx.byteorder, &ctx.buf[ctx.offset..])?; - crate::params::validate_object_path(&string)?; - Ok((bytes, params::Base::ObjectPath(string))) + let string = ctx.read_str()?; + crate::params::validate_object_path(string)?; + Ok(params::Base::ObjectPath(string.into())) } signature::Base::Signature => { - let (bytes, string) = unmarshal_signature(&ctx.buf[ctx.offset..])?; + let string = ctx.read_signature()?; crate::params::validate_signature(string)?; - Ok((bytes, params::Base::Signature(string.to_owned()))) + Ok(params::Base::Signature(string.to_owned())) } - }?; - ctx.offset += bytes; - Ok((padding + bytes, param)) + } } diff --git a/rustbus/src/wire/unmarshal/param/container.rs b/rustbus/src/wire/unmarshal/param/container.rs index bf21584..c3f951e 100644 --- a/rustbus/src/wire/unmarshal/param/container.rs +++ b/rustbus/src/wire/unmarshal/param/container.rs @@ -4,31 +4,30 @@ use crate::params; use crate::signature; use crate::wire::errors::UnmarshalError; use crate::wire::unmarshal::base::unmarshal_base; -use crate::wire::unmarshal::UnmarshalContext; use crate::wire::unmarshal::UnmarshalResult; -use crate::wire::util::*; +use crate::wire::unmarshal_context::UnmarshalContext; -pub fn unmarshal_with_sig<'a, 'e>( +pub fn unmarshal_with_sig( sig: &signature::Type, ctx: &mut UnmarshalContext, -) -> UnmarshalResult> { - let (bytes, param) = match &sig { +) -> UnmarshalResult> { + let param = match &sig { signature::Type::Base(base) => { - let (bytes, base) = unmarshal_base(*base, ctx)?; - (bytes, params::Param::Base(base)) + let base = unmarshal_base(*base, ctx)?; + params::Param::Base(base) } signature::Type::Container(cont) => { - let (bytes, cont) = unmarshal_container(cont, ctx)?; - (bytes, params::Param::Container(cont)) + let cont = unmarshal_container(cont, ctx)?; + params::Param::Container(cont) } }; - Ok((bytes, param)) + Ok(param) } -pub fn unmarshal_variant<'a, 'e>( +pub fn unmarshal_variant( ctx: &mut UnmarshalContext, -) -> UnmarshalResult> { - let (sig_bytes_used, sig_str) = unmarshal_signature(&ctx.buf[ctx.offset..])?; +) -> UnmarshalResult> { + let sig_str = ctx.read_signature()?; let mut sig = signature::Type::parse_description(sig_str)?; if sig.len() != 1 { @@ -36,92 +35,55 @@ pub fn unmarshal_variant<'a, 'e>( return Err(UnmarshalError::WrongSignature); } let sig = sig.remove(0); - ctx.offset += sig_bytes_used; - let (param_bytes_used, param) = unmarshal_with_sig(&sig, ctx)?; - Ok(( - sig_bytes_used + param_bytes_used, - params::Variant { sig, value: param }, - )) + let param = unmarshal_with_sig(&sig, ctx)?; + Ok(params::Variant { sig, value: param }) } -pub fn unmarshal_container<'a, 'e>( +pub fn unmarshal_container( typ: &signature::Container, ctx: &mut UnmarshalContext, -) -> UnmarshalResult> { +) -> UnmarshalResult> { let param = match typ { signature::Container::Array(elem_sig) => { - let start_offset = ctx.offset; - ctx.align_to(4)?; - - let (_, bytes_in_array) = parse_u32(&ctx.buf[ctx.offset..], ctx.byteorder)?; - ctx.offset += 4; + let bytes_in_array = ctx.read_u32()? as usize; ctx.align_to(elem_sig.get_alignment())?; let mut elements = Vec::new(); - let mut bytes_used_counter = 0; - while bytes_used_counter < bytes_in_array as usize { - if ctx.offset >= ctx.buf.len() { - return Err(UnmarshalError::NotEnoughBytes); - } - - let (bytes_used, element) = unmarshal_with_sig(elem_sig, ctx)?; + let mut ctx = ctx.sub_context(bytes_in_array)?; + while !ctx.remainder().is_empty() { + let element = unmarshal_with_sig(elem_sig, &mut ctx)?; elements.push(element); - bytes_used_counter += bytes_used; } - let total_bytes_used = ctx.offset - start_offset; - ( - total_bytes_used, - params::Container::Array(params::Array { - element_sig: elem_sig.as_ref().clone(), - values: elements, - }), - ) + params::Container::Array(params::Array { + element_sig: elem_sig.as_ref().clone(), + values: elements, + }) } signature::Container::Dict(key_sig, val_sig) => { - let start_offset = ctx.offset; - - ctx.align_to(4)?; - let (_, bytes_in_dict) = parse_u32(&ctx.buf[ctx.offset..], ctx.byteorder)?; - ctx.offset += 4; + let bytes_in_dict = ctx.read_u32()? as usize; ctx.align_to(8)?; let mut elements = std::collections::HashMap::new(); - let mut bytes_used_counter = 0; - while bytes_used_counter < bytes_in_dict as usize { - if ctx.offset >= ctx.buf.len() { - return Err(UnmarshalError::NotEnoughBytes); - } - - let element_padding = align_offset(8, ctx.buf, ctx.offset)?; - bytes_used_counter += element_padding; - ctx.offset += element_padding; - - let (key_bytes, key) = unmarshal_base(*key_sig, ctx)?; - bytes_used_counter += key_bytes; - - let (val_bytes, val) = unmarshal_with_sig(val_sig, ctx)?; - bytes_used_counter += val_bytes; + let mut ctx = ctx.sub_context(bytes_in_dict)?; + while !ctx.remainder().is_empty() { + ctx.align_to(8)?; + let key = unmarshal_base(*key_sig, &mut ctx)?; + let val = unmarshal_with_sig(val_sig, &mut ctx)?; elements.insert(key, val); } - let total_bytes_used = ctx.offset - start_offset; - ( - total_bytes_used, - params::Container::Dict(params::Dict { - key_sig: *key_sig, - value_sig: val_sig.as_ref().clone(), - map: elements, - }), - ) + params::Container::Dict(params::Dict { + key_sig: *key_sig, + value_sig: val_sig.as_ref().clone(), + map: elements, + }) } signature::Container::Struct(sigs) => { - let start_offset = ctx.offset; - ctx.align_to(8)?; let mut fields = Vec::new(); @@ -130,15 +92,14 @@ pub fn unmarshal_container<'a, 'e>( } for field_sig in sigs.as_ref() { - let (_, field) = unmarshal_with_sig(field_sig, ctx)?; + let field = unmarshal_with_sig(field_sig, ctx)?; fields.push(field); } - let total_bytes_used = ctx.offset - start_offset; - (total_bytes_used, params::Container::Struct(fields)) + params::Container::Struct(fields) } signature::Container::Variant => { - let (bytes_used, variant) = unmarshal_variant(ctx)?; - (bytes_used, params::Container::Variant(Box::new(variant))) + let variant = unmarshal_variant(ctx)?; + params::Container::Variant(Box::new(variant)) } }; Ok(param) diff --git a/rustbus/src/wire/unmarshal/traits.rs b/rustbus/src/wire/unmarshal/traits.rs index 4cc3c62..8076d65 100644 --- a/rustbus/src/wire/unmarshal/traits.rs +++ b/rustbus/src/wire/unmarshal/traits.rs @@ -2,7 +2,7 @@ use crate::wire::marshal::traits::Signature; use crate::wire::unmarshal; -use crate::wire::unmarshal::UnmarshalContext; +use crate::wire::unmarshal_context::UnmarshalContext; // these contain the implementations mod base; @@ -31,7 +31,7 @@ pub use container::*; /// use rustbus::wire::marshal::traits::Signature; /// use rustbus::signature; /// use rustbus::wire::unmarshal; -/// use rustbus::wire::unmarshal::UnmarshalContext; +/// use rustbus::wire::unmarshal_context::UnmarshalContext; /// use rustbus::wire::unmarshal::traits::Unmarshal; /// use rustbus::wire::unmarshal::UnmarshalResult; /// use rustbus::wire::marshal::traits::SignatureBuffer; @@ -58,20 +58,17 @@ pub use container::*; /// /// impl<'buf, 'fds> Unmarshal<'buf, 'fds> for MyStruct { /// fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { -/// let start_offset = ctx.offset; /// // check that we are aligned properly! /// // This is necessary at the start of each struct! They need to be aligned to 8 bytes! -/// let padding = ctx.align_to(Self::alignment())?; +/// ctx.align_to(Self::alignment())?; /// /// // decode some stuff and adjust offset -/// let (bytes, mycoolint) = u64::unmarshal(ctx)?; +/// let mycoolint = u64::unmarshal(ctx)?; /// /// // some more decoding if the struct had more fields /// // .... /// -/// //then report the total bytes used by unmarshalling this type (INCLUDING padding at the beginning!): -/// let total_bytes = ctx.offset - start_offset; -/// Ok((total_bytes, MyStruct{mycoolint})) +/// Ok(MyStruct{mycoolint}) /// } /// } /// ``` @@ -91,7 +88,7 @@ pub use container::*; /// ```rust /// use rustbus::Unmarshal; /// use rustbus::wire::unmarshal::UnmarshalResult; -/// use rustbus::wire::unmarshal::UnmarshalContext; +/// use rustbus::wire::unmarshal_context::UnmarshalContext; /// use rustbus::wire::marshal::traits::Signature; /// use rustbus::wire::marshal::traits::SignatureBuffer; /// use rustbus::signature; @@ -119,17 +116,14 @@ pub use container::*; /// /// impl<'buf, 'fds> Unmarshal<'buf, 'fds> for MyStruct { /// fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> UnmarshalResult { -/// let start_offset = ctx.offset; /// // check that we are aligned properly /// let padding = ctx.align_to(Self::alignment())?; /// /// // get the slice that contains marshalled data, and unmarshal it directly here! -/// let (bytes, raw_data) = <&[u8] as Unmarshal>::unmarshal(ctx)?; +/// let raw_data = <&[u8] as Unmarshal>::unmarshal(ctx)?; /// let unmarshalled_stuff = unmarshal_stuff_from_raw(&raw_data); /// -/// //then report the total bytes used by unmarshalling this type (INCLUDING padding at the beginning!): -/// let total_bytes = ctx.offset - start_offset; -/// Ok((total_bytes, MyStruct{mycoolint: unmarshalled_stuff})) +/// Ok(MyStruct{mycoolint: unmarshalled_stuff}) /// } /// } /// ``` @@ -146,15 +140,19 @@ pub fn unmarshal<'buf, 'fds, T: Unmarshal<'buf, 'fds>>( #[cfg(test)] mod test { + use std::fmt::Debug; + use super::unmarshal; use super::Unmarshal; use super::UnmarshalContext; use super::Variant; use crate::wire::marshal::MarshalContext; + use crate::wire::UnixFd; use crate::ByteOrder; use crate::Marshal; use crate::Signature; + // TODO this is more of a doc test? #[test] fn test_generic_unmarshal() { let mut fds = Vec::new(); @@ -168,85 +166,88 @@ mod test { // annotate the receiver with a type &str to unmarshal a &str "ABCD".marshal(ctx).unwrap(); - let _s: &str = unmarshal(&mut UnmarshalContext { - buf: ctx.buf, - byteorder: ctx.byteorder, - fds: ctx.fds, - offset: 0, - }) - .unwrap() - .1; + let _s: &str = unmarshal(&mut UnmarshalContext::new( + ctx.fds, + ctx.byteorder, + ctx.buf, + 0, + )) + .unwrap(); // annotate the receiver with a type bool to unmarshal a bool ctx.buf.clear(); true.marshal(ctx).unwrap(); - let _b: bool = unmarshal(&mut UnmarshalContext { - buf: ctx.buf, - byteorder: ctx.byteorder, - fds: ctx.fds, - offset: 0, - }) - .unwrap() - .1; + let _b: bool = unmarshal(&mut UnmarshalContext::new( + ctx.fds, + ctx.byteorder, + ctx.buf, + 0, + )) + .unwrap(); // can also use turbofish syntax ctx.buf.clear(); 0i32.marshal(ctx).unwrap(); - let _i = unmarshal::(&mut UnmarshalContext { - buf: ctx.buf, - byteorder: ctx.byteorder, - fds: ctx.fds, - offset: 0, - }) - .unwrap() - .1; + let _i = unmarshal::(&mut UnmarshalContext::new( + ctx.fds, + ctx.byteorder, + ctx.buf, + 0, + )) + .unwrap(); // No type info on let arg = unmarshal(...) is needed if it can be derived by other means ctx.buf.clear(); fn x(_arg: (i32, i32, &str)) {} (0, 0, "ABCD").marshal(ctx).unwrap(); - let arg = unmarshal(&mut UnmarshalContext { - buf: ctx.buf, - byteorder: ctx.byteorder, - fds: ctx.fds, - offset: 0, - }) - .unwrap() - .1; + let arg = unmarshal(&mut UnmarshalContext::new( + ctx.fds, + ctx.byteorder, + ctx.buf, + 0, + )) + .unwrap(); x(arg); } + fn roundtrip<'a, T>(original: T, fds: &'a mut Vec, buf: &'a mut Vec) + where + T: Unmarshal<'a, 'a>, + T: Marshal, + T: Debug, + T: Eq, + { + fds.clear(); + buf.clear(); + let byteorder = ByteOrder::LittleEndian; + + original + .marshal(&mut MarshalContext { + buf, + fds, + byteorder, + }) + .unwrap(); + + let unmarshalled = + T::unmarshal(&mut UnmarshalContext::new(fds, byteorder, buf, 0)).unwrap(); + eprintln!("{fds:?}"); + assert_eq!(original, unmarshalled); + } + #[test] fn test_unmarshal_byte_array() { - use crate::wire::marshal::MarshalContext; - use crate::Marshal; + let mut fds = vec![]; + let mut buf = vec![]; let mut orig = vec![]; for x in 0..1024 { orig.push((x % 255) as u8); } + roundtrip(orig, &mut fds, &mut buf); - let mut fds = Vec::new(); - let mut buf = Vec::new(); - let mut ctx = MarshalContext { - buf: &mut buf, - fds: &mut fds, - byteorder: ByteOrder::LittleEndian, - }; - let ctx = &mut ctx; - - orig.marshal(ctx).unwrap(); - assert_eq!(&ctx.buf[..4], &[0, 4, 0, 0]); - assert_eq!(ctx.buf.len(), 1028); - let (bytes, unorig) = <&[u8] as Unmarshal>::unmarshal(&mut UnmarshalContext { - buf: ctx.buf, - fds: ctx.fds, - byteorder: ctx.byteorder, - offset: 0, - }) - .unwrap(); - assert_eq!(bytes, orig.len() + 4); - assert_eq!(orig, unorig); + assert_eq!(&buf[..4], &[0, 4, 0, 0]); + assert_eq!(buf.len(), 1028); // even slices of slices of u8 work efficiently let mut orig1 = vec![]; @@ -259,112 +260,61 @@ mod test { } let orig = vec![orig1.as_slice(), orig2.as_slice()]; - - ctx.buf.clear(); - orig.marshal(ctx).unwrap(); - - // unorig[x] points into the appropriate region in buf, and unorigs lifetime is bound to buf - let (_bytes, unorig) = as Unmarshal>::unmarshal(&mut UnmarshalContext { - buf: ctx.buf, - fds: ctx.fds, - byteorder: ctx.byteorder, - offset: 0, - }) - .unwrap(); - assert_eq!(orig, unorig); + roundtrip(orig, &mut fds, &mut buf); } #[test] fn test_unmarshal_traits() { - use crate::wire::marshal::MarshalContext; - use crate::Marshal; - - let mut fds = Vec::new(); - let mut buf = Vec::new(); - let mut ctx = MarshalContext { - buf: &mut buf, - fds: &mut fds, - byteorder: ByteOrder::LittleEndian, - }; - let ctx = &mut ctx; + let mut fds = vec![]; + let mut buf = vec![]; - let original = &["a", "b"]; - original.marshal(ctx).unwrap(); - - let (_, v) = Vec::<&str>::unmarshal(&mut UnmarshalContext { - buf: ctx.buf, - fds: ctx.fds, - byteorder: ctx.byteorder, - offset: 0, - }) - .unwrap(); - - assert_eq!(original, v.as_slice()); - - ctx.buf.clear(); + let original = vec!["a", "b"]; + roundtrip(original, &mut fds, &mut buf); let mut original = std::collections::HashMap::new(); original.insert(0u64, "abc"); original.insert(1u64, "dce"); original.insert(2u64, "fgh"); + roundtrip(original, &mut fds, &mut buf); - original.marshal(ctx).unwrap(); - - let (_, map) = std::collections::HashMap::::unmarshal(&mut UnmarshalContext { - buf: ctx.buf, - fds: ctx.fds, - byteorder: ctx.byteorder, - offset: 0, - }) - .unwrap(); - assert_eq!(original, map); + let mut original = std::collections::HashMap::new(); + original.insert(0u8, "abc"); + original.insert(1u8, "dce"); + original.insert(2u8, "fgh"); + roundtrip(original, &mut fds, &mut buf); - ctx.buf.clear(); + let mut original = std::collections::HashMap::new(); + original.insert(0i16, "abc"); + original.insert(1i16, "dce"); + original.insert(2i16, "fgh"); + roundtrip(original, &mut fds, &mut buf); let orig = (30u8, true, 100u8, -123i32); - orig.marshal(ctx).unwrap(); - type ST = (u8, bool, u8, i32); - let s = ST::unmarshal(&mut UnmarshalContext { - buf: ctx.buf, - fds: ctx.fds, - byteorder: ctx.byteorder, - offset: 0, - }) - .unwrap() - .1; - assert_eq!(orig, s); - - ctx.buf.clear(); + roundtrip(orig, &mut fds, &mut buf); - use crate::wire::UnixFd; use crate::wire::{ObjectPath, SignatureWrapper}; - let orig_fd = UnixFd::new(nix::unistd::dup(1).unwrap()); let orig = ( + 1u8, ObjectPath::new("/a/b/c").unwrap(), SignatureWrapper::new("ss(aiau)").unwrap(), - &orig_fd, + 0u32, ); - orig.marshal(ctx).unwrap(); + roundtrip(orig, &mut fds, &mut buf); assert_eq!( - ctx.buf, + &buf, &[ - 6, 0, 0, 0, b'/', b'a', b'/', b'b', b'/', b'c', 0, 8, b's', b's', b'(', b'a', b'i', - b'a', b'u', b')', 0, 0, 0, 0, 0, 0, 0, 0 + 1, 0, 0, 0, 6, 0, 0, 0, b'/', b'a', b'/', b'b', b'/', b'c', 0, 8, b's', b's', b'(', + b'a', b'i', b'a', b'u', b')', 0, 0, 0, 0, 0, 0, 0, 0 ] ); - let (_, (p, s, _fd)) = - <(ObjectPath, SignatureWrapper<&str>, UnixFd) as Unmarshal>::unmarshal( - &mut UnmarshalContext { - buf: ctx.buf, - fds: ctx.fds, - byteorder: ctx.byteorder, - offset: 0, - }, - ) - .unwrap(); - assert_eq!(p.as_ref(), "/a/b/c"); - assert_eq!(s.as_ref(), "ss(aiau)"); + let orig = ( + 1u8, + ObjectPath::new("/a/b/c").unwrap(), + 1u8, + 0xFFFFFFFFFFFFFFFFu64, + ); + roundtrip(orig, &mut fds, &mut buf); } #[test] @@ -513,5 +463,27 @@ mod test { var_map["8"].get().unwrap() ); assert!(var_map["9"].get::().unwrap()); + + let mut body = MarshalledMessageBody::new(); + let orig = (10u8, 100u32, 20u8, 200u64); + body.push_variant(&orig).unwrap(); + let unmarshalled = body + .parser() + .get::() + .unwrap() + .get::<(u8, u32, u8, u64)>() + .unwrap(); + assert_eq!(orig, unmarshalled); + + let mut body = MarshalledMessageBody::new(); + let orig = (10u8, 100u32, SignatureWrapper::new("").unwrap(), 200u64); + body.push_variant(&orig).unwrap(); + let unmarshalled = body + .parser() + .get::() + .unwrap() + .get::<(u8, u32, SignatureWrapper<&str>, u64)>() + .unwrap(); + assert_eq!(orig, unmarshalled); } } diff --git a/rustbus/src/wire/unmarshal/traits/base.rs b/rustbus/src/wire/unmarshal/traits/base.rs index 29b042a..470d57d 100644 --- a/rustbus/src/wire/unmarshal/traits/base.rs +++ b/rustbus/src/wire/unmarshal/traits/base.rs @@ -2,84 +2,54 @@ use crate::wire::errors::UnmarshalError; use crate::wire::unmarshal; -use crate::wire::unmarshal::UnmarshalContext; -use crate::wire::util; +use crate::wire::unmarshal_context::UnmarshalContext; use crate::wire::ObjectPath; use crate::wire::SignatureWrapper; -use crate::Signature; use crate::Unmarshal; impl<'buf, 'fds> Unmarshal<'buf, 'fds> for u64 { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let padding = ctx.align_to(Self::alignment())?; - let (bytes, val) = util::parse_u64(&ctx.buf[ctx.offset..], ctx.byteorder)?; - ctx.offset += bytes; - Ok((bytes + padding, val)) + ctx.read_u64() } } impl<'buf, 'fds> Unmarshal<'buf, 'fds> for u32 { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let padding = ctx.align_to(Self::alignment())?; - let (bytes, val) = util::parse_u32(&ctx.buf[ctx.offset..], ctx.byteorder)?; - ctx.offset += bytes; - Ok((bytes + padding, val)) + ctx.read_u32() } } impl<'buf, 'fds> Unmarshal<'buf, 'fds> for u16 { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let padding = ctx.align_to(Self::alignment())?; - let (bytes, val) = util::parse_u16(&ctx.buf[ctx.offset..], ctx.byteorder)?; - ctx.offset += bytes; - Ok((bytes + padding, val)) + ctx.read_u16() } } impl<'buf, 'fds> Unmarshal<'buf, 'fds> for i64 { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let padding = ctx.align_to(Self::alignment())?; - let (bytes, val) = util::parse_u64(&ctx.buf[ctx.offset..], ctx.byteorder) - .map(|(bytes, val)| (bytes, val as i64))?; - ctx.offset += bytes; - Ok((bytes + padding, val)) + ctx.read_i64() } } impl<'buf, 'fds> Unmarshal<'buf, 'fds> for i32 { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let padding = ctx.align_to(Self::alignment())?; - let (bytes, val) = util::parse_u32(&ctx.buf[ctx.offset..], ctx.byteorder) - .map(|(bytes, val)| (bytes, val as i32))?; - ctx.offset += bytes; - Ok((bytes + padding, val)) + ctx.read_i32() } } impl<'buf, 'fds> Unmarshal<'buf, 'fds> for i16 { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let padding = ctx.align_to(Self::alignment())?; - let (bytes, val) = util::parse_u16(&ctx.buf[ctx.offset..], ctx.byteorder) - .map(|(bytes, val)| (bytes, val as i16))?; - ctx.offset += bytes; - Ok((bytes + padding, val)) + ctx.read_i16() } } impl<'buf, 'fds> Unmarshal<'buf, 'fds> for u8 { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - if ctx.offset >= ctx.buf.len() { - return Err(UnmarshalError::NotEnoughBytes); - } - let val = ctx.buf[ctx.offset]; - ctx.offset += 1; - Ok((1, val)) + ctx.read_u8() } } impl<'buf, 'fds> Unmarshal<'buf, 'fds> for bool { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let padding = ctx.align_to(Self::alignment())?; - let (bytes, val) = util::parse_u32(&ctx.buf[ctx.offset..], ctx.byteorder)?; - ctx.offset += bytes; + let val = ctx.read_u32()?; match val { - 0 => Ok((bytes + padding, false)), - 1 => Ok((bytes + padding, true)), + 0 => Ok(false), + 1 => Ok(true), _ => Err(UnmarshalError::InvalidBoolean), } } @@ -87,28 +57,20 @@ impl<'buf, 'fds> Unmarshal<'buf, 'fds> for bool { impl<'buf, 'fds> Unmarshal<'buf, 'fds> for f64 { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let padding = ctx.align_to(Self::alignment())?; - let (bytes, val) = util::parse_u64(&ctx.buf[ctx.offset..], ctx.byteorder)?; - ctx.offset += bytes; - Ok((bytes + padding, f64::from_bits(val))) + let val = ctx.read_u64()?; + Ok(f64::from_bits(val)) } } -impl<'buf, 'fds> Unmarshal<'buf, 'fds> for &'buf str { - fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let padding = ctx.align_to(Self::alignment())?; - let (bytes, val) = util::unmarshal_str(ctx.byteorder, &ctx.buf[ctx.offset..])?; - ctx.offset += bytes; - Ok((bytes + padding, val)) +impl<'buf> Unmarshal<'buf, '_> for &'buf str { + fn unmarshal(ctx: &mut UnmarshalContext<'_, 'buf>) -> unmarshal::UnmarshalResult { + ctx.read_str() } } impl<'buf, 'fds> Unmarshal<'buf, 'fds> for String { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let padding = ctx.align_to(Self::alignment())?; - let (bytes, val) = util::unmarshal_string(ctx.byteorder, &ctx.buf[ctx.offset..])?; - ctx.offset += bytes; - Ok((bytes + padding, val)) + ctx.read_str().map(|val| val.to_owned()) } } @@ -116,18 +78,16 @@ impl<'buf, 'fds, S: AsRef + From<&'buf str> + Unmarshal<'buf, 'fds>> Unmars for SignatureWrapper { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - // No alignment needed. Signature is aligned to 1 - let (bytes, val) = util::unmarshal_signature(&ctx.buf[ctx.offset..])?; - ctx.offset += bytes; + let val = ctx.read_signature()?; let sig = SignatureWrapper::new(val.into())?; - Ok((bytes, sig)) + Ok(sig) } } impl<'buf, 'fds, S: AsRef + Unmarshal<'buf, 'fds>> Unmarshal<'buf, 'fds> for ObjectPath { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let (bytes, val) = ::unmarshal(ctx)?; + let val = ::unmarshal(ctx)?; let path = ObjectPath::new(val)?; - Ok((bytes, path)) + Ok(path) } } diff --git a/rustbus/src/wire/unmarshal/traits/container.rs b/rustbus/src/wire/unmarshal/traits/container.rs index 8bd5495..eb90b58 100644 --- a/rustbus/src/wire/unmarshal/traits/container.rs +++ b/rustbus/src/wire/unmarshal/traits/container.rs @@ -4,9 +4,7 @@ use crate::signature; use crate::wire::errors::UnmarshalError; use crate::wire::marshal::traits::SignatureBuffer; use crate::wire::unmarshal; -use crate::wire::unmarshal::UnmarshalContext; -use crate::wire::util; -use crate::ByteOrder; +use crate::wire::unmarshal_context::UnmarshalContext; use crate::Signature; use crate::Unmarshal; use std::borrow::Cow; @@ -16,9 +14,9 @@ where E1: Unmarshal<'buf, 'fds> + Sized, { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let padding = ctx.align_to(8)?; - let (bytes, val1) = E1::unmarshal(ctx)?; - Ok((bytes + padding, (val1,))) + ctx.align_to(8)?; + let val1 = E1::unmarshal(ctx)?; + Ok((val1,)) } } @@ -28,15 +26,13 @@ where E2: Unmarshal<'buf, 'fds> + Sized, { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let start_offset = ctx.offset; ctx.align_to(8)?; - let (_bytes, val1) = E1::unmarshal(ctx)?; + let val1 = E1::unmarshal(ctx)?; ctx.align_to(E2::alignment())?; - let (_bytes, val2) = E2::unmarshal(ctx)?; + let val2 = E2::unmarshal(ctx)?; - let total_bytes = ctx.offset - start_offset; - Ok((total_bytes, (val1, val2))) + Ok((val1, val2)) } } @@ -47,19 +43,16 @@ where E3: Unmarshal<'buf, 'fds> + Sized, { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let start_offset = ctx.offset; - ctx.align_to(8)?; - let (_bytes, val1) = E1::unmarshal(ctx)?; + let val1 = E1::unmarshal(ctx)?; ctx.align_to(E2::alignment())?; - let (_bytes, val2) = E2::unmarshal(ctx)?; + let val2 = E2::unmarshal(ctx)?; ctx.align_to(E3::alignment())?; - let (_bytes, val3) = E3::unmarshal(ctx)?; + let val3 = E3::unmarshal(ctx)?; - let total_bytes = ctx.offset - start_offset; - Ok((total_bytes, (val1, val2, val3))) + Ok((val1, val2, val3)) } } @@ -71,22 +64,19 @@ where E4: Unmarshal<'buf, 'fds> + Sized, { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let start_offset = ctx.offset; - ctx.align_to(8)?; - let (_bytes, val1) = E1::unmarshal(ctx)?; + let val1 = E1::unmarshal(ctx)?; ctx.align_to(E2::alignment())?; - let (_bytes, val2) = E2::unmarshal(ctx)?; + let val2 = E2::unmarshal(ctx)?; ctx.align_to(E3::alignment())?; - let (_bytes, val3) = E3::unmarshal(ctx)?; + let val3 = E3::unmarshal(ctx)?; ctx.align_to(E4::alignment())?; - let (_bytes, val4) = E4::unmarshal(ctx)?; + let val4 = E4::unmarshal(ctx)?; - let total_bytes = ctx.offset - start_offset; - Ok((total_bytes, (val1, val2, val3, val4))) + Ok((val1, val2, val3, val4)) } } @@ -126,18 +116,14 @@ impl Signature for Cow<'_, [E]> { <[E]>::has_sig(sig) } } + /// for byte arrays we can give an efficient method of decoding. This will bind the returned slice to the lifetime of the buffer. impl<'buf, 'fds> Unmarshal<'buf, 'fds> for &'buf [u8] { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let padding = ctx.align_to(Self::alignment())?; - let (_, bytes_in_array) = u32::unmarshal(ctx)?; + ctx.align_to(Self::alignment())?; + let elements = ctx.read_u8_slice()?; - let elements = &ctx.buf[ctx.offset..ctx.offset + bytes_in_array as usize]; - ctx.offset += bytes_in_array as usize; - - let total_bytes_used = padding + 4 + bytes_in_array as usize; - - Ok((total_bytes_used, elements)) + Ok(elements) } } @@ -147,10 +133,7 @@ unsafe fn unmarshal_slice<'a, 'buf, 'fds, E>( where E: Unmarshal<'buf, 'fds>, //+ 'fds + 'buf { - let start_offset = ctx.offset; - ctx.align_to(4)?; - let (_, bytes_in_array) = u32::unmarshal(ctx)?; - let bytes_in_array = bytes_in_array as usize; + let bytes_in_array = ctx.read_u32()? as usize; let alignment = E::alignment(); ctx.align_to(alignment)?; @@ -158,75 +141,57 @@ where if bytes_in_array % alignment != 0 { return Err(UnmarshalError::NotAllBytesUsed); } - // Start at offset - let start_slice = &ctx.buf[ctx.offset..]; - // Check that the buffer contains enough bytes - if bytes_in_array > start_slice.len() { - return Err(UnmarshalError::NotEnoughBytes); - } - // limit the source slice to assert that the memory access will be valid - let content_slice = &start_slice[..bytes_in_array]; + let content_slice = ctx.read_raw(bytes_in_array)?; // cast the slice from u8 to the target type let elem_cnt = bytes_in_array / alignment; let ptr = content_slice.as_ptr().cast::(); let slice = std::slice::from_raw_parts(ptr, elem_cnt); - ctx.offset += bytes_in_array; - Ok((ctx.offset - start_offset, slice)) + Ok(slice) } + impl<'buf, 'fds, E: Unmarshal<'buf, 'fds> + Clone> Unmarshal<'buf, 'fds> for Cow<'buf, [E]> { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { unsafe { if E::valid_slice(ctx.byteorder) { - let (used, src): (_, &[E]) = unmarshal_slice(ctx)?; + let src: &[E] = unmarshal_slice(ctx)?; // SAFETY: One of requirements is for valid_slice it is only valid for 'buf // Thus this lifetime cast is always valid let l_expand: &'buf [E] = std::mem::transmute(src); - return Ok((used, Cow::Borrowed(l_expand))); + return Ok(Cow::Borrowed(l_expand)); } } - Vec::unmarshal(ctx).map(|o| (o.0, Cow::Owned(o.1))) + Vec::unmarshal(ctx).map(Cow::Owned) } } + impl<'buf, 'fds, E: Unmarshal<'buf, 'fds>> Unmarshal<'buf, 'fds> for Vec { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { unsafe { if E::valid_slice(ctx.byteorder) { - let (used, src) = unmarshal_slice::(ctx)?; + let src = unmarshal_slice::(ctx)?; let mut ret = Vec::with_capacity(src.len()); let dst = ret.as_mut_ptr(); std::ptr::copy_nonoverlapping(src.as_ptr(), dst, src.len()); ret.set_len(src.len()); - return Ok((used, ret)); + return Ok(ret); } } - let start_offset = ctx.offset; ctx.align_to(4)?; - let (_, bytes_in_array) = u32::unmarshal(ctx)?; + let bytes_in_array = u32::unmarshal(ctx)? as usize; ctx.align_to(E::alignment())?; let mut elements = Vec::new(); - let mut bytes_used_counter = 0; - while bytes_used_counter < bytes_in_array as usize { - if ctx.offset >= ctx.buf.len() { - return Err(UnmarshalError::NotEnoughBytes); - } - - let elem_padding = util::align_offset(E::alignment(), ctx.buf, ctx.offset)?; - - bytes_used_counter += elem_padding; - ctx.offset += elem_padding; - - let (bytes_used, element) = E::unmarshal(ctx)?; + let mut ctx = ctx.sub_context(bytes_in_array)?; + while !ctx.remainder().is_empty() { + ctx.align_to(E::alignment())?; + let element = E::unmarshal(&mut ctx)?; elements.push(element); - bytes_used_counter += bytes_used; } - let total_bytes_used = ctx.offset - start_offset; - - Ok((total_bytes_used, elements)) + Ok(elements) } } @@ -234,51 +199,36 @@ impl<'buf, 'fds, K: Unmarshal<'buf, 'fds> + std::hash::Hash + Eq, V: Unmarshal<' Unmarshal<'buf, 'fds> for std::collections::HashMap { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let start_offset = ctx.offset; ctx.align_to(4)?; - let (_, bytes_in_array) = u32::unmarshal(ctx)?; + let bytes_in_array = u32::unmarshal(ctx)? as usize; // align even if no elements are present ctx.align_to(8)?; let mut map = std::collections::HashMap::new(); - let mut bytes_used_counter = 0; - while bytes_used_counter < bytes_in_array as usize { - if ctx.offset >= ctx.buf.len() { - return Err(UnmarshalError::NotEnoughBytes); - } - - let elem_padding = util::align_offset(8, ctx.buf, ctx.offset)?; - bytes_used_counter += elem_padding; - ctx.offset += elem_padding; + let mut ctx = ctx.sub_context(bytes_in_array)?; + while !ctx.remainder().is_empty() { + // Always align to 8 + ctx.align_to(8)?; + let key = K::unmarshal(&mut ctx)?; - let (key_bytes_used, key) = K::unmarshal(ctx)?; - bytes_used_counter += key_bytes_used; - - let val_padding = util::align_offset(V::alignment(), ctx.buf, ctx.offset)?; - bytes_used_counter += val_padding; - ctx.offset += val_padding; - - let (val_bytes_used, val) = V::unmarshal(ctx)?; - bytes_used_counter += val_bytes_used; + //Align to value + ctx.align_to(V::alignment())?; + let val = V::unmarshal(&mut ctx)?; map.insert(key, val); } - let total_bytes_used = ctx.offset - start_offset; - - Ok((total_bytes_used, map)) + Ok(map) } } #[derive(Debug)] pub struct Variant<'fds, 'buf> { pub(crate) sig: signature::Type, - pub(crate) byteorder: ByteOrder, - pub(crate) offset: usize, - pub(crate) buf: &'buf [u8], - pub(crate) fds: &'fds [crate::wire::UnixFd], + pub(crate) sub_ctx: UnmarshalContext<'fds, 'buf>, } + impl<'buf, 'fds> Variant<'fds, 'buf> { /// Get the [`Type`] of the value contained by the variant. /// @@ -294,15 +244,11 @@ impl<'buf, 'fds> Variant<'fds, 'buf> { if self.sig != T::signature() { return Err(UnmarshalError::WrongSignature); } - let mut ctx = UnmarshalContext { - byteorder: self.byteorder, - offset: self.offset, - buf: self.buf, - fds: self.fds, - }; - T::unmarshal(&mut ctx).map(|r| r.1) + let mut ctx = self.sub_ctx; + T::unmarshal(&mut ctx) } } + impl Signature for Variant<'_, '_> { fn signature() -> signature::Type { signature::Type::Container(signature::Container::Variant) @@ -318,15 +264,13 @@ impl Signature for Variant<'_, '_> { sig.starts_with('v') } } + impl<'buf, 'fds> Unmarshal<'buf, 'fds> for Variant<'fds, 'buf> { fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult { - let start_offset = ctx.offset; - let (sig_bytes, desc) = util::unmarshal_signature(&ctx.buf[ctx.offset..])?; - ctx.offset += sig_bytes; + let desc = ctx.read_signature()?; - let mut sigs = match signature::Type::parse_description(desc) { - Ok(sigs) => sigs, - Err(_) => return Err(UnmarshalError::WrongSignature), + let Ok(mut sigs) = signature::Type::parse_description(desc) else { + return Err(UnmarshalError::WrongSignature); }; if sigs.len() != 1 { return Err(UnmarshalError::WrongSignature); @@ -335,27 +279,75 @@ impl<'buf, 'fds> Unmarshal<'buf, 'fds> for Variant<'fds, 'buf> { ctx.align_to(sig.get_alignment())?; - let start_loc = ctx.offset; - - let val_bytes = crate::wire::validate_raw::validate_marshalled( - ctx.byteorder, - ctx.offset, - ctx.buf, - &sig, - ) - .map_err(|e| e.1)?; - ctx.offset += val_bytes; - - let total_bytes = ctx.offset - start_offset; - Ok(( - total_bytes, - Variant { - sig, - buf: &ctx.buf[..ctx.offset], - offset: start_loc, - byteorder: ctx.byteorder, - fds: ctx.fds, - }, - )) + let val_bytes = + crate::wire::validate_raw::validate_marshalled(ctx.byteorder, 0, ctx.remainder(), &sig) + .map_err(|e| e.1)?; + + Ok(Variant { + sig, + sub_ctx: ctx.sub_context(val_bytes)?, + }) + } +} + +#[cfg(test)] +mod tests { + use crate::{message_builder::MarshalledMessageBody, ByteOrder}; + use std::borrow::Cow; + + #[test] + fn variant_with_sig() { + let mut m = MarshalledMessageBody::new(); + m.push_param("test.interface").unwrap(); + m.push_param("test_property").unwrap(); + m.push_param(crate::wire::marshal::traits::Variant(42u8)) + .unwrap(); + + let mut parser = m.parser(); + assert_eq!(parser.get::<&str>().unwrap(), "test.interface"); + assert_eq!(parser.get::<&str>().unwrap(), "test_property"); + assert_eq!(parser.get_next_sig().unwrap(), "v"); + let variant = parser + .get::() + .unwrap(); + assert_eq!(variant.get::().unwrap(), 42); + } + + #[test] + fn array() { + let mut m = MarshalledMessageBody::new(); + m.push_param([0u8, 1, 2, 3, 4, 5]).unwrap(); // Array by value + m.push_param(0u8).unwrap(); + m.push_param(-10i16).unwrap(); + m.push_param(&[0u8, 1, 2, 3, 4, 5, 6]).unwrap(); // Array as ref + m.push_param(-2000i16).unwrap(); + m.push_param(&[0u8, 1, 2, 3, 4, 5, 6, 7][..]).unwrap(); // Slice + m.push_param([-100i16, -200, -300, -400, -500, -600]) + .unwrap(); // Array by value + + let mut parser = m.parser(); + assert!(parser.get::>().is_err()); + assert_eq!(parser.get::<&[u8]>().unwrap(), &[0, 1, 2, 3, 4, 5]); + assert_eq!(parser.get::().unwrap(), 0); + assert_eq!(parser.get::().unwrap(), -10); + assert_eq!(parser.get::<&[u8]>().unwrap(), &[0, 1, 2, 3, 4, 5, 6]); + assert_eq!(parser.get::().unwrap(), -2000); + assert_eq!(parser.get::<&[u8]>().unwrap(), &[0, 1, 2, 3, 4, 5, 6, 7]); + assert!(matches!( + parser.get::>().unwrap(), + Cow::Borrowed(&[-100i16, -200, -300, -400, -500, -600]) + )); + + let non_native_byteorder = match cfg!(target_endian = "little") { + true => ByteOrder::BigEndian, + false => ByteOrder::LittleEndian, + }; + let mut m = MarshalledMessageBody::with_byteorder(non_native_byteorder); + m.push_param([-100i16, -200, -300, -400, -500, -600]) + .unwrap(); + let mut parser = m.parser(); + let unmarshalled = parser.get::>().unwrap(); + assert!(matches!(unmarshalled, Cow::Owned(_))); + assert_eq!(unmarshalled, vec![-100i16, -200, -300, -400, -500, -600]) } } diff --git a/rustbus/src/wire/unmarshal_context.rs b/rustbus/src/wire/unmarshal_context.rs new file mode 100644 index 0000000..6718501 --- /dev/null +++ b/rustbus/src/wire/unmarshal_context.rs @@ -0,0 +1,215 @@ +use crate::ByteOrder; + +use super::{ + errors::UnmarshalError, + unmarshal::UnmarshalResult, + util::{parse_u16, parse_u32, parse_u64, unmarshal_signature, unmarshal_str}, + UnixFd, +}; + +#[derive(Debug, Clone, Copy)] +pub struct UnmarshalContext<'fds, 'buf> { + pub byteorder: ByteOrder, + fds: &'fds [crate::wire::UnixFd], + cursor: Cursor<'buf>, +} + +impl<'fds, 'buf> UnmarshalContext<'fds, 'buf> { + pub fn new( + fds: &'fds [crate::wire::UnixFd], + byteorder: ByteOrder, + buf: &'buf [u8], + offset: usize, + ) -> UnmarshalContext<'fds, 'buf> { + Self { + fds, + byteorder, + cursor: Cursor { buf, offset }, + } + } + + pub fn sub_context(&mut self, length: usize) -> UnmarshalResult> { + let region = self.read_raw(length)?; + Ok(UnmarshalContext::new(self.fds, self.byteorder, region, 0)) + } + + pub fn align_to(&mut self, alignment: usize) -> Result { + self.cursor.align_to(alignment) + } + + pub fn remainder(&self) -> &[u8] { + self.cursor.remainder() + } + + pub fn read_u8(&mut self) -> UnmarshalResult { + self.cursor.read_u8() + } + + pub fn read_i16(&mut self) -> UnmarshalResult { + self.cursor.read_i16(self.byteorder) + } + + pub fn read_u16(&mut self) -> UnmarshalResult { + self.cursor.read_u16(self.byteorder) + } + + pub fn read_i32(&mut self) -> UnmarshalResult { + self.cursor.read_i32(self.byteorder) + } + + pub fn read_u32(&mut self) -> UnmarshalResult { + self.cursor.read_u32(self.byteorder) + } + + pub fn read_unixfd(&mut self) -> UnmarshalResult { + let idx = self.cursor.read_u32(self.byteorder)?; + if self.fds.len() <= idx as usize { + Err(UnmarshalError::BadFdIndex(idx as usize)) + } else { + let val = &self.fds[idx as usize]; + Ok(val.clone()) + } + } + + pub fn read_i64(&mut self) -> UnmarshalResult { + self.cursor.read_i64(self.byteorder) + } + + pub fn read_u64(&mut self) -> UnmarshalResult { + self.cursor.read_u64(self.byteorder) + } + + pub fn read_str(&mut self) -> UnmarshalResult<&'buf str> { + self.cursor.read_str(self.byteorder) + } + + pub fn read_signature(&mut self) -> UnmarshalResult<&'buf str> { + self.cursor.read_signature() + } + + pub fn read_u8_slice(&mut self) -> UnmarshalResult<&'buf [u8]> { + self.cursor.read_u8_slice(self.byteorder) + } + + pub fn read_raw(&mut self, length: usize) -> UnmarshalResult<&'buf [u8]> { + self.cursor.read_raw(length) + } + + pub fn reset(&mut self, reset_by: usize) { + self.cursor.reset(reset_by) + } +} + +#[derive(Debug, Clone, Copy)] +pub struct Cursor<'a> { + buf: &'a [u8], + offset: usize, +} + +impl<'buf> Cursor<'buf> { + pub fn new(buf: &[u8]) -> Cursor { + Cursor { buf, offset: 0 } + } + + pub fn consumed(&self) -> usize { + self.offset + } + + pub fn align_to(&mut self, alignment: usize) -> Result { + let padding = crate::wire::util::align_offset(alignment, self.buf, self.offset)?; + + if self.offset + padding > self.buf.len() { + Err(UnmarshalError::NotEnoughBytes) + } else { + self.offset += padding; + Ok(padding) + } + } + + pub fn remainder(&self) -> &[u8] { + &self.buf[self.offset..] + } + + pub fn read_u8(&mut self) -> UnmarshalResult { + if self.remainder().is_empty() { + Err(UnmarshalError::NotEnoughBytes) + } else { + self.offset += 1; + Ok(self.buf[self.offset - 1]) + } + } + + pub fn read_i16(&mut self, byteorder: ByteOrder) -> UnmarshalResult { + self.read_u16(byteorder).map(|value| value as i16) + } + + pub fn read_u16(&mut self, byteorder: ByteOrder) -> UnmarshalResult { + self.align_to(2)?; + let value = parse_u16(self.remainder(), byteorder)?; + self.offset += 2; + Ok(value) + } + + pub fn read_i32(&mut self, byteorder: ByteOrder) -> UnmarshalResult { + self.read_u32(byteorder).map(|value| value as i32) + } + + pub fn read_u32(&mut self, byteorder: ByteOrder) -> UnmarshalResult { + self.align_to(4)?; + let value = parse_u32(self.remainder(), byteorder)?; + self.offset += 4; + Ok(value) + } + + pub fn read_i64(&mut self, byteorder: ByteOrder) -> UnmarshalResult { + self.read_u64(byteorder).map(|value| value as i64) + } + + pub fn read_u64(&mut self, byteorder: ByteOrder) -> UnmarshalResult { + self.align_to(8)?; + let value = parse_u64(self.remainder(), byteorder)?; + self.offset += 8; + Ok(value) + } + + pub fn read_str(&mut self, byteorder: ByteOrder) -> UnmarshalResult<&'buf str> { + self.align_to(4)?; + let (bytes, value) = unmarshal_str(byteorder, &self.buf[self.offset..])?; + self.offset += bytes; + Ok(value) + } + + pub fn read_signature(&mut self) -> UnmarshalResult<&'buf str> { + let (bytes, value) = unmarshal_signature(&self.buf[self.offset..])?; + self.offset += bytes; + Ok(value) + } + + pub fn read_u8_slice(&mut self, byteorder: ByteOrder) -> UnmarshalResult<&'buf [u8]> { + self.align_to(4)?; + let bytes_in_array = self.read_u32(byteorder)?; + + let elements = self.read_raw(bytes_in_array as usize)?; + + Ok(elements) + } + + pub fn read_raw(&mut self, length: usize) -> UnmarshalResult<&'buf [u8]> { + if length > self.remainder().len() { + return Err(UnmarshalError::NotEnoughBytes); + } + + let elements = &&self.buf[self.offset..][..length]; + self.offset += length; + + Ok(elements) + } + + pub fn reset(&mut self, reset_by: usize) { + self.offset -= reset_by; + } + + pub fn advance(&mut self, advance_by: usize) { + self.offset += advance_by; + } +} diff --git a/rustbus/src/wire/util.rs b/rustbus/src/wire/util.rs index 2beab37..86a8bf2 100644 --- a/rustbus/src/wire/util.rs +++ b/rustbus/src/wire/util.rs @@ -147,7 +147,7 @@ pub fn parse_u64(number: &[u8], byteorder: ByteOrder) -> UnmarshalResult { + ((number[0] as u64) << 56) } }; - Ok((8, val)) + Ok(val) } pub fn parse_u32(number: &[u8], byteorder: ByteOrder) -> UnmarshalResult { @@ -168,7 +168,7 @@ pub fn parse_u32(number: &[u8], byteorder: ByteOrder) -> UnmarshalResult { + ((number[0] as u32) << 24) } }; - Ok((4, val)) + Ok(val) } pub fn parse_u16(number: &[u8], byteorder: ByteOrder) -> UnmarshalResult { @@ -179,7 +179,7 @@ pub fn parse_u16(number: &[u8], byteorder: ByteOrder) -> UnmarshalResult { ByteOrder::LittleEndian => (number[0] as u16) + ((number[1] as u16) << 8), ByteOrder::BigEndian => (number[1] as u16) + ((number[0] as u16) << 8), }; - Ok((2, val)) + Ok(val) } pub fn align_offset(align_to: usize, buf: &[u8], offset: usize) -> Result { @@ -201,7 +201,7 @@ pub fn align_offset(align_to: usize, buf: &[u8], offset: usize) -> Result UnmarshalResult<&str> { +pub fn unmarshal_signature(buf: &[u8]) -> UnmarshalResult<(usize, &str)> { if buf.is_empty() { return Err(UnmarshalError::NotEnoughBytes); } @@ -209,19 +209,22 @@ pub fn unmarshal_signature(buf: &[u8]) -> UnmarshalResult<&str> { if buf.len() < len + 2 { return Err(UnmarshalError::NotEnoughBytes); } - let sig_buf = &buf[1..]; - let string = std::str::from_utf8(&sig_buf[..len]) - .map_err(|_| crate::params::validation::Error::InvalidUtf8)?; + let sig_buf = &buf[1..][..len]; + let string = + std::str::from_utf8(sig_buf).map_err(|_| crate::params::validation::Error::InvalidUtf8)?; Ok((len + 2, string)) } -pub fn unmarshal_string(byteorder: ByteOrder, buf: &[u8]) -> UnmarshalResult { +pub fn unmarshal_string(byteorder: ByteOrder, buf: &[u8]) -> UnmarshalResult<(usize, String)> { let (bytes, string) = unmarshal_str(byteorder, buf)?; Ok((bytes, string.into())) } -pub fn unmarshal_str<'r, 'a: 'r>(byteorder: ByteOrder, buf: &'a [u8]) -> UnmarshalResult<&'r str> { - let len = parse_u32(buf, byteorder)?.1 as usize; +pub fn unmarshal_str<'r, 'a: 'r>( + byteorder: ByteOrder, + buf: &'a [u8], +) -> UnmarshalResult<(usize, &'r str)> { + let len = parse_u32(buf, byteorder)? as usize; if buf.len() < len + 5 { return Err(UnmarshalError::NotEnoughBytes); } diff --git a/rustbus/src/wire/validate_raw.rs b/rustbus/src/wire/validate_raw.rs index b7b32b6..277a9db 100644 --- a/rustbus/src/wire/validate_raw.rs +++ b/rustbus/src/wire/validate_raw.rs @@ -92,7 +92,7 @@ pub fn validate_marshalled_base( } let offset = offset + padding; let slice = &buf[offset..offset + 4]; - let (_, val) = + let val = crate::wire::util::parse_u32(slice, byteorder).map_err(|err| (offset, err))?; match val { 0 => Ok(4 + padding), @@ -134,7 +134,7 @@ pub fn validate_marshalled_container( signature::Container::Array(elem_sig) => { let padding = util::align_offset(4, buf, offset).map_err(|err| (offset, err))?; let offset = offset + padding; - let (_, bytes_in_array) = + let bytes_in_array = util::parse_u32(&buf[offset..], byteorder).map_err(|err| (offset, err))?; let offset = offset + 4; @@ -176,7 +176,7 @@ pub fn validate_marshalled_container( signature::Container::Dict(key_sig, val_sig) => { let padding = util::align_offset(4, buf, offset).map_err(|err| (offset, err))?; let offset = offset + padding; - let (_, bytes_in_dict) = + let bytes_in_dict = util::parse_u32(&buf[offset..], byteorder).map_err(|err| (offset, err))?; let offset = offset + 4; diff --git a/rustbus/src/wire/variant_macros.rs b/rustbus/src/wire/variant_macros.rs index 9e2f822..45f27c3 100644 --- a/rustbus/src/wire/variant_macros.rs +++ b/rustbus/src/wire/variant_macros.rs @@ -98,31 +98,29 @@ macro_rules! dbus_variant_sig_unmarshal { ($vname: ident, $($name: ident => $typ: path)+) => { impl<'buf, 'fds> $crate::Unmarshal<'buf, 'fds> for $vname { fn unmarshal( - ctx: &mut $crate::wire::unmarshal::UnmarshalContext<'fds, 'buf>, + ctx: &mut $crate::wire::unmarshal_context::UnmarshalContext<'fds, 'buf>, ) -> $crate::wire::unmarshal::UnmarshalResult { use $crate::Signature; - let (sig_bytes, sig_str) = $crate::wire::util::unmarshal_signature(&ctx.buf[ctx.offset..])?; + let sig_str = ctx.read_signature()?; let mut sig = $crate::signature::Type::parse_description(&sig_str)?; let sig = if sig.len() == 1 { sig.remove(0) } else { return Err($crate::wire::errors::UnmarshalError::WrongSignature); }; - ctx.offset += sig_bytes; $( if sig == <$typ as Signature>::signature() { - let (vbytes, v) = <$typ as $crate::Unmarshal>::unmarshal(ctx)?; - return Ok((sig_bytes + vbytes, Self::$name(v))); + let v = <$typ as $crate::Unmarshal>::unmarshal(ctx)?; + return Ok(Self::$name(v)); } )+ - let vbytes = $crate::wire::validate_raw::validate_marshalled( - ctx.byteorder, ctx.offset, ctx.buf, &sig + $crate::wire::validate_raw::validate_marshalled( + ctx.byteorder, 0, ctx.remainder(), &sig ).map_err(|e| e.1)?; - ctx.offset += vbytes; - Ok((sig_bytes + vbytes, Self::Catchall(sig))) + Ok(Self::Catchall(sig)) } } }; @@ -134,7 +132,7 @@ fn test_variant_sig_macro() { use crate::Unmarshal; use crate::wire::marshal::MarshalContext; - use crate::wire::unmarshal::UnmarshalContext; + use crate::wire::unmarshal_context::UnmarshalContext; let mut fds = Vec::new(); let mut ctxbuf = Vec::new(); @@ -162,14 +160,9 @@ fn test_variant_sig_macro() { ) .unwrap(); - let (bytes, (uv1, uv2, uv3)) = - <(MyVariant, MyVariant, MyVariant) as Unmarshal>::unmarshal(&mut UnmarshalContext { - buf: ctx.buf, - fds: ctx.fds, - byteorder: ctx.byteorder, - offset: 0, - }) - .unwrap(); + let mut unmarshal_ctx = UnmarshalContext::new(ctx.fds, ctx.byteorder, ctx.buf, 0); + let (uv1, uv2, uv3) = + <(MyVariant, MyVariant, MyVariant) as Unmarshal>::unmarshal(&mut unmarshal_ctx).unwrap(); assert_eq!(uv1, v1); assert_ne!(uv1, v2); assert_ne!(uv1, v3); @@ -179,13 +172,7 @@ fn test_variant_sig_macro() { assert_eq!(uv3, v3); - let (_bytes, uv4) = MyVariant::unmarshal(&mut UnmarshalContext { - buf: ctx.buf, - fds: ctx.fds, - byteorder: ctx.byteorder, - offset: bytes, - }) - .unwrap(); + let uv4 = MyVariant::unmarshal(&mut unmarshal_ctx).unwrap(); assert_eq!( uv4, MyVariant::Catchall(crate::signature::Type::Base(crate::signature::Base::Uint64)) @@ -209,14 +196,9 @@ fn test_variant_sig_macro() { ctx.buf.clear(); (&v1, &v2, &v3, &v4).marshal(ctx).unwrap(); - let (_bytes, (uv1, uv2, uv3, uv4)) = + let (uv1, uv2, uv3, uv4) = <(MyVariant2, MyVariant2, MyVariant2, MyVariant2) as Unmarshal>::unmarshal( - &mut UnmarshalContext { - buf: ctx.buf, - fds: ctx.fds, - byteorder: ctx.byteorder, - offset: 0, - }, + &mut UnmarshalContext::new(ctx.fds, ctx.byteorder, ctx.buf, 0), ) .unwrap(); assert_eq!(uv1, v1); @@ -242,12 +224,12 @@ fn test_variant_sig_macro() { ctx.fds, ) .unwrap(); - let (_bytes, uv) = ::unmarshal(&mut UnmarshalContext { - buf: ctx.buf, - fds: ctx.fds, - byteorder: ctx.byteorder, - offset: 0, - }) + let uv = ::unmarshal(&mut UnmarshalContext::new( + ctx.fds, + ctx.byteorder, + ctx.buf, + 0, + )) .unwrap(); assert_eq!( uv, @@ -358,25 +340,26 @@ macro_rules! dbus_variant_var_unmarshal { ($vname: ident, $($name: ident => $typ: ty)+) => { impl<'buf, 'fds> $crate::Unmarshal<'buf,'fds> for $vname <'fds, 'buf> { fn unmarshal( - ctx: &mut $crate::wire::unmarshal::UnmarshalContext<'fds, 'buf> + ctx: &mut $crate::wire::unmarshal_context::UnmarshalContext<'fds, 'buf> ) -> $crate::wire::unmarshal::UnmarshalResult { use $crate::Signature; use $crate::Unmarshal; use $crate::wire::marshal::traits::SignatureBuffer; - let (sig_bytes, sig_str) = $crate::wire::util::unmarshal_signature(&ctx.buf[ctx.offset..])?; + let sig_str = ctx.read_signature()?; let mut var_sig = SignatureBuffer::new(); $( var_sig.clear(); <$typ as Signature>::sig_str(&mut var_sig); if sig_str == var_sig.as_ref() { - ctx.offset += sig_bytes; - let (vbytes, v) = <$typ as $crate::Unmarshal>::unmarshal(ctx)?; - return Ok((sig_bytes + vbytes, Self::$name(v))); + let v = <$typ as $crate::Unmarshal>::unmarshal(ctx)?; + return Ok(Self::$name(v)); } )+ - let (vbytes,var) = <$crate::wire::unmarshal::traits::Variant as Unmarshal>::unmarshal(ctx)?; - Ok((sig_bytes + vbytes, Self::Catchall(var))) + // TODO this should just be a function on Variant that takes the signature str + ctx.reset(1 + sig_str.as_bytes().len() + 1); + let var = <$crate::wire::unmarshal::traits::Variant as Unmarshal>::unmarshal(ctx)?; + Ok(Self::Catchall(var)) } } }; @@ -388,7 +371,7 @@ fn test_variant_var_macro() { use crate::Unmarshal; use crate::wire::marshal::MarshalContext; - use crate::wire::unmarshal::UnmarshalContext; + use crate::wire::unmarshal_context::UnmarshalContext; let mut fds = Vec::new(); let mut buf = Vec::new(); @@ -418,16 +401,10 @@ fn test_variant_var_macro() { ) .unwrap(); - let (bytes, (uv1, uv2, uv3, uv4)) = - <(MyVariant, MyVariant, MyVariant, MyVariant) as Unmarshal>::unmarshal( - &mut UnmarshalContext { - buf: ctx.buf, - fds: ctx.fds, - byteorder: ctx.byteorder, - offset: 0, - }, - ) - .unwrap(); + let mut unmarshal_ctx = UnmarshalContext::new(ctx.fds, ctx.byteorder, ctx.buf, 0); + let (uv1, uv2, uv3, uv4) = + <(MyVariant, MyVariant, MyVariant, MyVariant) as Unmarshal>::unmarshal(&mut unmarshal_ctx) + .unwrap(); assert!(match uv1 { MyVariant::String(s) => s.eq("ABCD"), _ => false, @@ -445,13 +422,7 @@ fn test_variant_var_macro() { _ => false, }); - let (_bytes, uv4) = MyVariant::unmarshal(&mut UnmarshalContext { - buf: ctx.buf, - fds: ctx.fds, - byteorder: ctx.byteorder, - offset: bytes, - }) - .unwrap(); + let uv4 = MyVariant::unmarshal(&mut unmarshal_ctx).unwrap(); assert!(match uv4 { MyVariant::Catchall(var) => { @@ -476,14 +447,9 @@ fn test_variant_var_macro() { ctx.buf.clear(); (&v1, &v2, &v3, &v4).marshal(ctx).unwrap(); - let (_bytes, (uv1, uv2, uv3, uv4)) = + let (uv1, uv2, uv3, uv4) = <(MyVariant2, MyVariant2, MyVariant2, MyVariant2) as Unmarshal>::unmarshal( - &mut UnmarshalContext { - buf: ctx.buf, - fds: ctx.fds, - byteorder: ctx.byteorder, - offset: 0, - }, + &mut UnmarshalContext::new(ctx.fds, ctx.byteorder, ctx.buf, 0), ) .unwrap(); assert!(match uv1 { @@ -568,12 +534,12 @@ fn test_variant_var_macro() { ctx.fds, ) .unwrap(); - let (_bytes, uv) = ::unmarshal(&mut UnmarshalContext { - buf: ctx.buf, - fds: ctx.fds, - byteorder: ctx.byteorder, - offset: 0, - }) + let uv = ::unmarshal(&mut UnmarshalContext::new( + ctx.fds, + ctx.byteorder, + ctx.buf, + 0, + )) .unwrap(); assert!(match uv { MyVariant2::Catchall(var) => { diff --git a/rustbus/src/wire/wrapper_types/unixfd.rs b/rustbus/src/wire/wrapper_types/unixfd.rs index 4ce9643..e9cde21 100644 --- a/rustbus/src/wire/wrapper_types/unixfd.rs +++ b/rustbus/src/wire/wrapper_types/unixfd.rs @@ -1,7 +1,7 @@ -use crate::wire::errors::{MarshalError, UnmarshalError}; +use crate::wire::errors::MarshalError; use crate::wire::marshal::traits::SignatureBuffer; use crate::wire::marshal::MarshalContext; -use crate::wire::unmarshal::UnmarshalContext; +use crate::wire::unmarshal_context::UnmarshalContext; use crate::{Marshal, Signature, Unmarshal}; use std::io; @@ -191,14 +191,7 @@ impl<'buf, 'fds> Unmarshal<'buf, 'fds> for UnixFd { fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf>, ) -> crate::wire::unmarshal::UnmarshalResult { - let (bytes, idx) = u32::unmarshal(ctx)?; - - if ctx.fds.len() <= idx as usize { - Err(UnmarshalError::BadFdIndex(idx as usize)) - } else { - let val = &ctx.fds[idx as usize]; - Ok((bytes, val.clone())) - } + ctx.read_unixfd() } } diff --git a/rustbus_derive/Cargo.toml b/rustbus_derive/Cargo.toml index de5e5f3..da036c4 100644 --- a/rustbus_derive/Cargo.toml +++ b/rustbus_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustbus_derive" -version = "0.5.0" +version = "0.6.0" authors = ["Moritz Borcherding "] edition = "2018" license = "MIT" diff --git a/rustbus_derive/src/structs.rs b/rustbus_derive/src/structs.rs index 813a84e..6f0e33b 100644 --- a/rustbus_derive/src/structs.rs +++ b/rustbus_derive/src/structs.rs @@ -50,7 +50,7 @@ pub fn make_struct_unmarshal_impl( quote! { impl #impl_gen ::rustbus::Unmarshal<'__internal_buf, '_> for #ident #typ_gen #clause_gen { #[inline] - fn unmarshal(ctx: &mut ::rustbus::wire::unmarshal::UnmarshalContext<'_,'__internal_buf>) -> Result<(usize,Self), ::rustbus::wire::errors::UnmarshalError> { + fn unmarshal(ctx: &mut ::rustbus::wire::unmarshal_context::UnmarshalContext<'_,'__internal_buf>) -> Result { #marshal } } @@ -102,16 +102,14 @@ fn struct_field_unmarshal(fields: &syn::Fields) -> TokenStream { let field_types = fields.iter().map(|field| field.ty.to_token_stream()); quote! { - let start_offset = ctx.offset; ctx.align_to(8)?; let this = Self{ #( - #field_names: <#field_types as ::rustbus::Unmarshal>::unmarshal(ctx)?.1, + #field_names: <#field_types as ::rustbus::Unmarshal>::unmarshal(ctx)?, )* }; - let total_bytes = ctx.offset - start_offset; - Ok((total_bytes, this)) + Ok(this) } } fn struct_field_sigs(fields: &syn::Fields) -> TokenStream { diff --git a/rustbus_derive/src/variants.rs b/rustbus_derive/src/variants.rs index 5c263d8..11a5c4f 100644 --- a/rustbus_derive/src/variants.rs +++ b/rustbus_derive/src/variants.rs @@ -185,10 +185,8 @@ pub fn make_variant_unmarshal_impl( quote! { impl #impl_gen ::rustbus::Unmarshal<'__internal_buf, '_> for #ident #typ_gen #clause_gen { #[inline] - fn unmarshal(ctx: &mut ::rustbus::wire::unmarshal::UnmarshalContext<'_,'__internal_buf>) -> Result<(usize,Self), ::rustbus::wire::errors::UnmarshalError> { - let start_offset = ctx.offset; - let (sig_bytes, sig) = ::rustbus::wire::util::unmarshal_signature(&ctx.buf[ctx.offset..])?; - ctx.offset += sig_bytes; + fn unmarshal(ctx: &mut ::rustbus::wire::unmarshal_context::UnmarshalContext<'_,'__internal_buf>) -> Result { + let sig = ctx.read_signature()?; #marshal Err(::rustbus::wire::errors::UnmarshalError::NoMatchingVariantFound) @@ -227,11 +225,10 @@ fn variant_unmarshal(enum_name: syn::Ident, variant: &syn::Variant) -> TokenStre ctx.align_to(8)?; let this = #enum_name::#name{ #( - #field_names: <#field_types2 as ::rustbus::Unmarshal>::unmarshal(ctx)?.1, + #field_names: <#field_types2 as ::rustbus::Unmarshal>::unmarshal(ctx)?, )* }; - let total_bytes = ctx.offset - start_offset; - return Ok((total_bytes, this)); + return Ok(this); } } } else if variant.fields.iter().next().unwrap().ident.is_none() && variant.fields.len() > 1 @@ -249,11 +246,10 @@ fn variant_unmarshal(enum_name: syn::Ident, variant: &syn::Variant) -> TokenStre ctx.align_to(8)?; let this = #enum_name::#name( #( - <#field_types2 as ::rustbus::Unmarshal>::unmarshal(ctx)?.1, + <#field_types2 as ::rustbus::Unmarshal>::unmarshal(ctx)?, )* ); - let total_bytes = ctx.offset - start_offset; - return Ok((total_bytes, this)); + return Ok(this); } } } else { @@ -266,10 +262,9 @@ fn variant_unmarshal(enum_name: syn::Ident, variant: &syn::Variant) -> TokenStre if sig.eq(sig_str.as_ref()) { let this = #enum_name::#name( - <#ty as ::rustbus::Unmarshal>::unmarshal(ctx)?.1, + <#ty as ::rustbus::Unmarshal>::unmarshal(ctx)?, ); - let total_bytes = ctx.offset - start_offset; - return Ok((total_bytes, this)); + return Ok(this); } } } diff --git a/rustbus_derive_test/Cargo.toml b/rustbus_derive_test/Cargo.toml index 9f8efba..7104d9e 100644 --- a/rustbus_derive_test/Cargo.toml +++ b/rustbus_derive_test/Cargo.toml @@ -8,4 +8,4 @@ edition = "2018" [dependencies] "rustbus" = {path = "../rustbus", version = "0.19.3"} -"rustbus_derive" = {path = "../rustbus_derive", version = "0.5.0"} \ No newline at end of file +"rustbus_derive" = {path = "../rustbus_derive", version = "0.6.0"} \ No newline at end of file