diff --git a/src/de.rs b/src/de.rs index 743ad91..806ffb7 100644 --- a/src/de.rs +++ b/src/de.rs @@ -4,70 +4,19 @@ #![allow(non_snake_case)] -#[cfg(feature = "_etsi")] -use alloc::borrow::ToOwned; -#[cfg(any( - feature = "_etsi", - all(target_arch = "wasm32", feature = "v2x", feature = "json"), - all(test, feature = "_etsi") -))] -use alloc::string::String; -#[cfg(any(feature = "_etsi", feature = "transport"))] -use alloc::string::ToString; -#[cfg(all(target_arch = "wasm32", feature = "v2x", feature = "json"))] -use core::fmt::Write; -#[cfg(any( - feature = "_etsi", - all(target_arch = "wasm32", feature = "v2x", feature = "json"), - all(test, feature = "_etsi") -))] -use core::primitive::str; - -#[cfg(all(target_arch = "wasm32", feature = "v2x", feature = "json"))] -use geonetworking::Encode; -#[cfg(feature = "transport")] -use geonetworking::{Decode, NextAfterCommon, Packet}; -#[cfg(any( - feature = "_etsi", - all(target_arch = "wasm32", feature = "v2x", feature = "json"), - all(test, feature = "_etsi") -))] -use nom::FindSubstring; #[cfg(all(target_arch = "wasm32", feature = "v2x", feature = "json"))] use wasm_bindgen::prelude::*; #[cfg(all(target_arch = "wasm32", feature = "v2x", feature = "json"))] -use crate::JsonItsMessage; -#[cfg(any(feature = "transport", feature = "_etsi"))] -use crate::map_err_to_string; -#[cfg(feature = "_etsi")] -use crate::pcap::{remove_pcap_headers, remove_wlan_headers}; -#[cfg(feature = "transport")] -use crate::transport::TransportHeader; -#[cfg(feature = "transport")] -use crate::transport::{ - BasicTransportAHeader, - BasicTransportBHeader, - IPv6Header, - decode::Decode as TransportDecode, -}; -#[cfg(any( - feature = "_etsi", - all(target_arch = "wasm32", feature = "v2x", feature = "json"), - all(test, feature = "_etsi") -))] -use crate::{EncodingRules, standards::cdd_2_2_1::etsi_its_cdd::ItsPduHeader}; -#[cfg(feature = "_etsi")] -use crate::{Headers, ItsMessage, standards}; - +use crate::transport::decode::Decode as _; #[cfg(all(target_arch = "wasm32", feature = "v2x", feature = "json"))] macro_rules! btp { ($btp_ty:ty, $input:ident) => { <$btp_ty>::decode($input) - .map_err(map_err_to_string) + .map_err(crate::map_err_to_string) .and_then(|(rem, tp)| { tp.encode_to_json() - .map_err(map_err_to_string) + .map_err(crate::map_err_to_string) .map(|json| (rem, json)) }) }; @@ -88,16 +37,24 @@ macro_rules! btp { /// /// # Errors /// Throws string error on decoding errors. -pub fn decode(input: &'_ [u8], headers: Headers) -> Result, alloc::string::String> { +pub fn decode( + input: &'_ [u8], + headers: crate::Headers, +) -> Result, alloc::string::String> { + use alloc::borrow::ToOwned as _; + use alloc::string::ToString as _; + + use crate::{ItsMessage, standards}; + let (input, transport, geonetworking) = match headers { - Headers::None => Ok((input, None, None)), - Headers::GnBtp => { + crate::Headers::None => Ok((input, None, None)), + crate::Headers::GnBtp => { decode_gn_btp_headers(input).map(|(rem, tp, gn)| (rem, Some(tp), Some(gn))) } - Headers::IEEE802LlcGnBtp => remove_wlan_headers(input) + crate::Headers::IEEE802LlcGnBtp => crate::pcap::remove_wlan_headers(input) .and_then(decode_gn_btp_headers) .map(|(rem, tp, gn)| (rem, Some(tp), Some(gn))), - Headers::RadioTap802LlcGnBtp => remove_pcap_headers(input) + crate::Headers::RadioTap802LlcGnBtp => crate::pcap::remove_pcap_headers(input) .and_then(decode_gn_btp_headers) .map(|(rem, tp, gn)| (rem, Some(tp), Some(gn))), }?; @@ -106,7 +63,7 @@ pub fn decode(input: &'_ [u8], headers: Headers) -> Result, alloc let input = match msg_type { // workaround to parse DENM and IVIM as XER/ JER which still uses old CDD 1 | 6 => { - if let Ok(data) = str::from_utf8(input) + if let Ok(data) = core::primitive::str::from_utf8(input) && (data.trim_start().starts_with('<') || data.trim_start().starts_with('{')) && data.contains("messageID") { @@ -121,7 +78,7 @@ pub fn decode(input: &'_ [u8], headers: Headers) -> Result, alloc } // workaround to parse MAPEM, SPATEM, SREM, SSEM as XER/ JER which still uses old CDD 4 | 5 | 9 | 10 => { - if let Ok(data) = str::from_utf8(input) { + if let Ok(data) = core::primitive::str::from_utf8(input) { // live-patch messageID and stationID in PDU header for MAPEMs, SPATEMs, SREMs and SSEMs // Note: an SREM may contain stationID in the requestor, but that's actually fine!!! So we shall only patch the PDU header if data.trim_start().starts_with('<') && data.contains("messageID") { @@ -261,7 +218,7 @@ pub fn decode(input: &'_ [u8], headers: Headers) -> Result, alloc "Unsupported ITS message type: Found message id {message_i_d}." )) } - }.map_err(map_err_to_string) + }.map_err(crate::map_err_to_string) } #[cfg(feature = "transport")] @@ -271,27 +228,49 @@ pub fn decode(input: &'_ [u8], headers: Headers) -> Result, alloc /// Returns human-readable error descriptions when decoding failed pub fn decode_gn_btp_headers( input: &'_ [u8], -) -> Result<(&'_ [u8], alloc::boxed::Box, Packet<'_>), alloc::string::String> { - let result = Packet::decode(input).map_err(map_err_to_string)?; +) -> Result< + ( + &'_ [u8], + alloc::boxed::Box, + geonetworking::Packet<'_>, + ), + alloc::string::String, +> { + use alloc::string::ToString as _; + + use geonetworking::Decode as _; + + use crate::transport::decode::Decode as _; + + let result = geonetworking::Packet::decode(input).map_err(crate::map_err_to_string)?; let payload = match &result.decoded { - Packet::Unsecured { payload, .. } => *payload, - s @ Packet::Secured { .. } => s + geonetworking::Packet::Unsecured { payload, .. } => *payload, + s @ geonetworking::Packet::Secured { .. } => s .secured_payload_after_gn() .ok_or("No payload in secured geonetworking header!")?, }; let (remaining, tp) = match result.decoded.common().next_header { - NextAfterCommon::Any => { + geonetworking::NextAfterCommon::Any => { Err("Currently, only BTP and IPv6 Headers can be decoded!".to_string()) } - NextAfterCommon::BTPA => BasicTransportAHeader::decode(payload) - .map(|(rem, btpa)| (rem, TransportHeader::BtpA(btpa))) - .map_err(map_err_to_string), - NextAfterCommon::BTPB => BasicTransportBHeader::decode(payload) - .map(|(rem, btpb)| (rem, TransportHeader::BtpB(btpb))) - .map_err(map_err_to_string), - NextAfterCommon::IPv6 => IPv6Header::decode(payload) - .map(|(rem, ipv6)| (rem, TransportHeader::IPv6(alloc::boxed::Box::new(ipv6)))) - .map_err(map_err_to_string), + geonetworking::NextAfterCommon::BTPA => { + crate::transport::BasicTransportAHeader::decode(payload) + .map(|(rem, btpa)| (rem, crate::transport::TransportHeader::BtpA(btpa))) + .map_err(crate::map_err_to_string) + } + geonetworking::NextAfterCommon::BTPB => { + crate::transport::BasicTransportBHeader::decode(payload) + .map(|(rem, btpb)| (rem, crate::transport::TransportHeader::BtpB(btpb))) + .map_err(crate::map_err_to_string) + } + geonetworking::NextAfterCommon::IPv6 => crate::transport::IPv6Header::decode(payload) + .map(|(rem, ipv6)| { + ( + rem, + crate::transport::TransportHeader::IPv6(alloc::boxed::Box::new(ipv6)), + ) + }) + .map_err(crate::map_err_to_string), }?; Ok((remaining, alloc::boxed::Box::new(tp), result.decoded)) } @@ -307,9 +286,9 @@ pub fn decode_gn_btp_headers( /// Throws string error on decoding errors. pub fn decode_to( message: &[u8], - headersPresent: Headers, - outputEncodingRules: EncodingRules, -) -> Result { + headersPresent: crate::Headers, + outputEncodingRules: crate::EncodingRules, +) -> Result { let (input, mut etsi_json) = optionally_decode_headers(message, headersPresent)?; let (input_encoding_rules, protocol_version, message_type) = message_type(input)?; let (msg_ty, decoded) = match (message_type, protocol_version) { @@ -318,7 +297,7 @@ pub fn decode_to( decode_denm( input, Some(211), - Headers::None, + crate::Headers::None, input_encoding_rules, outputEncodingRules, )? @@ -329,7 +308,7 @@ pub fn decode_to( decode_denm( input, Some(131), - Headers::None, + crate::Headers::None, input_encoding_rules, outputEncodingRules, )? @@ -340,7 +319,7 @@ pub fn decode_to( decode_cam( input, None, - Headers::None, + crate::Headers::None, input_encoding_rules, outputEncodingRules, )? @@ -351,7 +330,7 @@ pub fn decode_to( decode_spatem( input, None, - Headers::None, + crate::Headers::None, input_encoding_rules, outputEncodingRules, )? @@ -362,7 +341,7 @@ pub fn decode_to( decode_mapem( input, None, - Headers::None, + crate::Headers::None, input_encoding_rules, outputEncodingRules, )? @@ -373,7 +352,7 @@ pub fn decode_to( decode_ivim( input, Some(221), - Headers::None, + crate::Headers::None, input_encoding_rules, outputEncodingRules, )? @@ -384,7 +363,7 @@ pub fn decode_to( decode_ivim( input, Some(131), - Headers::None, + crate::Headers::None, input_encoding_rules, outputEncodingRules, )? @@ -395,7 +374,7 @@ pub fn decode_to( decode_srem( input, None, - Headers::None, + crate::Headers::None, input_encoding_rules, outputEncodingRules, )? @@ -406,7 +385,7 @@ pub fn decode_to( decode_ssem( input, None, - Headers::None, + crate::Headers::None, input_encoding_rules, outputEncodingRules, )? @@ -417,7 +396,7 @@ pub fn decode_to( decode_cpm( input, Some(211), - Headers::None, + crate::Headers::None, input_encoding_rules, outputEncodingRules, )? @@ -428,7 +407,7 @@ pub fn decode_to( decode_cpm( input, Some(131), - Headers::None, + crate::Headers::None, input_encoding_rules, outputEncodingRules, )? @@ -450,14 +429,16 @@ pub fn decode_to( all(target_arch = "wasm32", feature = "v2x", feature = "json"), all(test, feature = "_etsi") ))] -fn message_type(input: &[u8]) -> Result<(EncodingRules, u8, u8), String> { - let encoding_rules = match str::from_utf8(input) { - Ok(s) if s.trim_start().starts_with('<') => EncodingRules::XER, - Ok(s) if s.trim_start().starts_with('{') => EncodingRules::JER, - _ => EncodingRules::UPER, +fn message_type(input: &[u8]) -> Result<(crate::EncodingRules, u8, u8), alloc::string::String> { + use nom::FindSubstring as _; + + let encoding_rules = match core::primitive::str::from_utf8(input) { + Ok(s) if s.trim_start().starts_with('<') => crate::EncodingRules::XER, + Ok(s) if s.trim_start().starts_with('{') => crate::EncodingRules::JER, + _ => crate::EncodingRules::UPER, }; match encoding_rules { - EncodingRules::XER => { + crate::EncodingRules::XER => { let message_id_start = input .find_substring("messageID>") .or(input.find_substring("messageId>")) @@ -467,11 +448,12 @@ fn message_type(input: &[u8]) -> Result<(EncodingRules, u8, u8), String> { .find_substring("") .ok_or("Failed to determine protocol version.")? @@ -480,19 +462,22 @@ fn message_type(input: &[u8]) -> Result<(EncodingRules, u8, u8), String> { .find_substring(" { + crate::EncodingRules::JER => { let message_id = input .find_substring("messageID\":") .or(input.find_substring("messageId\":")) - .ok_or(String::from("Failed to determine message ID.")) + .ok_or(alloc::string::String::from( + "Failed to determine message ID.", + )) .and_then(|start| { let mut end = start + 11; let mut value = input[end] as char; @@ -500,13 +485,15 @@ fn message_type(input: &[u8]) -> Result<(EncodingRules, u8, u8), String> { end += 1; value = input[end] as char; } - str::from_utf8(&input[(start + 11)..end]) - .map_err(map_err_to_string) - .and_then(|s| s.trim().parse::().map_err(map_err_to_string)) + core::primitive::str::from_utf8(&input[(start + 11)..end]) + .map_err(crate::map_err_to_string) + .and_then(|s| s.trim().parse::().map_err(crate::map_err_to_string)) })?; let protocol_version = input .find_substring("protocolVersion\":") - .ok_or(String::from("Failed to determine message ID.")) + .ok_or(alloc::string::String::from( + "Failed to determine message ID.", + )) .and_then(|start| { let mut end = start + 17; let mut value = input[end] as char; @@ -514,15 +501,15 @@ fn message_type(input: &[u8]) -> Result<(EncodingRules, u8, u8), String> { end += 1; value = input[end] as char; } - str::from_utf8(&input[(start + 17)..end]) - .map_err(map_err_to_string) - .and_then(|s| s.trim().parse::().map_err(map_err_to_string)) + core::primitive::str::from_utf8(&input[(start + 17)..end]) + .map_err(crate::map_err_to_string) + .and_then(|s| s.trim().parse::().map_err(crate::map_err_to_string)) })?; Ok((encoding_rules, protocol_version, message_id)) } - EncodingRules::UPER => EncodingRules::UPER + crate::EncodingRules::UPER => crate::EncodingRules::UPER .codec() - .decode_from_binary::(input) + .decode_from_binary::(input) .map(|header| { ( encoding_rules, @@ -530,7 +517,7 @@ fn message_type(input: &[u8]) -> Result<(EncodingRules, u8, u8), String> { header.message_id.0, ) }) - .map_err(map_err_to_string), + .map_err(crate::map_err_to_string), } } @@ -538,10 +525,10 @@ fn message_type(input: &[u8]) -> Result<(EncodingRules, u8, u8), String> { fn decode_denm( denm: &[u8], mut version: Option, - headers_present: Headers, - input_encoding_rules: EncodingRules, - output_encoding_rules: EncodingRules, -) -> Result { + headers_present: crate::Headers, + input_encoding_rules: crate::EncodingRules, + output_encoding_rules: crate::EncodingRules, +) -> Result { let (input, mut etsi_json) = optionally_decode_headers(denm, headers_present)?; if version.is_none() { version = match input.first() { @@ -552,16 +539,12 @@ fn decode_denm( } etsi_json.its = match version { Some(131) => Some(transcode::< - standards::denm_1_3_1::denm_pdu_descriptions::DENM, + crate::standards::denm_1_3_1::denm_pdu_descriptions::DENM, >(input, input_encoding_rules, output_encoding_rules)) .transpose(), - None | Some(221) => Some( - transcode::( - input, - input_encoding_rules, - output_encoding_rules, - ), - ) + None | Some(221) => Some(transcode::< + crate::standards::denm_2_2_1::denm_pdu_description::DENM, + >(input, input_encoding_rules, output_encoding_rules)) .transpose(), _ => { return Err( @@ -576,19 +559,15 @@ fn decode_denm( fn decode_cam( cam: &[u8], version: Option, - headers_present: Headers, - input_encoding_rules: EncodingRules, - output_encoding_rules: EncodingRules, -) -> Result { + headers_present: crate::Headers, + input_encoding_rules: crate::EncodingRules, + output_encoding_rules: crate::EncodingRules, +) -> Result { let (input, mut etsi_json) = optionally_decode_headers(cam, headers_present)?; etsi_json.its = match version { - None | Some(141) => Some( - transcode::( - input, - input_encoding_rules, - output_encoding_rules, - ), - ) + None | Some(141) => Some(transcode::< + crate::standards::cam_1_4_1::cam_pdu_descriptions::CAM, + >(input, input_encoding_rules, output_encoding_rules)) .transpose(), _ => return Err("Unsupported DENM version: Supported CAM version is 141.".to_string()), }?; @@ -599,14 +578,14 @@ fn decode_cam( fn decode_mapem( mapem: &[u8], version: Option, - headers_present: Headers, - input_encoding_rules: EncodingRules, - output_encoding_rules: EncodingRules, -) -> Result { + headers_present: crate::Headers, + input_encoding_rules: crate::EncodingRules, + output_encoding_rules: crate::EncodingRules, +) -> Result { let (input, mut etsi_json) = optionally_decode_headers(mapem, headers_present)?; etsi_json.its = match version { None | Some(221) => Some(transcode::< - standards::mapem_2_2_1::mapem_pdu_descriptions::MAPEM, + crate::standards::mapem_2_2_1::mapem_pdu_descriptions::MAPEM, >(input, input_encoding_rules, output_encoding_rules)) .transpose(), _ => return Err("Unsupported MAPEM version: Supported MAPEM version is 221.".to_string()), @@ -618,14 +597,14 @@ fn decode_mapem( fn decode_spatem( spatem: &[u8], version: Option, - headers_present: Headers, - input_encoding_rules: EncodingRules, - output_encoding_rules: EncodingRules, -) -> Result { + headers_present: crate::Headers, + input_encoding_rules: crate::EncodingRules, + output_encoding_rules: crate::EncodingRules, +) -> Result { let (input, mut etsi_json) = optionally_decode_headers(spatem, headers_present)?; etsi_json.its = match version { None | Some(131) => Some(transcode::< - standards::spatem_2_2_1::spatem_pdu_descriptions::SPATEM, + crate::standards::spatem_2_2_1::spatem_pdu_descriptions::SPATEM, >(input, input_encoding_rules, output_encoding_rules)) .transpose(), _ => { @@ -639,10 +618,10 @@ fn decode_spatem( fn decode_ivim( ivim: &[u8], mut version: Option, - headers_present: Headers, - input_encoding_rules: EncodingRules, - output_encoding_rules: EncodingRules, -) -> Result { + headers_present: crate::Headers, + input_encoding_rules: crate::EncodingRules, + output_encoding_rules: crate::EncodingRules, +) -> Result { let (input, mut etsi_json) = optionally_decode_headers(ivim, headers_present)?; if version.is_none() { version = match input.first() { @@ -653,11 +632,11 @@ fn decode_ivim( } etsi_json.its = match version { Some(131) | Some(211) => Some(transcode::< - standards::ivim_2_1_1::ivim_pdu_descriptions::IVIM, + crate::standards::ivim_2_1_1::ivim_pdu_descriptions::IVIM, >(input, input_encoding_rules, output_encoding_rules)) .transpose(), None | Some(221) => Some(transcode::< - standards::ivim_2_2_1::ivim_pdu_descriptions::IVIM, + crate::standards::ivim_2_2_1::ivim_pdu_descriptions::IVIM, >(input, input_encoding_rules, output_encoding_rules)) .transpose(), _ => { @@ -674,14 +653,14 @@ fn decode_ivim( fn decode_srem( srem: &[u8], version: Option, - headers_present: Headers, - input_encoding_rules: EncodingRules, - output_encoding_rules: EncodingRules, -) -> Result { + headers_present: crate::Headers, + input_encoding_rules: crate::EncodingRules, + output_encoding_rules: crate::EncodingRules, +) -> Result { let (input, mut etsi_json) = optionally_decode_headers(srem, headers_present)?; etsi_json.its = match version { None | Some(221) => Some(transcode::< - standards::srem_2_2_1::srem_pdu_descriptions::SREM, + crate::standards::srem_2_2_1::srem_pdu_descriptions::SREM, >(input, input_encoding_rules, output_encoding_rules)) .transpose(), _ => return Err("Unsupported SREM version: Supported SREM version is 221.".to_string()), @@ -693,10 +672,10 @@ fn decode_srem( fn decode_cpm( cpm: &[u8], mut version: Option, - headers_present: Headers, - input_encoding_rules: EncodingRules, - output_encoding_rules: EncodingRules, -) -> Result { + headers_present: crate::Headers, + input_encoding_rules: crate::EncodingRules, + output_encoding_rules: crate::EncodingRules, +) -> Result { let (input, mut etsi_json) = optionally_decode_headers(cpm, headers_present)?; if version.is_none() { version = match input.first() { @@ -707,14 +686,12 @@ fn decode_cpm( } etsi_json.its = match version { None | Some(211) => Some(transcode::< - standards::cpm_2_1_1::cpm_pdu_descriptions::CollectivePerceptionMessage, + crate::standards::cpm_2_1_1::cpm_pdu_descriptions::CollectivePerceptionMessage, >(input, input_encoding_rules, output_encoding_rules)) .transpose(), - Some(131) => Some(transcode::( - input, - input_encoding_rules, - output_encoding_rules, - )) + Some(131) => Some(transcode::< + crate::standards::cpm_1::cpm_pdu_descriptions::CPM, + >(input, input_encoding_rules, output_encoding_rules)) .transpose(), _ => { return Err( @@ -729,14 +706,14 @@ fn decode_cpm( fn decode_ssem( ssem: &[u8], version: Option, - headers_present: Headers, - input_encoding_rules: EncodingRules, - output_encoding_rules: EncodingRules, -) -> Result { + headers_present: crate::Headers, + input_encoding_rules: crate::EncodingRules, + output_encoding_rules: crate::EncodingRules, +) -> Result { let (input, mut etsi_json) = optionally_decode_headers(ssem, headers_present)?; etsi_json.its = match version { None | Some(221) => Some(transcode::< - standards::ssem_2_2_1::ssem_pdu_descriptions::SSEM, + crate::standards::ssem_2_2_1::ssem_pdu_descriptions::SSEM, >(input, input_encoding_rules, output_encoding_rules)) .transpose(), _ => return Err("Unsupported SSEM version: Supported SSEM version is 221.".to_string()), @@ -747,25 +724,27 @@ fn decode_ssem( #[cfg(all(target_arch = "wasm32", feature = "v2x", feature = "json"))] pub fn optionally_decode_headers( input: &[u8], - headers: Headers, -) -> Result<(&[u8], JsonItsMessage), String> { + headers: crate::Headers, +) -> Result<(&[u8], crate::JsonItsMessage), String> { match headers { - Headers::None => Ok((input, JsonItsMessage::default())), - Headers::GnBtp => transcode_gn_tp_to_json(input), - Headers::IEEE802LlcGnBtp => remove_wlan_headers(input).and_then(transcode_gn_tp_to_json), - Headers::RadioTap802LlcGnBtp => { - remove_pcap_headers(input).and_then(transcode_gn_tp_to_json) + crate::Headers::None => Ok((input, crate::JsonItsMessage::default())), + crate::Headers::GnBtp => transcode_gn_tp_to_json(input), + crate::Headers::IEEE802LlcGnBtp => { + crate::pcap::remove_wlan_headers(input).and_then(transcode_gn_tp_to_json) + } + crate::Headers::RadioTap802LlcGnBtp => { + crate::pcap::remove_pcap_headers(input).and_then(transcode_gn_tp_to_json) } } } #[cfg(all(target_arch = "wasm32", feature = "v2x", feature = "json"))] -fn transcode_gn_tp_to_json(input: &[u8]) -> Result<(&[u8], JsonItsMessage), String> { +fn transcode_gn_tp_to_json(input: &[u8]) -> Result<(&[u8], crate::JsonItsMessage), String> { decode_geonetworking_header(input).and_then(|(remaining, gn_json, next_header)| { decode_transport_header(remaining, next_header).map(|(rem, tp)| { ( rem, - JsonItsMessage { + crate::JsonItsMessage { geonetworking: Some(gn_json), transport: Some(tp), ..Default::default() @@ -776,11 +755,18 @@ fn transcode_gn_tp_to_json(input: &[u8]) -> Result<(&[u8], JsonItsMessage), Stri } #[cfg(all(target_arch = "wasm32", feature = "v2x", feature = "json"))] -fn decode_geonetworking_header(input: &[u8]) -> Result<(&[u8], String, NextAfterCommon), String> { - let result = Packet::decode(input).map_err(map_err_to_string)?; - let gn_json = result.decoded.encode_to_json().map_err(map_err_to_string)?; +fn decode_geonetworking_header( + input: &[u8], +) -> Result<(&[u8], String, geonetworking::NextAfterCommon), String> { + use geonetworking::{Decode as _, Encode as _}; + + let result = geonetworking::Packet::decode(input).map_err(crate::map_err_to_string)?; + let gn_json = result + .decoded + .encode_to_json() + .map_err(crate::map_err_to_string)?; match result.decoded { - Packet::Unsecured { + geonetworking::Packet::Unsecured { common, payload, .. } => Ok((payload, gn_json, common.next_header)), p => p @@ -793,16 +779,21 @@ fn decode_geonetworking_header(input: &[u8]) -> Result<(&[u8], String, NextAfter #[cfg(all(target_arch = "wasm32", feature = "v2x", feature = "json"))] fn decode_transport_header( input: &[u8], - header_type: NextAfterCommon, + header_type: geonetworking::NextAfterCommon, ) -> Result<(&[u8], String), String> { match header_type { - NextAfterCommon::Any => { + geonetworking::NextAfterCommon::Any => { Err("Currently, only BTP and IPv6 Headers can be decoded!".to_string()) } - NextAfterCommon::BTPA => btp![BasicTransportAHeader, input], - NextAfterCommon::BTPB => btp![BasicTransportBHeader, input], - NextAfterCommon::IPv6 => { - let (remaining, ipv6) = IPv6Header::decode(input).map_err(map_err_to_string)?; + geonetworking::NextAfterCommon::BTPA => { + btp![crate::transport::BasicTransportAHeader, input] + } + geonetworking::NextAfterCommon::BTPB => { + btp![crate::transport::BasicTransportBHeader, input] + } + geonetworking::NextAfterCommon::IPv6 => { + let (remaining, ipv6) = + crate::transport::IPv6Header::decode(input).map_err(crate::map_err_to_string)?; Ok((remaining, to_ipv6_debug(ipv6))) } } @@ -811,35 +802,37 @@ fn decode_transport_header( #[cfg(all(target_arch = "wasm32", feature = "v2x", feature = "json"))] fn transcode( input: &[u8], - input_encoding_rules: EncodingRules, - output_encoding_rules: EncodingRules, + input_encoding_rules: crate::EncodingRules, + output_encoding_rules: crate::EncodingRules, ) -> Result { - if let (EncodingRules::UPER, EncodingRules::UPER) = + use core::fmt::Write as _; + + if let (crate::EncodingRules::UPER, crate::EncodingRules::UPER) = (input_encoding_rules, output_encoding_rules) { return input.iter().try_fold(String::new(), |mut acc, byte| { write!(&mut acc, "{byte:02X?}") - .map_err(map_err_to_string) + .map_err(crate::map_err_to_string) .map(|_| acc) }); } let decoded: T = input_encoding_rules .codec() .decode_from_binary(input) - .map_err(map_err_to_string)?; + .map_err(crate::map_err_to_string)?; match output_encoding_rules { - EncodingRules::UPER => rasn::uper::encode(&decoded) + crate::EncodingRules::UPER => rasn::uper::encode(&decoded) .map(hex::encode) - .map_err(map_err_to_string), + .map_err(crate::map_err_to_string), o => o .codec() .encode_to_string(&decoded) - .map_err(map_err_to_string), + .map_err(crate::map_err_to_string), } } #[cfg(all(target_arch = "wasm32", feature = "v2x", feature = "json"))] -fn to_ipv6_debug(ipv6: IPv6Header) -> String { +fn to_ipv6_debug(ipv6: crate::transport::IPv6Header) -> String { alloc::format!(r#"{{"ipv6Debug":"{ipv6:?}"}}"#) } diff --git a/src/en.rs b/src/en.rs index 735c1d7..09e6a89 100644 --- a/src/en.rs +++ b/src/en.rs @@ -6,28 +6,9 @@ #[cfg(not(target_arch = "wasm32"))] use alloc::string::ToString; -#[cfg(any( - all(target_arch = "wasm32", feature = "json"), - not(target_arch = "wasm32") -))] -use geonetworking::{Encode, ExtendedHeader, HeaderType, UnsecuredHeader}; #[cfg(all(target_arch = "wasm32", feature = "json"))] use wasm_bindgen::prelude::*; -#[cfg(not(target_arch = "wasm32"))] -use crate::ItsMessage; -#[cfg(all(target_arch = "wasm32", feature = "json"))] -use crate::JsonItsMessage; -#[cfg(any( - all(target_arch = "wasm32", feature = "json"), - not(target_arch = "wasm32") -))] -use crate::map_err_to_string; -#[cfg(all(target_arch = "wasm32", feature = "json"))] -use crate::transport::encode::Encode as TpEncode; -#[cfg(not(target_arch = "wasm32"))] -use crate::{EncodingRules, Packet}; - #[cfg(all(target_arch = "wasm32", feature = "json"))] /// Wasm output is a Javascript uint8 array pub type Encoded = js_sys::Uint8Array; @@ -36,7 +17,7 @@ pub type Encoded = js_sys::Uint8Array; pub type Encoded = alloc::vec::Vec; #[cfg(not(target_arch = "wasm32"))] -impl ItsMessage<'_> { +impl crate::ItsMessage<'_> { #[allow(clippy::too_many_lines)] /// Encodes an ITS message with optional headers. /// @@ -51,7 +32,12 @@ impl ItsMessage<'_> { /// /// # Errors /// Gives a human-readable error description when ASN.1 parsing failed or an unexpected set of headers was found. - pub fn encode(self, encoding_rules: EncodingRules) -> Result { + pub fn encode( + self, + encoding_rules: crate::EncodingRules, + ) -> Result { + use crate::ItsMessage; + let (geo, tp, mut etsi_uper) = match self { #[cfg(feature = "denm_1_3_1")] ItsMessage::DenmV1 { @@ -153,19 +139,19 @@ impl ItsMessage<'_> { .encode_to_binary(&etsi) .map(|enc| (geonetworking, transport, enc)), } - .map_err(map_err_to_string)?; + .map_err(crate::map_err_to_string)?; - if encoding_rules == EncodingRules::UPER { + if encoding_rules == crate::EncodingRules::UPER { match (tp, geo) { (None, None) => Ok(etsi_uper), ( Some(tp), - Some(Packet::Unsecured { + Some(geonetworking::Packet::Unsecured { basic, common, extended, .. - } | Packet::Secured { + } | geonetworking::Packet::Secured { basic, common, extended, @@ -174,7 +160,7 @@ impl ItsMessage<'_> { ) => { let mut encoded = tp.encode()?; encoded.append(&mut etsi_uper); - fill_gn_and_encode(UnsecuredHeader { basic, common, extended }, &encoded) + fill_gn_and_encode(geonetworking::UnsecuredHeader { basic, common, extended }, &encoded) } _ => Err( "Expecting either both or neither GeoNetworking and Transport headers to be present!" @@ -193,7 +179,7 @@ impl ItsMessage<'_> { /// The encoder expects either both (GeoNetworking and Transport) headers or none /// Currently, denms of the following versions are supported: v2.2.1 (221) and v1.3.1 (131) /// Throws string error on encoding error -pub fn encode_denm(denm: &JsonItsMessage, version: u32) -> Result { +pub fn encode_denm(denm: &crate::JsonItsMessage, version: u32) -> Result { let mut payload = vec![]; match (&denm.its, version) { (None, 131) | (None, 221) => return Err("No DENM JSON provided.".to_string()), @@ -223,7 +209,7 @@ pub fn encode_denm(denm: &JsonItsMessage, version: u32) -> Result Result { +pub fn encode_cam(cam: &crate::JsonItsMessage, version: u32) -> Result { let mut payload = vec![]; match (&cam.its, version) { (None, 141) => return Err("No CAM JSON provided.".to_string()), @@ -244,7 +230,7 @@ pub fn encode_cam(cam: &JsonItsMessage, version: u32) -> Result /// The encoder expects either both (GeoNetworking and Transport) headers or none /// Currently, mapems of the following versions are supported: v2.2.1 (221) /// Throws string error on encoding error -pub fn encode_mapem(mapem: &JsonItsMessage, version: u32) -> Result { +pub fn encode_mapem(mapem: &crate::JsonItsMessage, version: u32) -> Result { let mut payload = vec![]; match (&mapem.its, version) { (None, 221) => return Err("No MAPEM JSON provided.".to_string()), @@ -265,7 +251,7 @@ pub fn encode_mapem(mapem: &JsonItsMessage, version: u32) -> Result Result { +pub fn encode_spatem(spatem: &crate::JsonItsMessage, version: u32) -> Result { let mut payload = vec![]; match (&spatem.its, version) { (None, 221) => return Err("No SPATEM JSON provided.".to_string()), @@ -288,7 +274,7 @@ pub fn encode_spatem(spatem: &JsonItsMessage, version: u32) -> Result Result { +pub fn encode_ivim(ivim: &crate::JsonItsMessage, version: u32) -> Result { let mut payload = vec![]; match (&ivim.its, version) { (None, 131) | (None, 211) | (None, 221) => return Err("No IVIM JSON provided.".to_string()), @@ -319,7 +305,7 @@ pub fn encode_ivim(ivim: &JsonItsMessage, version: u32) -> Result Result { +pub fn encode_srem(srem: &crate::JsonItsMessage, version: u32) -> Result { let mut payload = vec![]; match (&srem.its, version) { (None, 221) => return Err("No SREM JSON provided.".to_string()), @@ -340,7 +326,7 @@ pub fn encode_srem(srem: &JsonItsMessage, version: u32) -> Result Result { +pub fn encode_cpm(cpm: &crate::JsonItsMessage, version: u32) -> Result { let mut payload = vec![]; match (&cpm.its, version) { (None, 131) | (None, 211) => return Err("No CPM JSON provided.".to_string()), @@ -370,7 +356,7 @@ pub fn encode_cpm(cpm: &JsonItsMessage, version: u32) -> Result /// The encoder expects either both (GeoNetworking and Transport) headers or none /// Currently, ssems of the following versions are supported: v2.2.1 (221) /// Throws string error on encoding error -pub fn encode_ssem(ssem: &JsonItsMessage, version: u32) -> Result { +pub fn encode_ssem(ssem: &crate::JsonItsMessage, version: u32) -> Result { let mut payload = vec![]; match (&ssem.its, version) { (None, 221) => return Err("No SSEM JSON provided.".to_string()), @@ -391,25 +377,28 @@ fn optionally_encode_headers( tp_json: &Option, mut its: alloc::vec::Vec, ) -> Result, String> { + use crate::transport::encode::Encode as _; + match (gn_json, tp_json) { (Some(_), None) | (None, Some(_)) => Err( "Expecting either both or neither GeoNetworking and Transport headers to be present!" .to_string(), ), (Some(gn), Some(tp)) => { - let geonetworking = UnsecuredHeader::from_json(gn).map_err(map_err_to_string)?; + let geonetworking = + geonetworking::UnsecuredHeader::from_json(gn).map_err(crate::map_err_to_string)?; let mut transport = match geonetworking.common.next_header { geonetworking::NextAfterCommon::BTPA => { crate::transport::BasicTransportAHeader::decode_from_json(tp) - .map_err(map_err_to_string)? + .map_err(crate::map_err_to_string)? .encode() - .map_err(map_err_to_string)? + .map_err(crate::map_err_to_string)? } geonetworking::NextAfterCommon::BTPB => { crate::transport::BasicTransportBHeader::decode_from_json(tp) - .map_err(map_err_to_string)? + .map_err(crate::map_err_to_string)? .encode() - .map_err(map_err_to_string)? + .map_err(crate::map_err_to_string)? } h => { return Err(alloc::format!( @@ -429,43 +418,50 @@ fn optionally_encode_headers( not(target_arch = "wasm32") ))] fn fill_gn_and_encode( - mut geonetworking: UnsecuredHeader, + mut geonetworking: geonetworking::UnsecuredHeader, payload: &[u8], ) -> Result, alloc::string::String> { + use geonetworking::{ + AreaType, + BroadcastType, + Encode as _, + ExtendedHeader, + HeaderType, + LocationServiceType, + }; + #[allow(clippy::cast_possible_truncation)] let gn_payload_length = payload.len() as u16; geonetworking.common.payload_length = gn_payload_length; geonetworking.common.header_type_and_subtype = match geonetworking.extended { Some(ExtendedHeader::Beacon(_)) => HeaderType::Beacon, - Some(ExtendedHeader::GAC(_)) => HeaderType::GeoAnycast(geonetworking::AreaType::Circular), - Some(ExtendedHeader::GBC(_)) => HeaderType::GeoBroadcast(geonetworking::AreaType::Circular), + Some(ExtendedHeader::GAC(_)) => HeaderType::GeoAnycast(AreaType::Circular), + Some(ExtendedHeader::GBC(_)) => HeaderType::GeoBroadcast(AreaType::Circular), Some(ExtendedHeader::GUC(_)) => HeaderType::GeoUnicast, Some(ExtendedHeader::TSB(_)) => { - HeaderType::TopologicallyScopedBroadcast(geonetworking::BroadcastType::MultiHop) + HeaderType::TopologicallyScopedBroadcast(BroadcastType::MultiHop) } Some(ExtendedHeader::SHB(_)) => { - HeaderType::TopologicallyScopedBroadcast(geonetworking::BroadcastType::SingleHop) + HeaderType::TopologicallyScopedBroadcast(BroadcastType::SingleHop) } Some(ExtendedHeader::LSRequest(_)) => { - HeaderType::LocationService(geonetworking::LocationServiceType::Request) - } - Some(ExtendedHeader::LSReply(_)) => { - HeaderType::LocationService(geonetworking::LocationServiceType::Reply) + HeaderType::LocationService(LocationServiceType::Request) } + Some(ExtendedHeader::LSReply(_)) => HeaderType::LocationService(LocationServiceType::Reply), None => HeaderType::Any, }; geonetworking .with_payload(payload) - .map_err(map_err_to_string)? + .map_err(crate::map_err_to_string)? .encode_to_vec() - .map_err(map_err_to_string) + .map_err(crate::map_err_to_string) } #[cfg(all(target_arch = "wasm32", feature = "json"))] fn transcode_jer_to_uper( input: &String, ) -> Result, String> { - rasn::uper::encode(&rasn::jer::decode::(input).map_err(map_err_to_string)?) - .map_err(map_err_to_string) + rasn::uper::encode(&rasn::jer::decode::(input).map_err(crate::map_err_to_string)?) + .map_err(crate::map_err_to_string) } diff --git a/src/lib.rs b/src/lib.rs index 03d08f7..2a0e24a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,8 +80,6 @@ pub use geonetworking::{Decode, Packet}; #[cfg(feature = "transport")] #[deprecated = "use `pcap::remove_pcap_headers` instead"] pub use pcap::remove_pcap_headers; -#[cfg(feature = "_etsi")] -use transport::TransportHeader; #[cfg(all(target_arch = "wasm32", any(feature = "json", feature = "_etsi")))] use wasm_bindgen::prelude::*; @@ -150,78 +148,78 @@ pub enum ItsMessage<'a> { #[cfg(feature = "denm_1_3_1")] /// ETSI EN 302 637-3 v1.3.1 DENM DenmV1 { - geonetworking: Option>, - transport: Option>, + geonetworking: Option>, + transport: Option>, etsi: alloc::boxed::Box, }, #[cfg(feature = "denm_2_2_1")] /// ETSI TS 103 831 v2.2.1 (or v2.1.1) DENM DenmV2 { - geonetworking: Option>, - transport: Option>, + geonetworking: Option>, + transport: Option>, etsi: alloc::boxed::Box, }, #[cfg(feature = "cam_1_4_1")] /// ETSI TS 103 301 v2.2.1 (or v2.1.1 or v1.3.1) CAM Cam { - geonetworking: Option>, - transport: Option>, + geonetworking: Option>, + transport: Option>, etsi: alloc::boxed::Box, }, #[cfg(feature = "spatem_2_2_1")] /// ETSI TS 103 301 v2.2.1 (or v2.1.1 or v1.3.1) SPATEM Spatem { - geonetworking: Option>, - transport: Option>, + geonetworking: Option>, + transport: Option>, etsi: alloc::boxed::Box, }, #[cfg(feature = "mapem_2_2_1")] /// ETSI TS 103 301 v2.2.1 (or v2.1.1 or v1.3.1) MAPEM Mapem { - geonetworking: Option>, - transport: Option>, + geonetworking: Option>, + transport: Option>, etsi: alloc::boxed::Box, }, #[cfg(feature = "ivim_2_1_1")] /// ETSI TS 103 301 v2.1.1 (or v1.3.1) IVIM IvimV1 { - geonetworking: Option>, - transport: Option>, + geonetworking: Option>, + transport: Option>, etsi: alloc::boxed::Box, }, #[cfg(feature = "ivim_2_2_1")] /// ETSI TS 103 301 v2.2.1 IVIM IvimV2 { - geonetworking: Option>, - transport: Option>, + geonetworking: Option>, + transport: Option>, etsi: alloc::boxed::Box, }, #[cfg(feature = "srem_2_2_1")] /// ETSI TS 103 301 v2.2.1 (or v2.1.1 or v1.3.1) SREM Srem { - geonetworking: Option>, - transport: Option>, + geonetworking: Option>, + transport: Option>, etsi: alloc::boxed::Box, }, #[cfg(feature = "ssem_2_2_1")] /// ETSI TS 103 301 v2.2.1 (or v2.1.1 or v1.3.1) SSEM Ssem { - geonetworking: Option>, - transport: Option>, + geonetworking: Option>, + transport: Option>, etsi: alloc::boxed::Box, }, #[cfg(feature = "cpm_1")] /// ETSI TR 103 562 v2.1.1 CPM CpmV1 { - geonetworking: Option>, - transport: Option>, + geonetworking: Option>, + transport: Option>, etsi: alloc::boxed::Box, }, #[cfg(feature = "cpm_2_1_1")] /// ETSI TS 103 324 v2.1.1 CPM CpmV2 { - geonetworking: Option>, - transport: Option>, + geonetworking: Option>, + transport: Option>, etsi: alloc::boxed::Box< standards::cpm_2_1_1::cpm_pdu_descriptions::CollectivePerceptionMessage, >, @@ -232,14 +230,14 @@ pub enum ItsMessage<'a> { impl<'a> ItsMessage<'a> { /// Returns the `geonetworking` field of the `ItsMessage` variant #[must_use] - pub fn get_geonetworking(&self) -> Option> { + pub fn get_geonetworking(&self) -> Option> { let (gn, _) = self.get_headers(); gn.clone() } /// Returns the `transport` field of the `ItsMessage` variant #[must_use] - pub fn get_transport(&self) -> Option> { + pub fn get_transport(&self) -> Option> { let (_, tp) = self.get_headers(); tp.clone() } @@ -249,8 +247,8 @@ impl<'a> ItsMessage<'a> { fn get_headers( &self, ) -> ( - &Option>, - &Option>, + &Option>, + &Option>, ) { match self { #[cfg(feature = "denm_1_3_1")] diff --git a/src/transport/decode.rs b/src/transport/decode.rs index 722a12f..5ffd0db 100644 --- a/src/transport/decode.rs +++ b/src/transport/decode.rs @@ -4,8 +4,6 @@ use nom::combinator::{into, map_res}; use nom::error::{ErrorKind, FromExternalError, ParseError}; use nom::sequence::pair; -use crate::transport::{BasicTransportAHeader, BasicTransportBHeader, IPv6Header}; - #[derive(Debug, PartialEq)] pub enum DecodeError { IntegerError(alloc::string::String), @@ -52,13 +50,13 @@ pub trait Decode: Sized { fn decode(input: &[u8]) -> IResult<&[u8], Self>; } -impl Decode for BasicTransportAHeader { +impl Decode for super::BasicTransportAHeader { fn decode(input: &[u8]) -> IResult<&[u8], Self> { into(pair(u16_from_be_bytes, u16_from_be_bytes))(input) } } -impl From<(u16, u16)> for BasicTransportAHeader { +impl From<(u16, u16)> for super::BasicTransportAHeader { fn from(value: (u16, u16)) -> Self { Self { destination_port: value.0, @@ -67,7 +65,7 @@ impl From<(u16, u16)> for BasicTransportAHeader { } } -impl BasicTransportAHeader { +impl super::BasicTransportAHeader { #[cfg(feature = "json")] /// Decodes a BTP-A header from JSON /// @@ -79,13 +77,13 @@ impl BasicTransportAHeader { } } -impl Decode for BasicTransportBHeader { +impl Decode for super::BasicTransportBHeader { fn decode(input: &[u8]) -> IResult<&[u8], Self> { into(pair(u16_from_be_bytes, u16_from_be_bytes))(input) } } -impl From<(u16, u16)> for BasicTransportBHeader { +impl From<(u16, u16)> for super::BasicTransportBHeader { fn from(value: (u16, u16)) -> Self { Self { destination_port: value.0, @@ -94,7 +92,7 @@ impl From<(u16, u16)> for BasicTransportBHeader { } } -impl BasicTransportBHeader { +impl super::BasicTransportBHeader { #[cfg(feature = "json")] /// Decodes a BTP-B header from JSON /// @@ -116,7 +114,7 @@ fn u16_from_be_bytes(input: &[u8]) -> IResult<&[u8], u16> { })(input) } -impl Decode for IPv6Header { +impl Decode for super::IPv6Header { fn decode(input: &[u8]) -> IResult<&[u8], Self> { etherparse::PacketHeaders::from_ip_slice(input) .map(|headers| { @@ -136,7 +134,10 @@ impl Decode for IPv6Header { .link_exts .first() .map_or(0, etherparse::LinkExtHeader::header_len); - (&input[first_after_headers..], IPv6Header::from(headers)) + ( + &input[first_after_headers..], + super::IPv6Header::from(headers), + ) }) .map_err(|e| { nom::Err::Error(DecodeError::IPv6Parsing(alloc::format!( @@ -146,7 +147,7 @@ impl Decode for IPv6Header { } } -impl From> for IPv6Header { +impl From> for super::IPv6Header { fn from(value: PacketHeaders<'_>) -> Self { Self { ip: value.net, diff --git a/src/transport/encode.rs b/src/transport/encode.rs index 2b7da16..32c1cae 100644 --- a/src/transport/encode.rs +++ b/src/transport/encode.rs @@ -1,7 +1,5 @@ use alloc::string::ToString; -use super::{BasicTransportAHeader, BasicTransportBHeader, Debug, IPv6Header}; - #[allow(dead_code)] #[derive(Debug)] pub enum EncodeError { @@ -14,7 +12,7 @@ pub trait Encode: Sized { fn encode(&self) -> Result, EncodeError>; } -impl Encode for BasicTransportAHeader { +impl Encode for super::BasicTransportAHeader { fn encode(&self) -> Result, EncodeError> { Ok([ self.destination_port.to_be_bytes(), @@ -24,7 +22,7 @@ impl Encode for BasicTransportAHeader { } } -impl BasicTransportAHeader { +impl super::BasicTransportAHeader { #[cfg(feature = "json")] /// Encodes a BTP-A as a JSON representation /// @@ -36,7 +34,7 @@ impl BasicTransportAHeader { } } -impl Encode for BasicTransportBHeader { +impl Encode for super::BasicTransportBHeader { fn encode(&self) -> Result, EncodeError> { Ok([ self.destination_port.to_be_bytes(), @@ -46,7 +44,7 @@ impl Encode for BasicTransportBHeader { } } -impl BasicTransportBHeader { +impl super::BasicTransportBHeader { #[cfg(feature = "json")] /// Encodes a BTP-B as a JSON representation /// @@ -58,7 +56,7 @@ impl BasicTransportBHeader { } } -impl Encode for IPv6Header { +impl Encode for super::IPv6Header { fn encode(&self) -> Result, EncodeError> { Err(EncodeError::Unsupported( "Encoding IPv6 headers is currently unsupported.".to_string(), diff --git a/src/transport/mod.rs b/src/transport/mod.rs index c9322be..fcf5e22 100644 --- a/src/transport/mod.rs +++ b/src/transport/mod.rs @@ -3,9 +3,6 @@ use alloc::string::ToString; use core::fmt::Debug; -use decode::Decode; -use encode::Encode; -use geonetworking::NextAfterCommon; #[cfg(feature = "json")] use serde::{Deserialize, Serialize}; @@ -34,20 +31,22 @@ impl TransportHeader { /// # Errors /// Returns a human-readable error when parsing failed of unsupported header type was selected. pub fn decode_with_gn_next_header( - next_header: NextAfterCommon, + next_header: geonetworking::NextAfterCommon, bytes: &[u8], ) -> Result<(&[u8], TransportHeader), alloc::string::String> { + use decode::Decode as _; + match next_header { - NextAfterCommon::Any => { + geonetworking::NextAfterCommon::Any => { Err("Currently, only BTP and IPv6 Headers can be decoded!".to_string()) } - NextAfterCommon::BTPA => BasicTransportAHeader::decode(bytes) + geonetworking::NextAfterCommon::BTPA => BasicTransportAHeader::decode(bytes) .map(|(rem, btpa)| (rem, TransportHeader::BtpA(btpa))) .map_err(map_err_to_string), - NextAfterCommon::BTPB => BasicTransportBHeader::decode(bytes) + geonetworking::NextAfterCommon::BTPB => BasicTransportBHeader::decode(bytes) .map(|(rem, btpb)| (rem, TransportHeader::BtpB(btpb))) .map_err(map_err_to_string), - NextAfterCommon::IPv6 => IPv6Header::decode(bytes) + geonetworking::NextAfterCommon::IPv6 => IPv6Header::decode(bytes) .map(|(rem, ipv6)| (rem, TransportHeader::IPv6(alloc::boxed::Box::new(ipv6)))) .map_err(map_err_to_string), } @@ -60,6 +59,8 @@ impl TransportHeader { /// # Errors /// Returns a human-readable error when encoding failed. pub fn encode(&self) -> Result, alloc::string::String> { + use encode::Encode as _; + match self { TransportHeader::BtpA(a) => a.encode().map_err(map_err_to_string), TransportHeader::BtpB(b) => b.encode().map_err(map_err_to_string),