use std::{fmt, ops::Deref}; use base64::display::Base64Display; use serde::{ de::{Error as DeError, SeqAccess, Visitor}, Deserialize, Deserializer, Serialize, Serializer, }; use serde_bytes::Bytes; use crate::Error; pub(crate) const TOKEN: &str = "$serde_wormhole::private::RawMessage"; /// Reference to a range of bytes in the input data. /// /// A `RawMessage` can be used to defer parsing parts of the input data until later, or to avoid /// parsing it at all if it needs to be passed on verbatim to a different output object. /// /// When used to deserialize data in the wormhole data format, `RawMessage` will consume all the /// remaining data in the input since the wormhole wire format is not self-describing. However when /// used with self-describing formats like JSON, `RawMessage` will expect either a sequence of bytes /// or a base64-encoded string. /// /// When serializing, a `RawMessage` will either serialize to a base64-encoded string if the data /// format is human readable (like JSON) or will forward the raw bytes to the serializer if not. /// /// # Examples /// /// Defer parsing the payload of a VAA body: /// /// ``` /// # fn example() -> Result<(), serde_wormhole::Error> { /// # let data = [ /// # 0x62, 0xb9, 0xf7, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, /// # 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x9a, 0x2a, 0x01, 0xb7, 0x05, 0x19, 0xf6, /// # 0x7a, 0xdb, 0x30, 0x9a, 0x99, 0x4e, 0xc8, 0xc6, 0x9a, 0x96, 0x7e, 0x8b, 0x00, 0x00, 0x00, /// # 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x46, 0x72, 0x6f, 0x6d, 0x3a, 0x20, 0x65, 0x76, 0x6d, /// # 0x30, 0x5c, 0x6e, 0x4d, 0x73, 0x67, 0x3a, 0x20, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, /// # 0x6f, 0x72, 0x6c, 0x64, 0x21, /// # ]; /// # /// use serde::{Serialize, Deserialize}; /// use serde_wormhole::{from_slice, RawMessage}; /// /// #[derive(Serialize, Deserialize, Debug)] /// struct Body<'a> { /// timestamp: u32, /// nonce: u32, /// emitter_chain: u16, /// emitter_address: [u8; 32], /// sequence: u64, /// consistency_level: u8, /// #[serde(borrow)] /// payload: &'a RawMessage, /// } /// /// let body = from_slice::
(&data)?; /// assert_eq!(b"From: evm0\\nMsg: Hello World!", body.payload.get()); /// # /// # Ok(()) /// # } /// # /// # example().unwrap(); /// ``` /// /// # Ownership /// /// The typical usage of `RawMessage` will be in its borrowed form: /// /// ``` /// # use serde::Deserialize; /// # use serde_wormhole::RawMessage; /// # /// #[derive(Deserialize)] /// struct MyStruct<'a> { /// #[serde(borrow)] /// raw_message: &'a RawMessage, /// } /// ``` /// /// The borrowed form is suitable for use with `serde_wormhole::from_slice` because it supports /// borrowing from the input data without memory allocation. If the value is encoded as a string, /// deserializing to the borrowed form may or may not succeed depending on the deserializer /// implementation. In the case where the deserialization is successful, the contents of the string /// will not be interpreted in any way and the `RawMessage` will simply contain the raw bytes of /// the input string. This may have unexpected consequences (such as the bytes being base64-encoded /// if the `RawMessage` is re-serialized, potentially leading to double-encoding). In general, you /// should only use the borrowed form if you know the input data contains raw bytes. Otherwise, the /// boxed form is a safer choice. /// /// When deserializing through `serde_wormhole::from_reader` or when the value is encoded as a /// base64 string, it is necessary to use the boxed form. This involves either copying the data /// from the IO stream or decoding the base64 string and then storing it in memory. /// /// ``` /// # use serde::Deserialize; /// # use serde_wormhole::RawMessage; /// # /// #[derive(Deserialize)] /// struct MyStruct { /// raw_message: Box {
f1: u32,
f2: u16,
payload: P,
}
#[test]
fn borrowed() {
let data = [
0x5b, 0x4a, 0x55, 0xca, 0x80, 0x53, 0xfe, 0x25, 0x6d, 0xdc, 0xb3, 0x3b, 0x8d, 0x38,
0xf7, 0x1b,
];
let expected = MyStruct {
f1: 0x5b4a55ca,
f2: 0x8053,
payload: RawMessage::from_borrowed(&data[6..]),
};
let actual = crate::from_slice::