From eb18a0fe67478a7e74f2605b77300ec2bbcec685 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Fri, 11 Jul 2025 14:42:55 +0200 Subject: [PATCH 1/2] der: optimize compile-time: code reuse with `encode_value_to_slice` --- der/src/asn1/any.rs | 9 ++------- der/src/asn1/integer.rs | 12 +++++------- der/src/asn1/integer/int.rs | 4 +--- der/src/asn1/integer/uint.rs | 4 +--- der/src/encode.rs | 10 ++++++++++ der/src/length.rs | 14 ++++---------- 6 files changed, 23 insertions(+), 30 deletions(-) diff --git a/der/src/asn1/any.rs b/der/src/asn1/any.rs index efb891610..a522cfe99 100644 --- a/der/src/asn1/any.rs +++ b/der/src/asn1/any.rs @@ -8,9 +8,6 @@ use crate::{ }; use core::cmp::Ordering; -#[cfg(feature = "alloc")] -use crate::SliceWriter; - /// ASN.1 `ANY`: represents any explicitly tagged ASN.1 value. /// /// This is a zero-copy reference type which borrows from the input data. @@ -179,7 +176,7 @@ pub use self::allocating::Any; #[cfg(feature = "alloc")] mod allocating { use super::*; - use crate::{BytesOwned, reader::read_value, referenced::*}; + use crate::{BytesOwned, encode::encode_value_to_slice, reader::read_value, referenced::*}; use alloc::boxed::Box; /// ASN.1 `ANY`: represents any explicitly tagged ASN.1 value. @@ -242,9 +239,7 @@ mod allocating { { let encoded_len = usize::try_from(msg.value_len()?)?; let mut buf = vec![0u8; encoded_len]; - let mut writer = SliceWriter::new(&mut buf); - msg.encode_value(&mut writer)?; - writer.finish()?; + encode_value_to_slice(&mut buf, msg)?; Any::new(msg.tag(), buf) } diff --git a/der/src/asn1/integer.rs b/der/src/asn1/integer.rs index 7ea87abad..ffdb76d84 100644 --- a/der/src/asn1/integer.rs +++ b/der/src/asn1/integer.rs @@ -5,7 +5,7 @@ pub(super) mod uint; use core::{cmp::Ordering, mem::size_of}; -use crate::{EncodeValue, Result, SliceWriter}; +use crate::{EncodeValue, Result, encode::encode_value_to_slice}; /// Is the highest bit of the first byte in the slice set to `1`? (if present) #[inline] @@ -25,14 +25,12 @@ where debug_assert!(size_of::() <= MAX_INT_SIZE); let mut buf1 = [0u8; MAX_INT_SIZE]; - let mut encoder1 = SliceWriter::new(&mut buf1); - a.encode_value(&mut encoder1)?; - let mut buf2 = [0u8; MAX_INT_SIZE]; - let mut encoder2 = SliceWriter::new(&mut buf2); - b.encode_value(&mut encoder2)?; - Ok(encoder1.finish()?.cmp(encoder2.finish()?)) + let buf1 = encode_value_to_slice(&mut buf1, &a)?; + let buf2 = encode_value_to_slice(&mut buf2, &b)?; + + Ok(buf1.cmp(buf2)) } #[cfg(test)] diff --git a/der/src/asn1/integer/int.rs b/der/src/asn1/integer/int.rs index 51bfa0f72..e96d4fbe5 100644 --- a/der/src/asn1/integer/int.rs +++ b/der/src/asn1/integer/int.rs @@ -311,9 +311,7 @@ mod allocating { fn try_from(value: $int) -> $crate::Result { let mut buf = [0u8; 16]; - let mut writer = $crate::SliceWriter::new(&mut buf[..]); - value.encode_value(&mut writer)?; - let buf = writer.finish()?; + let buf = $crate::asn1::integer::encode_value_to_slice(&mut buf, &value)?; Int::new(buf) } } diff --git a/der/src/asn1/integer/uint.rs b/der/src/asn1/integer/uint.rs index eb22bb29c..727788f67 100644 --- a/der/src/asn1/integer/uint.rs +++ b/der/src/asn1/integer/uint.rs @@ -284,9 +284,7 @@ mod allocating { fn try_from(value: $uint) -> $crate::Result { let mut buf = [0u8; 17]; - let mut writer = $crate::SliceWriter::new(&mut buf[..]); - value.encode_value(&mut writer)?; - let buf = writer.finish()?; + let buf = $crate::encode::encode_value_to_slice(&mut buf, &value)?; Uint::new(buf) } } diff --git a/der/src/encode.rs b/der/src/encode.rs index 578f7c9c3..25f4c48b8 100644 --- a/der/src/encode.rs +++ b/der/src/encode.rs @@ -164,3 +164,13 @@ where T::encode_value(self, writer) } } + +/// Encodes value only (without tag + length) to a slice. +pub(crate) fn encode_value_to_slice<'a, T>(buf: &'a mut [u8], value: &T) -> Result<&'a [u8]> +where + T: EncodeValue, +{ + let mut encoder = SliceWriter::new(buf); + value.encode_value(&mut encoder)?; + encoder.finish() +} diff --git a/der/src/length.rs b/der/src/length.rs index 272b328d9..35f4f9242 100644 --- a/der/src/length.rs +++ b/der/src/length.rs @@ -3,10 +3,7 @@ pub(crate) mod indefinite; use self::indefinite::INDEFINITE_LENGTH_OCTET; -use crate::{ - Decode, DerOrd, Encode, EncodingRules, Error, ErrorKind, Reader, Result, SliceWriter, Tag, - Writer, -}; +use crate::{Decode, DerOrd, Encode, EncodingRules, Error, ErrorKind, Reader, Result, Tag, Writer}; use core::{ cmp::Ordering, fmt, @@ -327,13 +324,10 @@ impl DerOrd for Length { let mut buf1 = [0u8; Self::MAX_SIZE]; let mut buf2 = [0u8; Self::MAX_SIZE]; - let mut encoder1 = SliceWriter::new(&mut buf1); - encoder1.encode(self)?; - - let mut encoder2 = SliceWriter::new(&mut buf2); - encoder2.encode(other)?; + let buf1 = self.encode_to_slice(&mut buf1)?; + let buf2 = other.encode_to_slice(&mut buf2)?; - Ok(encoder1.finish()?.cmp(encoder2.finish()?)) + Ok(buf1.cmp(buf2)) } } From 2c4bfad4f8d7ee9d83ea9dece0adf18a923de18f Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Tue, 15 Jul 2025 10:17:55 +0200 Subject: [PATCH 2/2] der: wrong macro fn import --- der/src/asn1/integer/int.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/der/src/asn1/integer/int.rs b/der/src/asn1/integer/int.rs index e96d4fbe5..9e8b5eb7a 100644 --- a/der/src/asn1/integer/int.rs +++ b/der/src/asn1/integer/int.rs @@ -311,7 +311,7 @@ mod allocating { fn try_from(value: $int) -> $crate::Result { let mut buf = [0u8; 16]; - let buf = $crate::asn1::integer::encode_value_to_slice(&mut buf, &value)?; + let buf = $crate::encode::encode_value_to_slice(&mut buf, &value)?; Int::new(buf) } }