ice_rs/slice/
function_argument.rs

1use crate::slice::types::IceType;
2use __private::TokenStream;
3use quote::*;
4
5
6#[derive(Clone, Debug)]
7pub struct FunctionArgument {
8    pub id: TokenStream,
9    pub r#type: IceType,
10    pub out: bool
11}
12
13impl FunctionArgument {
14    pub fn new(id: TokenStream, r#type: IceType, out: bool) -> FunctionArgument {
15        FunctionArgument {
16            id: id,
17            r#type: r#type,
18            out: out
19        }
20    }
21
22    pub fn pass_argument(&self) -> TokenStream {
23        let id = &self.id;
24        if self.out { 
25            quote! { &mut #id }
26        } else {
27            if self.r#type.as_ref() {
28                quote! { &#id }
29            } else {
30                quote! { #id }
31            }
32        }
33    }
34
35    pub fn token(&self) -> TokenStream {
36        let id = &self.id;
37        let out = if self.out { 
38            Some(quote! { &mut })
39        } else {
40            if self.r#type.as_ref() {
41                Some(quote! { & })
42            } else {
43                None 
44            }
45
46        };
47        let typename = self.r#type.token();
48        quote! { #id: #out #typename }
49    }
50
51    pub fn decode_request(&self) -> Option<TokenStream> {
52        let id_token = &self.id;
53        match self.r#type {
54            IceType::Optional(_, _) => Some(quote! {
55                let mut #id_token = None;
56            }),
57            _ => {                
58                let type_token = &self.r#type.token_from();
59                let mut_token = if self.out {
60                    quote! { mut }
61                } else {
62                    quote! { }
63                };
64                Some(quote! {
65                    let #mut_token #id_token = #type_token::from_bytes(&request.params.data[read_bytes as usize..request.params.data.len()], &mut read_bytes)?;
66                })        
67            }
68        }
69    }
70
71    pub fn decode_optional_request(&self) -> Option<TokenStream> {
72        let id_token = &self.id;
73        let type_token = &self.r#type.token_from();
74        match self.r#type {
75            IceType::Optional(_, tag) => {
76                Some(quote! {
77                    let mut flag_bytes = 0;
78                    match OptionalFlag::from_bytes(&request.params.data[read_bytes as usize..request.params.data.len()], &mut flag_bytes) {
79                        Ok(flag) => {
80                            if flag.tag == #tag {
81                                #id_token = #type_token::from_bytes(&request.params.data[read_bytes as usize..request.params.data.len()], &mut read_bytes)?;
82                            }
83                        }
84                        _ => {}
85                    }
86                })
87            },
88            _ => None,
89        }
90    }
91
92    pub fn encode_output(&self) -> Option<TokenStream> {
93        if self.out {
94            let id_token = &self.id;
95            match self.r#type {
96                IceType::Optional(_, tag) => {
97                    Some(quote! {
98                        result.extend(OptionalWrapper::new(#tag, #id_token).to_bytes()?);
99                    })
100                }
101                _ => {
102                    Some(quote! {
103                        result.extend(#id_token.to_bytes()?);
104                    })
105                }
106            }
107            
108        } else {
109            None
110        }
111    }
112
113    pub fn serialize_output(&self) -> Option<TokenStream> {
114        if self.out {
115            let id_token = &self.id;
116            let type_token = &self.r#type.token_from();
117            Some(quote! {
118                *#id_token = #type_token::from_bytes(&reply.body.data[read_bytes as usize..reply.body.data.len()], &mut read_bytes)?;
119            })
120        } else {
121            None
122        }
123    }
124
125    pub fn serialize_input(&self) -> Option<TokenStream> {
126        let id_token = &self.id;
127        if self.out {
128            None
129        } else {
130            match &self.r#type {
131                IceType::Optional(var_type, tag) => {
132                    let option_type = var_type.token();
133                    Some(quote! {
134                        if let Some(value) = #id_token {
135                            bytes.extend(OptionalFlag::new(#tag, #option_type::optional_type()).to_bytes()?);
136                            bytes.extend(value.to_bytes()?);
137                        }
138                    })
139                }
140                _ => {
141                    Some(quote! {
142                        bytes.extend(#id_token.to_bytes()?);
143                    })
144                }
145            }
146        }
147    }
148}