rusmpp_extra/encoding/gsm7bit/
unpacked.rs1use rusmpp_core::values::DataCoding;
2
3use crate::encoding::gsm7bit::alphabet::Gsm7BitAlphabet;
4
5#[non_exhaustive]
7#[derive(Debug)]
8pub struct Gsm7BitUnpacked {
9 alphabet: Gsm7BitAlphabet,
11 allow_split_extended_character: bool,
13}
14
15impl Default for Gsm7BitUnpacked {
16 fn default() -> Self {
17 Self::new()
18 }
19}
20
21impl Gsm7BitUnpacked {
22 pub const fn new() -> Self {
29 Self {
30 alphabet: Gsm7BitAlphabet::default(),
31 allow_split_extended_character: false,
32 }
33 }
34
35 pub const fn with_alphabet(mut self, alphabet: Gsm7BitAlphabet) -> Self {
37 self.alphabet = alphabet;
38 self
39 }
40
41 pub const fn allow_split_extended_character(&self) -> bool {
43 self.allow_split_extended_character
44 }
45
46 pub const fn with_allow_split_extended_character(mut self, allow: bool) -> Self {
48 self.allow_split_extended_character = allow;
49 self
50 }
51
52 pub const fn alphabet(&self) -> &Gsm7BitAlphabet {
54 &self.alphabet
55 }
56
57 pub const fn data_coding(&self) -> DataCoding {
59 DataCoding::McSpecific
60 }
61}
62
63#[cfg(any(test, feature = "alloc"))]
64#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
65mod impl_owned {
66 use alloc::vec::Vec;
67
68 use crate::{
69 concatenation::{
70 MAX_PARTS,
71 owned::{Concatenation, Concatenator},
72 },
73 encoding::{
74 gsm7bit::{
75 alphabet::ESCAPE_CHARACTER,
76 errors::{Gsm7BitConcatenateError, Gsm7BitEncodeError},
77 },
78 owned::Encoder,
79 },
80 };
81
82 use super::*;
83
84 impl Gsm7BitUnpacked {
85 pub fn encode_to_vec(&self, input: &str) -> Result<Vec<u8>, Gsm7BitEncodeError> {
87 self.alphabet
88 .encode_to_vec(input)
89 .map_err(Gsm7BitEncodeError::UnencodableCharacter)
90 }
91 }
92
93 impl Encoder for Gsm7BitUnpacked {
94 type Error = Gsm7BitEncodeError;
95
96 fn encode(&self, message: &str) -> Result<(Vec<u8>, DataCoding), Self::Error> {
97 self.encode_to_vec(message)
98 .map(|vec| (vec, self.data_coding()))
99 }
100 }
101
102 impl Concatenator for Gsm7BitUnpacked {
103 type Error = Gsm7BitConcatenateError;
104
105 fn concatenate(
106 &self,
107 message: &str,
108 max_message_size: usize,
109 part_header_size: usize,
110 ) -> Result<(Concatenation, DataCoding), Self::Error> {
111 let encoded = self.encode_to_vec(message)?;
112
113 let total = encoded.len();
114
115 if total <= max_message_size {
116 return Ok((Concatenation::single(encoded), self.data_coding()));
117 }
118
119 let part_payload_size = max_message_size.saturating_sub(part_header_size);
120
121 if part_payload_size == 0 {
122 return Err(Gsm7BitConcatenateError::PartCapacityExceeded);
123 }
124
125 let mut parts: Vec<Vec<u8>> = Vec::new();
126 let mut i = 0;
127
128 while i < total {
129 let mut end = (i + part_payload_size).min(total);
130
131 if !self.allow_split_extended_character {
133 if end < total && encoded[end - 1] == ESCAPE_CHARACTER {
136 end -= 1;
137
138 if end == i {
140 return Err(Gsm7BitConcatenateError::InvalidBoundary);
141 }
142 }
143 }
144
145 parts.push(encoded[i..end].to_vec());
146
147 i = end;
148 }
149
150 if parts.len() > MAX_PARTS {
151 return Err(Gsm7BitConcatenateError::parts_count_exceeded(parts.len()));
152 }
153
154 Ok((Concatenation::concatenated(parts), self.data_coding()))
155 }
156 }
157}