diff --git a/rust/candid/src/utils.rs b/rust/candid/src/utils.rs index aee8206d..c1edf0cd 100644 --- a/rust/candid/src/utils.rs +++ b/rust/candid/src/utils.rs @@ -194,6 +194,29 @@ pub fn write_args( ser.serialize(writer) } +/// Serialize an encoding of a tuple and write it to a `Write` buffer. +/// +/// ``` +/// # use candid::Decode; +/// # use candid::write_args; +/// let golden1 = 1u64; +/// let golden2 = "hello"; +/// let mut buffer = Vec::new(); +/// write_args_ref(&mut buffer, &(golden1, golden2)).unwrap(); +/// +/// let (value1, value2) = Decode!(&buffer, u64, String).unwrap(); +/// assert_eq!(golden1, value1); +/// assert_eq!(golden2, value2); +/// ``` +pub fn write_args_ref( + writer: &mut Writer, + arguments: &Tuple, +) -> Result<()> { + let mut ser = IDLBuilder::new(); + arguments.encode_ref(&mut ser)?; + ser.serialize(writer) +} + /// Serialize an encoding of a tuple to a vector of bytes. /// /// ``` @@ -213,6 +236,25 @@ pub fn encode_args(arguments: Tuple) -> Result> Ok(result) } +/// Serialize an encoding of a tuple to a vector of bytes. +/// +/// ``` +/// # use candid::Decode; +/// # use candid::encode_args; +/// let golden1 = 1u64; +/// let golden2 = "hello"; +/// let buffer = encode_args_ref(&(golden1, golden2)).unwrap(); +/// +/// let (value1, value2) = Decode!(&buffer, u64, String).unwrap(); +/// assert_eq!(golden1, value1); +/// assert_eq!(golden2, value2); +/// ``` +pub fn encode_args_ref(arguments: &Tuple) -> Result> { + let mut result = Vec::new(); + write_args_ref(&mut result, arguments)?; + Ok(result) +} + /// Serialize a single value to a vector of bytes. /// /// ``` @@ -245,11 +287,18 @@ impl<'a> ArgumentDecoder<'a> for () { pub trait ArgumentEncoder { /// Encode a value of type [Self]. fn encode(self, ser: &mut IDLBuilder) -> Result<()>; + + /// Encode a reference value of type [Self]. + fn encode_ref(&self, ser: &mut IDLBuilder) -> Result<()>; } /// Decode an empty tuple. impl ArgumentEncoder for () { - fn encode(self, _de: &mut IDLBuilder) -> Result<()> { + fn encode(self, _ser: &mut IDLBuilder) -> Result<()> { + Ok(()) + } + + fn encode_ref(&self, _ser: &mut IDLBuilder) -> Result<()> { Ok(()) } } @@ -287,6 +336,15 @@ macro_rules! encode_impl { Ok(()) } + + fn encode_ref(&self, ser: &mut IDLBuilder) -> Result<()> { + let ( $( $id, )* ) = self; + $( + ser.arg(&$id)?; + )* + + Ok(()) + } } } }