diff --git a/Cargo.lock b/Cargo.lock index f4fc2b4c..c11fdd22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -209,7 +209,7 @@ dependencies = [ [[package]] name = "candid" -version = "0.10.12" +version = "0.10.13" dependencies = [ "anyhow", "bincode", @@ -280,7 +280,7 @@ version = "0.2.0-beta.4" dependencies = [ "anyhow", "arbitrary", - "candid 0.10.12", + "candid 0.10.13", "codespan-reporting", "console", "convert_case", diff --git a/Changelog.md b/Changelog.md index 4b0e4cd2..678bbc69 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,12 @@ # Changelog +## 2025-01-22 + +### Candid 0.10.13 + +* Add `ArgumentEncoder::encode_ref`, `utils::{write_args, encode_args}` that don't consume the value when encoding. + ## 2025-01-15 ### Candid 0.10.12 diff --git a/rust/candid/Cargo.toml b/rust/candid/Cargo.toml index d91d13ce..8679ed7d 100644 --- a/rust/candid/Cargo.toml +++ b/rust/candid/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "candid" -version = "0.10.12" +version = "0.10.13" edition = "2021" rust-version.workspace = true authors = ["DFINITY Team"] diff --git a/rust/candid/src/utils.rs b/rust/candid/src/utils.rs index aee8206d..e35c1ae5 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::utils::write_args_ref; +/// 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::utils::encode_args_ref; +/// 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(()) + } } } }