1use std::borrow::Cow;
2use std::rc::Rc;
3use std::sync::Arc;
4use crate::protocol::*;
5use crate::ThriftError;
6
7impl <'i> CompactThriftProtocol<'i> for bool {
25 const FIELD_TYPE: u8 = 2; #[inline]
28 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
29 let byte = input.read_byte()?;
30 *self = byte == 1;
31 Ok(())
32 }
33
34 #[inline]
35 fn fill_thrift_field<T: CompactThriftInput<'i>>(&mut self, _input: &mut T, field_type: u8) -> Result<(), ThriftError> {
36 *self = field_type == 1;
37 Ok(())
38 }
39
40 #[inline]
41 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
42 let value = 1 + (!*self) as u8;
43 output.write_byte(value)
44 }
45
46 fn write_thrift_field<T: CompactThriftOutput>(&self, output: &mut T, field_id: i16, last_field_id: &mut i16) -> Result<(), ThriftError> {
47 let field_type = 1 + (!*self) as u8;
48 write_field_header(output, field_type, field_id, last_field_id)
49 }
50}
51
52impl <'i> CompactThriftProtocol<'i> for i8 {
53 const FIELD_TYPE: u8 = 3;
54
55 #[inline]
56 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
57 *self = input.read_byte()? as i8;
58 Ok(())
59 }
60
61 #[inline]
62 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
63 output.write_byte(*self as u8)
64 }
65}
66
67impl <'i> CompactThriftProtocol<'i> for i16 {
68 const FIELD_TYPE: u8 = 4;
69
70 #[inline]
71 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
72 *self = input.read_i16()?;
73 Ok(())
74 }
75
76 #[inline]
77 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
78 output.write_i16(*self)
79 }
80}
81
82impl <'i> CompactThriftProtocol<'i> for i32 {
83 const FIELD_TYPE: u8 = 5;
84
85 #[inline]
86 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
87 *self = input.read_i32()?;
88 Ok(())
89 }
90
91 #[inline]
92 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
93 output.write_i32(*self)
94 }
95}
96
97impl <'i> CompactThriftProtocol<'i> for i64 {
98 const FIELD_TYPE: u8 = 6;
99
100 #[inline]
101 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
102 *self = input.read_i64()?;
103 Ok(())
104 }
105
106 #[inline]
107 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
108 output.write_i64(*self)
109 }
110}
111
112impl <'i> CompactThriftProtocol<'i> for f64 {
113 const FIELD_TYPE: u8 = 7;
114
115 #[inline]
116 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
117 *self = input.read_double()?;
118 Ok(())
119 }
120
121 #[inline]
122 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
123 output.write_double(*self)
124 }
125}
126
127impl <'i> CompactThriftProtocol<'i> for Vec<u8> {
128 const FIELD_TYPE: u8 = 8;
129
130 #[inline]
131 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
132 *self = input.read_binary()?.into_owned();
133 Ok(())
134 }
135
136 #[inline]
137 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
138 output.write_binary(self.as_slice())
139 }
140}
141
142impl <'i> CompactThriftProtocol<'i> for String {
143 const FIELD_TYPE: u8 = 8;
145
146 #[inline]
147 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
148 *self = input.read_string()?.into_owned();
149 Ok(())
150 }
151
152 #[inline]
153 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
154 output.write_string(self.as_str())
155 }
156}
157
158impl <'i> CompactThriftProtocol<'i> for Cow<'i, [u8]> {
159 const FIELD_TYPE: u8 = 8;
160
161 #[inline]
162 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
163 *self = input.read_binary()?;
164 Ok(())
165 }
166
167 #[inline]
168 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
169 output.write_binary(self.as_ref())
170 }
171}
172
173impl <'i> CompactThriftProtocol<'i> for Cow<'i, str> {
174 const FIELD_TYPE: u8 = 8;
175
176 #[inline]
177 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
178 *self = input.read_string()?;
179 Ok(())
180 }
181
182 #[inline]
183 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
184 output.write_string(self.as_ref())
185 }
186}
187
188impl <'i, P: CompactThriftProtocol<'i> + Default> CompactThriftProtocol<'i> for Vec<P> {
189 const FIELD_TYPE: u8 = 9;
190
191 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
192 let (len, element_type) = read_collection_len_and_type(input)?;
193 if element_type != P::FIELD_TYPE && !(P::FIELD_TYPE == bool::FIELD_TYPE && element_type == 1) {
197 return Err(ThriftError::InvalidType);
198 }
199 self.clear();
200 self.try_reserve(len as usize).map_err(|_| ThriftError::ReserveError)?;
201
202 for _ in 0..len as usize {
203 self.extend((0..1).map(|_| P::default()));
206 unsafe {
208 self.last_mut().unwrap_unchecked().fill_thrift(input)?;
209 }
210 }
211
212 Ok(())
213 }
214
215 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
216 let len = self.len();
217 if len > MAX_COLLECTION_LEN {
218 return Err(ThriftError::InvalidCollectionLen);
219 }
220
221 if len < 15 {
222 let header = P::FIELD_TYPE | ((len as u8) << 4);
223 output.write_byte(header)?;
224 } else {
225 output.write_byte(P::FIELD_TYPE | 0xF0)?;
226 output.write_len(len)?;
227 }
228 self.iter().try_for_each(|value| {
229 value.write_thrift(output)
230 })
231 }
232}
233
234impl <'i, P: CompactThriftProtocol<'i> + Default> CompactThriftProtocol<'i> for Option<P> {
235 const FIELD_TYPE: u8 = P::FIELD_TYPE;
236
237 #[inline]
238 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
239 if self.is_some() {
240 return Err(ThriftError::DuplicateField);
241 }
242 unsafe {
244 std::ptr::write(self as *mut _, Some(P::default()));
245 self.as_mut().unwrap_unchecked().fill_thrift(input)?;
246 }
247 Ok(())
248 }
249
250 #[inline]
251 fn fill_thrift_field<T: CompactThriftInput<'i>>(&mut self, input: &mut T, field_type: u8) -> Result<(), ThriftError> {
252 if self.is_some() {
253 return Err(ThriftError::DuplicateField);
254 }
255 unsafe {
257 std::ptr::write(self as *mut _, Some(P::default()));
258 self.as_mut().unwrap_unchecked().fill_thrift_field(input, field_type)?;
259 }
260 Ok(())
261 }
262
263
264 #[inline]
265 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
266 if let Some(value) = self.as_ref() {
267 value.write_thrift(output)
268 } else {
269 Err(ThriftError::MissingValue)
270 }
271 }
272
273 #[inline]
274 fn write_thrift_field<T: CompactThriftOutput>(&self, output: &mut T, field_id: i16, last_field_id: &mut i16) -> Result<(), ThriftError> {
275 if let Some(value) = self.as_ref() {
277 value.write_thrift_field(output, field_id, last_field_id)?;
278 }
279 Ok(())
280 }
281}
282
283impl <'i, P: CompactThriftProtocol<'i> + Default> CompactThriftProtocol<'i> for Box<P> {
284 const FIELD_TYPE: u8 = P::FIELD_TYPE;
285
286 #[inline]
287 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
288 Box::as_mut(self).fill_thrift(input)
289 }
290
291 #[inline]
292 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
293 Box::as_ref(self).write_thrift(output)
294 }
295}
296
297impl <'i, P: CompactThriftProtocol<'i> + Default> CompactThriftProtocol<'i> for Rc<P> {
298 const FIELD_TYPE: u8 = P::FIELD_TYPE;
299
300 #[inline]
301 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
302 Rc::get_mut(self).ok_or(ThriftError::DuplicateField)?.fill_thrift(input)
303 }
304
305 #[inline]
306 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
307 Rc::as_ref(self).write_thrift(output)
308 }
309}
310
311impl <'i, P: CompactThriftProtocol<'i> + Default> CompactThriftProtocol<'i> for Arc<P> {
312 const FIELD_TYPE: u8 = P::FIELD_TYPE;
313
314 #[inline]
315 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
316 Arc::get_mut(self).ok_or(ThriftError::DuplicateField)?.fill_thrift(input)
317 }
318
319 #[inline]
320 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
321 Arc::as_ref(self).write_thrift(output)
322 }
323}
324
325impl <'i> CompactThriftProtocol<'i> for Box<str> {
326 const FIELD_TYPE: u8 = String::FIELD_TYPE;
327
328 #[inline]
329 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
330 *self = input.read_string()?.into_owned().into_boxed_str();
331 Ok(())
332 }
333
334 #[inline]
335 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
336 output.write_string(self.as_ref())
337 }
338}
339
340impl <'i> CompactThriftProtocol<'i> for Rc<str> {
341 const FIELD_TYPE: u8 = String::FIELD_TYPE;
342
343 #[inline]
344 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
345 *self = match input.read_string()? {
346 Cow::Borrowed(s) => Rc::from(s),
347 Cow::Owned(s) => Rc::from(s),
348 };
349 Ok(())
350 }
351
352 #[inline]
353 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
354 output.write_string(self.as_ref())
355 }
356}
357
358impl <'i> CompactThriftProtocol<'i> for Arc<str> {
359 const FIELD_TYPE: u8 = String::FIELD_TYPE;
360
361 #[inline]
362 fn fill_thrift<T: CompactThriftInput<'i>>(&mut self, input: &mut T) -> Result<(), ThriftError> {
363 *self = match input.read_string()? {
364 Cow::Borrowed(s) => Arc::from(s),
365 Cow::Owned(s) => Arc::from(s),
366 };
367 Ok(())
368 }
369
370 #[inline]
371 fn write_thrift<T: CompactThriftOutput>(&self, output: &mut T) -> Result<(), ThriftError> {
372 output.write_string(self.as_ref())
373 }
374}
375
376
377#[cfg(test)]
378mod tests {
379 use crate::{CompactThriftInputSlice, CompactThriftProtocol};
380
381 #[test]
382 fn test_encode_boolean_list() {
383 let mut output = vec![];
384 vec![false, true, true].write_thrift(&mut output).unwrap();
385 assert_eq!(&output, &[0b0011_0010, 2, 1, 1]);
386 }
387 #[test]
388 fn test_decode_boolean_list_tag1() {
389 let input = vec![0b0011_0001_u8, 2, 1, 0];
390 let values = Vec::<bool>::read_thrift(&mut CompactThriftInputSlice::new(&input)).unwrap();
391 assert_eq!(&values, &[false, true, false]);
392 }
393 #[test]
394 fn test_decode_boolean_list_tag2() {
395 let input = vec![0b0011_0010_u8, 2, 1, 0];
396 let values = Vec::<bool>::read_thrift(&mut CompactThriftInputSlice::new(&input)).unwrap();
397 assert_eq!(&values, &[false, true, false]);
398 }
399}