From 57c879a025498704dd9948fdae18f1f96c7afa42 Mon Sep 17 00:00:00 2001 From: Jannik Beyerstedt Date: Wed, 22 Jul 2026 17:47:44 +0200 Subject: [PATCH 1/2] feat(en,de): Add encoding and decoding functions for all ASN.1 types --- src/de.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/en.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/src/de.rs b/src/de.rs index d2e38c2..cc939bf 100644 --- a/src/de.rs +++ b/src/de.rs @@ -272,6 +272,61 @@ pub fn decode_gn_btp_headers( Ok((remaining, alloc::boxed::Box::new(tp), result.decoded)) } +#[cfg(all(not(target_arch = "wasm32"), feature = "_etsi"))] +/// Decodes some ASN.1 data type from UPER buffer +/// +/// # Errors +/// Returns a human-readable string when decoding failed +pub fn decode_from_uper(input: &[u8]) -> Result { + rasn::Codec::Uper + .decode_from_binary(input) + .map_err(crate::map_err_to_string) +} + +#[cfg(all(not(target_arch = "wasm32"), feature = "_etsi"))] +/// Decodes some ASN.1 data type from XER buffer +/// +/// # Errors +/// Returns a human-readable string when decoding failed +pub fn decode_from_xer_buf(input: &[u8]) -> Result { + rasn::Codec::Xer + .decode_from_binary(input) + .map_err(crate::map_err_to_string) +} + +#[cfg(all(not(target_arch = "wasm32"), feature = "_etsi"))] +/// Decodes some ASN.1 data type from XER string +/// +/// # Errors +/// Returns a human-readable string when decoding failed +pub fn decode_from_xer_str(input: &str) -> Result { + rasn::Codec::Xer + .decode_from_str(input) + .map_err(crate::map_err_to_string) +} + +#[cfg(all(not(target_arch = "wasm32"), feature = "_etsi"))] +/// Decodes some ASN.1 data type from JER buffer +/// +/// # Errors +/// Returns a human-readable string when decoding failed +pub fn decode_from_jer_buf(input: &[u8]) -> Result { + rasn::Codec::Jer + .decode_from_binary(input) + .map_err(crate::map_err_to_string) +} + +#[cfg(all(not(target_arch = "wasm32"), feature = "_etsi"))] +/// Decodes some ASN.1 data type from JER string +/// +/// # Errors +/// Returns a human-readable string when decoding failed +pub fn decode_from_jer_str(input: &str) -> Result { + rasn::Codec::Jer + .decode_from_str(input) + .map_err(crate::map_err_to_string) +} + #[cfg(all(target_arch = "wasm32", feature = "v2x", feature = "json"))] #[wasm_bindgen(js_name = decode)] /// Decodes an ITS message of undefined type. diff --git a/src/en.rs b/src/en.rs index cf0ed9a..99e0e9c 100644 --- a/src/en.rs +++ b/src/en.rs @@ -178,6 +178,65 @@ impl crate::ItsMessage<'_> { } } +#[cfg(all(not(target_arch = "wasm32"), feature = "_etsi"))] +/// Encodes some ASN.1 data type to UPER buffer +/// +/// # Errors +/// Returns a human-readable string when encoding failed +pub fn encode_to_uper(input: &T) -> Result { + rasn::Codec::Uper + .encode_to_binary(input) + .map_err(crate::map_err_to_string) +} + +#[cfg(all(not(target_arch = "wasm32"), feature = "_etsi"))] +/// Encodes some ASN.1 data type to XER buffer +/// +/// # Errors +/// Returns a human-readable string when encoding failed +pub fn encode_to_xer_buf(input: &T) -> Result { + rasn::Codec::Xer + .encode_to_binary(input) + .map_err(crate::map_err_to_string) +} + +#[cfg(all(not(target_arch = "wasm32"), feature = "_etsi"))] +/// Encodes some ASN.1 data type to XER string +/// +/// # Errors +/// Returns a human-readable string when encoding failed +pub fn encode_to_xer_str( + input: &T, +) -> Result { + rasn::Codec::Xer + .encode_to_string(input) + .map_err(crate::map_err_to_string) +} + +#[cfg(all(not(target_arch = "wasm32"), feature = "_etsi"))] +/// Encodes some ASN.1 data type to JER buffer +/// +/// # Errors +/// Returns a human-readable string when encoding failed +pub fn encode_to_jer_buf(input: &T) -> Result { + rasn::Codec::Jer + .encode_to_binary(input) + .map_err(crate::map_err_to_string) +} + +#[cfg(all(not(target_arch = "wasm32"), feature = "_etsi"))] +/// Encodes some ASN.1 data type to JER string +/// +/// # Errors +/// Returns a human-readable string when encoding failed +pub fn encode_to_jer_str( + input: &T, +) -> Result { + rasn::Codec::Jer + .encode_to_string(input) + .map_err(crate::map_err_to_string) +} + #[cfg(all(target_arch = "wasm32", feature = "json"))] #[wasm_bindgen(js_name = encodeDenm)] /// Encodes a DENM message into binary UPER with optional headers From cb891b1ed6755facaa6ff111126731b856fda62d Mon Sep 17 00:00:00 2001 From: Jannik Beyerstedt Date: Tue, 7 Jul 2026 14:14:56 +0200 Subject: [PATCH 2/2] feat(en,de): Add encoding methods for common messages --- src/de.rs | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/en.rs | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 228 insertions(+) diff --git a/src/de.rs b/src/de.rs index cc939bf..d7e0c31 100644 --- a/src/de.rs +++ b/src/de.rs @@ -327,6 +327,118 @@ pub fn decode_from_jer_str(input: &str) -> Result { + impl $t { + /// Decodes [`Self`] from UPER buffer + /// + /// # Errors + /// Returns a human-readable string when decoding failed + pub fn decode_from_uper(input: &[u8]) -> Result { + crate::de::decode_from_uper::(input) + } + + /// Decodes [`Self`] from XER buffer + /// + /// # Errors + /// Returns a human-readable string when decoding failed + pub fn decode_from_xer_buf(input: &[u8]) -> Result { + crate::de::decode_from_xer_buf::(input) + } + + /// Decodes [`Self`] from XER string + /// + /// # Errors + /// Returns a human-readable string when decoding failed + pub fn decode_from_xer_str(input: &str) -> Result { + crate::de::decode_from_xer_str::(input) + } + + /// Decodes [`Self`] from JER buffer + /// + /// # Errors + /// Returns a human-readable string when decoding failed + pub fn decode_from_jer_buf(input: &[u8]) -> Result { + crate::de::decode_from_jer_buf::(input) + } + + /// Decodes [`Self`] from JER string + /// + /// # Errors + /// Returns a human-readable string when decoding failed + pub fn decode_from_jer_str(input: &str) -> Result { + crate::de::decode_from_jer_str::(input) + } + } + }; +} + +#[cfg(all(not(target_arch = "wasm32"), feature = "_cdd_1_3_1_1"))] +decode_some_type!(crate::standards::cdd_1_3_1_1::its_container::ItsPduHeader); +#[cfg(all(not(target_arch = "wasm32"), feature = "_cdd_2_2_1"))] +decode_some_type!(crate::standards::cdd_2_2_1::etsi_its_cdd::ItsPduHeader); + +#[cfg(all(not(target_arch = "wasm32"), feature = "denm_2_2_1"))] +decode_some_type!(crate::standards::denm_2_2_1::denm_pdu_description::DENM); +#[cfg(all(not(target_arch = "wasm32"), feature = "denm_2_2_1"))] +decode_some_type!(crate::standards::denm_2_2_1::denm_pdu_description::DenmPayload); + +#[cfg(all(not(target_arch = "wasm32"), feature = "denm_1_3_1"))] +decode_some_type!(crate::standards::denm_1_3_1::denm_pdu_descriptions::DENM); +#[cfg(all(not(target_arch = "wasm32"), feature = "denm_1_3_1"))] +decode_some_type!( + crate::standards::denm_1_3_1::denm_pdu_descriptions::DecentralizedEnvironmentalNotificationMessage +); + +#[cfg(all(not(target_arch = "wasm32"), feature = "cam_1_4_1"))] +decode_some_type!(crate::standards::cam_1_4_1::cam_pdu_descriptions::CAM); +#[cfg(all(not(target_arch = "wasm32"), feature = "cam_1_4_1"))] +decode_some_type!(crate::standards::cam_1_4_1::cam_pdu_descriptions::CoopAwareness); + +#[cfg(all(not(target_arch = "wasm32"), feature = "spatem_2_2_1"))] +decode_some_type!(crate::standards::spatem_2_2_1::spatem_pdu_descriptions::SPATEM); +#[cfg(all(not(target_arch = "wasm32"), feature = "_dsrc_2_2_1"))] +decode_some_type!(crate::standards::dsrc_2_2_1::etsi_its_dsrc::SPAT); + +#[cfg(all(not(target_arch = "wasm32"), feature = "mapem_2_2_1"))] +decode_some_type!(crate::standards::mapem_2_2_1::mapem_pdu_descriptions::MAPEM); +#[cfg(all(not(target_arch = "wasm32"), feature = "_dsrc_2_2_1"))] +decode_some_type!(crate::standards::dsrc_2_2_1::etsi_its_dsrc::MapData); + +#[cfg(all(not(target_arch = "wasm32"), feature = "ivim_2_2_1"))] +decode_some_type!(crate::standards::ivim_2_2_1::ivim_pdu_descriptions::IVIM); +#[cfg(all(not(target_arch = "wasm32"), feature = "ivim_2_2_1"))] +decode_some_type!(crate::standards::ivim_2_2_1::ivi::IviStructure); + +#[cfg(all(not(target_arch = "wasm32"), feature = "ivim_2_1_1"))] +decode_some_type!(crate::standards::ivim_2_1_1::ivim_pdu_descriptions::IVIM); +#[cfg(all(not(target_arch = "wasm32"), feature = "ivim_2_1_1"))] +decode_some_type!(crate::standards::ivim_2_1_1::ivi::IviStructure); + +#[cfg(all(not(target_arch = "wasm32"), feature = "srem_2_2_1"))] +decode_some_type!(crate::standards::srem_2_2_1::srem_pdu_descriptions::SREM); +#[cfg(all(not(target_arch = "wasm32"), feature = "_dsrc_2_2_1"))] +decode_some_type!(crate::standards::dsrc_2_2_1::etsi_its_dsrc::SignalRequestMessage); + +#[cfg(all(not(target_arch = "wasm32"), feature = "ssem_2_2_1"))] +decode_some_type!(crate::standards::ssem_2_2_1::ssem_pdu_descriptions::SSEM); +#[cfg(all(not(target_arch = "wasm32"), feature = "_dsrc_2_2_1"))] +decode_some_type!(crate::standards::dsrc_2_2_1::etsi_its_dsrc::SignalStatusMessage); + +#[cfg(all(not(target_arch = "wasm32"), feature = "cpm_2_1_1"))] +decode_some_type!(crate::standards::cpm_2_1_1::cpm_pdu_descriptions::CollectivePerceptionMessage); +#[cfg(all(not(target_arch = "wasm32"), feature = "cpm_2_1_1"))] +decode_some_type!(crate::standards::cpm_2_1_1::cpm_pdu_descriptions::CpmPayload); + +#[cfg(all(not(target_arch = "wasm32"), feature = "cpm_1"))] +decode_some_type!(crate::standards::cpm_1::cpm_pdu_descriptions::CPM); +#[cfg(all(not(target_arch = "wasm32"), feature = "cpm_1"))] +decode_some_type!(crate::standards::cpm_1::cpm_pdu_descriptions::CollectivePerceptionMessage); + #[cfg(all(target_arch = "wasm32", feature = "v2x", feature = "json"))] #[wasm_bindgen(js_name = decode)] /// Decodes an ITS message of undefined type. diff --git a/src/en.rs b/src/en.rs index 99e0e9c..00d00fb 100644 --- a/src/en.rs +++ b/src/en.rs @@ -237,6 +237,122 @@ pub fn encode_to_jer_str( .map_err(crate::map_err_to_string) } +#[cfg(all(not(target_arch = "wasm32"), feature = "_etsi"))] +/// Adds encoding methods to encodable types +/// +/// This doesn't provide anything more than the encode functions, but adds them as methods for ease of use. +macro_rules! encode_some_type { + ($t:ty) => { + impl $t { + /// Encodes [`Self`] to UPER buffer + /// + /// # Errors + /// Returns a human-readable string when decoding failed + pub fn encode_to_uper(&self) -> Result { + crate::en::encode_to_uper(&self) + } + + /// Encodes [`Self`] to XER buffer + /// + /// # Errors + /// Returns a human-readable string when decoding failed + pub fn encode_to_xer_buf(&self) -> Result { + crate::en::encode_to_xer_buf(&self) + } + + /// Encodes [`Self`] to XER buffer + /// + /// # Errors + /// Returns a human-readable string when decoding failed + pub fn encode_to_xer_str( + &self, + ) -> Result { + crate::en::encode_to_xer_str(&self) + } + + /// Encodes [`Self`] to JER buffer + /// + /// # Errors + /// Returns a human-readable string when decoding failed + pub fn encode_to_jer_buf(&self) -> Result { + crate::en::encode_to_jer_buf(&self) + } + + /// Encodes [`Self`] to JER buffer + /// + /// # Errors + /// Returns a human-readable string when decoding failed + pub fn encode_to_jer_str( + &self, + ) -> Result { + crate::en::encode_to_jer_str(&self) + } + } + }; +} + +#[cfg(all(not(target_arch = "wasm32"), feature = "_cdd_1_3_1_1"))] +encode_some_type!(crate::standards::cdd_1_3_1_1::its_container::ItsPduHeader); +#[cfg(all(not(target_arch = "wasm32"), feature = "_cdd_2_2_1"))] +encode_some_type!(crate::standards::cdd_2_2_1::etsi_its_cdd::ItsPduHeader); + +#[cfg(all(not(target_arch = "wasm32"), feature = "denm_2_2_1"))] +encode_some_type!(crate::standards::denm_2_2_1::denm_pdu_description::DENM); +#[cfg(all(not(target_arch = "wasm32"), feature = "denm_2_2_1"))] +encode_some_type!(crate::standards::denm_2_2_1::denm_pdu_description::DenmPayload); + +#[cfg(all(not(target_arch = "wasm32"), feature = "denm_1_3_1"))] +encode_some_type!(crate::standards::denm_1_3_1::denm_pdu_descriptions::DENM); +#[cfg(all(not(target_arch = "wasm32"), feature = "denm_1_3_1"))] +encode_some_type!( + crate::standards::denm_1_3_1::denm_pdu_descriptions::DecentralizedEnvironmentalNotificationMessage +); + +#[cfg(all(not(target_arch = "wasm32"), feature = "cam_1_4_1"))] +encode_some_type!(crate::standards::cam_1_4_1::cam_pdu_descriptions::CAM); +#[cfg(all(not(target_arch = "wasm32"), feature = "cam_1_4_1"))] +encode_some_type!(crate::standards::cam_1_4_1::cam_pdu_descriptions::CoopAwareness); + +#[cfg(all(not(target_arch = "wasm32"), feature = "spatem_2_2_1"))] +encode_some_type!(crate::standards::spatem_2_2_1::spatem_pdu_descriptions::SPATEM); +#[cfg(all(not(target_arch = "wasm32"), feature = "_dsrc_2_2_1"))] +encode_some_type!(crate::standards::dsrc_2_2_1::etsi_its_dsrc::SPAT); + +#[cfg(all(not(target_arch = "wasm32"), feature = "mapem_2_2_1"))] +encode_some_type!(crate::standards::mapem_2_2_1::mapem_pdu_descriptions::MAPEM); +#[cfg(all(not(target_arch = "wasm32"), feature = "_dsrc_2_2_1"))] +encode_some_type!(crate::standards::dsrc_2_2_1::etsi_its_dsrc::MapData); + +#[cfg(all(not(target_arch = "wasm32"), feature = "ivim_2_2_1"))] +encode_some_type!(crate::standards::ivim_2_2_1::ivim_pdu_descriptions::IVIM); +#[cfg(all(not(target_arch = "wasm32"), feature = "ivim_2_2_1"))] +encode_some_type!(crate::standards::ivim_2_2_1::ivi::IviStructure); + +#[cfg(all(not(target_arch = "wasm32"), feature = "ivim_2_1_1"))] +encode_some_type!(crate::standards::ivim_2_1_1::ivim_pdu_descriptions::IVIM); +#[cfg(all(not(target_arch = "wasm32"), feature = "ivim_2_1_1"))] +encode_some_type!(crate::standards::ivim_2_1_1::ivi::IviStructure); + +#[cfg(all(not(target_arch = "wasm32"), feature = "srem_2_2_1"))] +encode_some_type!(crate::standards::srem_2_2_1::srem_pdu_descriptions::SREM); +#[cfg(all(not(target_arch = "wasm32"), feature = "_dsrc_2_2_1"))] +encode_some_type!(crate::standards::dsrc_2_2_1::etsi_its_dsrc::SignalRequestMessage); + +#[cfg(all(not(target_arch = "wasm32"), feature = "ssem_2_2_1"))] +encode_some_type!(crate::standards::ssem_2_2_1::ssem_pdu_descriptions::SSEM); +#[cfg(all(not(target_arch = "wasm32"), feature = "_dsrc_2_2_1"))] +encode_some_type!(crate::standards::dsrc_2_2_1::etsi_its_dsrc::SignalStatusMessage); + +#[cfg(all(not(target_arch = "wasm32"), feature = "cpm_2_1_1"))] +encode_some_type!(crate::standards::cpm_2_1_1::cpm_pdu_descriptions::CollectivePerceptionMessage); +#[cfg(all(not(target_arch = "wasm32"), feature = "cpm_2_1_1"))] +encode_some_type!(crate::standards::cpm_2_1_1::cpm_pdu_descriptions::CpmPayload); + +#[cfg(all(not(target_arch = "wasm32"), feature = "cpm_1"))] +encode_some_type!(crate::standards::cpm_1::cpm_pdu_descriptions::CPM); +#[cfg(all(not(target_arch = "wasm32"), feature = "cpm_1"))] +encode_some_type!(crate::standards::cpm_1::cpm_pdu_descriptions::CollectivePerceptionMessage); + #[cfg(all(target_arch = "wasm32", feature = "json"))] #[wasm_bindgen(js_name = encodeDenm)] /// Encodes a DENM message into binary UPER with optional headers