mqute_codec/protocol/common/
payload.rs1use crate::Error;
9use crate::codec::util::{decode_string, encode_string};
10use crate::protocol::util;
11use bytes::{Buf, BufMut, Bytes, BytesMut};
12use std::borrow::Borrow;
13use std::ops::{Index, IndexMut};
14
15#[derive(Debug, Clone, PartialEq, Eq)]
29pub struct Codes<T>(Vec<T>);
30
31#[allow(clippy::len_without_is_empty)]
32impl<T> Codes<T>
33where
34 T: TryFrom<u8, Error = Error> + Into<u8> + Copy,
35{
36 pub fn new<I: IntoIterator<Item = T>>(codes: I) -> Self {
42 let values: Vec<T> = codes.into_iter().collect();
43
44 if values.is_empty() {
45 panic!("At least one code is required");
46 }
47
48 Codes(values)
49 }
50
51 pub(crate) fn decode(payload: &mut Bytes) -> Result<Self, Error> {
53 let mut codes: Vec<T> = Vec::with_capacity(payload.len());
54 while payload.has_remaining() {
55 codes.push(payload.get_u8().try_into()?);
56 }
57
58 if codes.is_empty() {
59 return Err(Error::NoCodes);
60 }
61
62 Ok(codes.into())
63 }
64
65 pub(crate) fn encode(&self, buf: &mut BytesMut) {
67 self.0.iter().for_each(|&value| {
68 buf.put_u8(value.into());
69 });
70 }
71
72 pub fn len(&self) -> usize {
74 self.0.len()
75 }
76}
77
78impl<T> AsRef<Vec<T>> for Codes<T> {
79 #[inline]
80 fn as_ref(&self) -> &Vec<T> {
81 self.0.as_ref()
82 }
83}
84
85impl<T> Borrow<Vec<T>> for Codes<T> {
86 fn borrow(&self) -> &Vec<T> {
87 self.0.as_ref()
88 }
89}
90
91impl<T> IntoIterator for Codes<T> {
92 type Item = T;
93 type IntoIter = std::vec::IntoIter<T>;
94
95 fn into_iter(self) -> Self::IntoIter {
96 self.0.into_iter()
97 }
98}
99
100impl<T> FromIterator<T> for Codes<T> {
101 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
102 Codes(Vec::from_iter(iter))
103 }
104}
105
106impl<T> From<Codes<T>> for Vec<T> {
107 #[inline]
108 fn from(value: Codes<T>) -> Self {
109 value.0
110 }
111}
112
113impl<T> From<Vec<T>> for Codes<T> {
114 #[inline]
115 fn from(value: Vec<T>) -> Self {
116 Codes(value)
117 }
118}
119
120#[derive(Debug, Clone, PartialEq, Eq)]
136pub struct TopicFilters(Vec<String>);
137
138#[allow(clippy::len_without_is_empty)]
139impl TopicFilters {
140 pub fn new<T: IntoIterator<Item: Into<String>>>(filters: T) -> Self {
148 let values: Vec<String> = filters.into_iter().map(|x| x.into()).collect();
149
150 if values.is_empty() {
151 panic!("At least one topic filter is required");
152 }
153
154 for value in &values {
156 if !util::is_valid_topic_filter(&value) {
157 panic!("Invalid topic filter: '{}'", value);
158 }
159 }
160
161 TopicFilters(values)
162 }
163
164 pub fn len(&self) -> usize {
166 self.0.len()
167 }
168
169 pub(crate) fn decode(payload: &mut Bytes) -> Result<Self, Error> {
171 let mut filters = Vec::with_capacity(1);
172
173 while payload.has_remaining() {
174 let filter = decode_string(payload)?;
175
176 if !util::is_valid_topic_filter(&filter) {
178 return Err(Error::InvalidTopicFilter(filter));
179 }
180
181 filters.push(filter);
182 }
183
184 if filters.is_empty() {
185 return Err(Error::NoTopic);
186 }
187
188 Ok(TopicFilters(filters))
189 }
190
191 pub(crate) fn encode(&self, buf: &mut BytesMut) {
193 self.0.iter().for_each(|filter| {
194 encode_string(buf, filter);
195 });
196 }
197
198 pub(crate) fn encoded_len(&self) -> usize {
200 self.0.iter().fold(0, |acc, filter| acc + 2 + filter.len())
201 }
202}
203
204impl AsRef<Vec<String>> for TopicFilters {
205 #[inline]
206 fn as_ref(&self) -> &Vec<String> {
207 self.0.as_ref()
208 }
209}
210
211impl Borrow<Vec<String>> for TopicFilters {
212 fn borrow(&self) -> &Vec<String> {
213 self.0.as_ref()
214 }
215}
216
217impl IntoIterator for TopicFilters {
218 type Item = String;
219 type IntoIter = std::vec::IntoIter<String>;
220
221 fn into_iter(self) -> Self::IntoIter {
222 self.0.into_iter()
223 }
224}
225
226impl FromIterator<String> for TopicFilters {
227 fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
228 TopicFilters(Vec::from_iter(iter))
229 }
230}
231
232impl From<TopicFilters> for Vec<String> {
233 #[inline]
234 fn from(value: TopicFilters) -> Self {
235 value.0
236 }
237}
238
239impl From<Vec<String>> for TopicFilters {
240 #[inline]
241 fn from(value: Vec<String>) -> Self {
242 TopicFilters(value)
243 }
244}
245
246impl<T> Index<usize> for Codes<T> {
247 type Output = T;
248 fn index(&self, index: usize) -> &Self::Output {
249 self.0.index(index)
250 }
251}
252
253impl<T> IndexMut<usize> for Codes<T> {
254 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
255 self.0.index_mut(index)
256 }
257}