rusmpp_extra/encoding/
latin1.rs1use rusmpp_core::values::DataCoding;
4
5mod errors;
6pub use errors::{Latin1ConcatenateError, Latin1EncodeError};
7
8#[derive(Debug)]
10#[non_exhaustive]
11pub struct Latin1 {}
12
13impl Default for Latin1 {
14 fn default() -> Self {
15 Self::new()
16 }
17}
18
19impl Latin1 {
20 pub const fn new() -> Self {
22 Self {}
23 }
24
25 pub const fn data_coding(&self) -> DataCoding {
27 DataCoding::Latin1
28 }
29}
30
31#[cfg(any(test, feature = "alloc"))]
32#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
33mod impl_owned {
34 use alloc::vec::Vec;
35
36 use crate::{
37 concatenation::{
38 MAX_PARTS,
39 owned::{Concatenation, Concatenator},
40 },
41 encoding::owned::Encoder,
42 };
43
44 use super::*;
45
46 impl Latin1 {
47 pub fn encode_to_vec(&self, input: &str) -> Result<Vec<u8>, Latin1EncodeError> {
49 encoding_rs::mem::is_utf8_latin1(input.as_bytes())
50 .then_some(())
51 .ok_or(Latin1EncodeError::UnencodableCharacter)?;
52
53 let mut buffer = alloc::vec![0u8; input.len()];
54 let size =
61 encoding_rs::mem::convert_utf8_to_latin1_lossy(input.as_bytes(), &mut buffer);
62
63 buffer.truncate(size);
64
65 Ok(buffer)
66 }
67 }
68
69 impl Encoder for Latin1 {
70 type Error = Latin1EncodeError;
71
72 fn encode(&self, message: &str) -> Result<(Vec<u8>, DataCoding), Self::Error> {
73 self.encode_to_vec(message)
74 .map(|vec| (vec, self.data_coding()))
75 }
76 }
77
78 impl Concatenator for Latin1 {
79 type Error = Latin1ConcatenateError;
80
81 fn concatenate(
82 &self,
83 message: &str,
84 max_message_size: usize,
85 part_header_size: usize,
86 ) -> Result<(Concatenation, DataCoding), Self::Error> {
87 let encoded = self.encode_to_vec(message)?;
88
89 let total = encoded.len();
90
91 if total <= max_message_size {
92 return Ok((Concatenation::single(encoded), self.data_coding()));
93 }
94
95 let part_payload_size = max_message_size.saturating_sub(part_header_size);
96
97 if part_payload_size == 0 {
98 return Err(Latin1ConcatenateError::PartCapacityExceeded);
99 }
100
101 let parts = encoded
102 .chunks(part_payload_size)
103 .map(|chunk| chunk.to_vec())
104 .collect::<Vec<Vec<u8>>>();
105
106 if parts.len() > MAX_PARTS {
107 return Err(Latin1ConcatenateError::parts_count_exceeded(parts.len()));
108 }
109
110 Ok((Concatenation::concatenated(parts), self.data_coding()))
111 }
112 }
113}
114
115#[cfg(test)]
116mod tests;