protospec_build/prelude/
utf8.rs

1use super::*;
2
3pub struct Utf8;
4
5impl ForeignType for Utf8 {
6    fn assignable_from(&self, type_: &Type) -> bool {
7        match type_ {
8            Type::Array(inner) => {
9                let inner = inner.element.type_.borrow();
10                Type::Scalar(ScalarType::U8).assignable_from(&*inner)
11            }
12            _ => false,
13        }
14    }
15
16    fn assignable_to(&self, type_: &Type) -> bool {
17        self.assignable_from(type_)
18    }
19
20    fn type_ref(&self) -> TokenStream {
21        quote! { String }
22    }
23
24    fn decoding_gen(
25        &self,
26        source: TokenStream,
27        output_ref: TokenStream,
28        arguments: Vec<TokenStream>,
29        is_async: bool,
30    ) -> TokenStream {
31        let async_ = map_async(is_async);
32        if let Some(len) = arguments.first() {
33            quote! {
34                let #output_ref = {
35                    let t_count = #len as usize;
36                    let mut t: Vec<u8> = Vec::with_capacity(t_count);
37                    unsafe { t.set_len(t_count); }
38                    let t_borrow = &mut t[..];
39                    let t_borrow2 = unsafe {
40                        let len = t_borrow.len();
41                        let ptr = t.as_ptr() as *mut u8;
42                        slice::from_raw_parts_mut(ptr, len)
43                    };
44                    #source.read_exact(&mut t_borrow2[..])#async_?;
45                    String::from_utf8(t)?
46                };
47            }
48        } else {
49            quote! {
50                let #output_ref = {
51                    let mut t: Vec<u8> = vec![];
52                    #source.read_until(0u8, &mut t)#async_?;
53                    if t.len() > 0 && t[t.len() - 1] == 0u8 {
54                        t.truncate(t.len() - 1);
55                    }
56                    String::from_utf8(t)?
57                };
58            }
59        }
60    }
61
62    fn encoding_gen(
63        &self,
64        target: TokenStream,
65        field_ref: TokenStream,
66        arguments: Vec<TokenStream>,
67        is_async: bool,
68    ) -> TokenStream {
69        let async_ = map_async(is_async);
70        if let Some(_) = arguments.first() {
71            quote! {
72                {
73                    #target.write_all(#field_ref.as_bytes())#async_?;
74                }
75            }
76        } else {
77            quote! {
78                {
79                    #target.write_all(#field_ref.as_bytes())#async_?;
80                    #target.write_all(&[0u8])#async_?;
81                }
82            }
83        }
84    }
85
86    fn arguments(&self) -> Vec<TypeArgument> {
87        vec![TypeArgument {
88            name: "length".to_string(),
89            type_: Type::Scalar(ScalarType::U64),
90            default_value: Some(u64::MAX.into()),
91            can_resolve_auto: true,
92        }]
93    }
94
95    fn can_receive_auto(&self) -> Option<ScalarType> {
96        None
97    }
98}