1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
use std::marker::PhantomData; /// The encoding format. /// #[derive(Debug, PartialEq, Copy, Clone)] pub enum EncodingFormat { /// [D-Bus](https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling) /// format. DBus, /// [GVariant](https://developer.gnome.org/glib/stable/glib-GVariant.html) format. #[cfg(feature = "gvariant")] GVariant, } impl Default for EncodingFormat { fn default() -> Self { EncodingFormat::DBus } } impl std::fmt::Display for EncodingFormat { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { EncodingFormat::DBus => write!(f, "D-Bus"), #[cfg(feature = "gvariant")] EncodingFormat::GVariant => write!(f, "GVariant"), } } } /// The encoding context to use with the [serialization and deserialization] API. /// /// This type is generic over the [ByteOrder] trait. Moreover, the encoding is dependent on the /// position of the encoding in the entire message and hence the need to [specify] the byte /// position of the data being serialized or deserialized. Simply pass `0` if serializing or /// deserializing to or from the beginning of message, or the preceeding bytes end on an 8-byte /// boundry. /// /// # Examples /// /// ``` /// use byteorder::LE; /// /// use zvariant::EncodingContext as Context; /// use zvariant::{from_slice, to_bytes}; /// /// let str_vec = vec!["Hello", "World"]; /// let ctxt = Context::<LE>::new_dbus(0); /// let encoded = to_bytes(ctxt, &str_vec).unwrap(); /// /// // Let's decode the 2nd element of the array only /// let ctxt = Context::<LE>::new_dbus(14); /// let decoded: &str = from_slice(&encoded[14..], ctxt).unwrap(); /// assert_eq!(decoded, "World"); /// ``` /// /// [serialization and deserialization]: index.html#functions /// [ByteOrder]: https://docs.rs/byteorder/1.3.4/byteorder/trait.ByteOrder.html /// [specify]: #method.new #[derive(Debug, PartialEq, Copy, Clone)] pub struct EncodingContext<B> { format: EncodingFormat, position: usize, b: PhantomData<B>, } impl<B> EncodingContext<B> where B: byteorder::ByteOrder, { /// Create a new encoding context. pub fn new(format: EncodingFormat, position: usize) -> Self { Self { format, position, b: PhantomData, } } /// Convenient wrapper for [`new`] to create a context for D-Bus format. /// /// [`new`]: #method.new pub fn new_dbus(position: usize) -> Self { Self::new(EncodingFormat::DBus, position) } /// Convenient wrapper for [`new`] to create a context for GVariant format. /// /// [`new`]: #method.new #[cfg(feature = "gvariant")] pub fn new_gvariant(position: usize) -> Self { Self::new(EncodingFormat::GVariant, position) } /// The [`EncodingFormat`] of this context. /// /// [`EncodingFormat`]: enum.EncodingFormat.html pub fn format(self) -> EncodingFormat { self.format } /// The byte position of the value to be encoded or decoded, in the entire message. pub fn position(self) -> usize { self.position } }