stomp_parser/model/frames/
sender.rs

1macro_rules! sender_frame {
2    ( $name:ident,  $($comment:literal,)? $command:ident, $origin:ident $(, $header_name:ident : $header_type:ident )* $(,( $(  $opt_header_name:ident : $opt_header_type:ident $(: $opt_header_default:tt $(: $opt_header_default_comment:literal)?)?  ),* ))? $(,[custom: $has_custom:ident])? $(,[body: $has_body:ident])?  $(,$long_comment:literal)*) => {
3
4        paste::paste! {
5            $(#[doc = ""$comment]
6            #[doc = ""])?
7            #[doc = "This frame has required headers "$("`"$header_name"`")","* $(" and optional headers " $("`"$opt_header_name"`")","* )?"."]
8            $(#[doc = ""]
9            #[doc = ""$long_comment])?
10            pub struct [<$name Builder>] {
11                $(
12                    $header_name: <[<$header_type Value>]<'static> as HeaderValue>::OwnedValue,
13                )*
14                $($(
15                    $opt_header_name: Option<<[<$opt_header_type Value>]<'static> as HeaderValue>::OwnedValue>,
16                )*)?
17                $(
18                    #[doc(hidden)]
19                    #[doc = "Useless doc: `"$has_custom"`."]
20                    custom: Vec<(String, String)>,
21                )?
22                $(
23                    #[doc(hidden)]
24                    #[doc = "Useless doc: `"$has_body"`."]
25                    body: Option<Vec<u8>>,
26                )?
27            }
28
29            impl [<$name Builder>] {
30                $($(
31                    #[doc = "The value of the `"$opt_header_name"` header."]
32                    $($(#[doc = "Defaults to `"$opt_header_default_comment"` if not supplied."])?)?
33                    pub fn $opt_header_name(mut self, new_val: <[<$opt_header_type Value>] as HeaderValue>::OwnedValue) -> [<$name Builder>] {
34                        self.$opt_header_name = Some(new_val);
35
36                        self
37                    }
38                )*)?
39                $(
40                    #[doc = "Useless doc: `"$has_custom"`."]
41                    pub fn add_custom_header(mut self, name: String, value: String) -> [<$name Builder>] {
42                        self.custom.push((name, value));
43                        self
44                    }
45                )?
46                $(
47                    #[doc = "Useless doc: `"$has_body"`."]
48                    pub fn body(mut self, new_value: Vec<u8>) -> [<$name Builder>] {
49                        self.body = Some(new_value);
50                        self
51                    }
52                )?
53
54                pub fn new($(
55                            $header_name: <[<$header_type Value>]<'static> as HeaderValue>::OwnedValue,
56                        )*) -> [<$name Builder>] {
57                    [<$name Builder>] {
58                        $(
59                            $header_name,
60                        )*
61                        $($(
62                            $opt_header_name: choose_from_presence!($($opt_header_default)? {Some($($opt_header_default)?().into())},{None}),
63                        )*)?
64                        $(
65                            custom: choose_from_presence!($has_custom {Vec::new()}, {Vec::new()}),
66                        )?
67                        $(
68                            body: choose_from_presence!($has_body None, None),
69                        )?
70                    }
71                }
72
73                #[allow(unused_mut)]
74                pub fn build(mut self) -> $name<'static> {
75                    // First, build the byte array
76                    let mut bytes : Vec<u8> = Vec::with_capacity(1000);
77                    let bytes_ref = &mut bytes;
78
79                    let mut frame = $name::init(Vec::new());
80
81                    write_command(bytes_ref, $name::NAME);
82
83                    $(
84                        // Write the required header, returning an error if the value was not set
85                        let (_,[<$header_name _range>]) = if [<$header_type Value>]::OWNED {
86                            // Owned values are already in the right form for the frame, but also need to be written to the
87                            // output buffer
88                            let mut bytes = self.[<$header_name>].to_string().into_bytes();
89                            frame.$header_name = [<$header_type Value>]::from_owned(self.[<$header_name>]);
90                            write_header(bytes_ref, [<$header_type Value>]::NAME, &mut bytes)
91                        } else {
92                            // Non-owned values strings; the value for the header on the frame needs to be in the byte buffer
93                            let mut bytes = self.[<$header_name>].to_string().into_bytes();
94                            write_header(bytes_ref, [<$header_type Value>]::NAME, &mut bytes)
95                        };
96                    )*
97
98                    $($(
99                        // Write the required header, returning an error if the value was not set
100                        let [<$opt_header_name _range>] = if [<$opt_header_type Value>]::OWNED {
101                            // Owned values are already in the right form for the frame, but also need to be written to the
102                            // output buffer
103                            self.[<$opt_header_name>].take().map(|value| {
104                                let mut bytes = value.to_string().into_bytes();
105                                 choose_from_presence!($($opt_header_default)? {
106                                    frame.$opt_header_name = [<$opt_header_type Value>]::from_owned(value);
107                                }, {
108                                    frame.$opt_header_name = Some([<$opt_header_type Value>]::from_owned(value));
109                                });
110                                write_header(bytes_ref, [<$opt_header_type Value>]::NAME, &mut bytes)
111                            })
112                        } else {
113                            // Non-owned values strings; the value for the header on the frame needs to be in the byte buffer
114                            self.[<$opt_header_name>].take().map(|value| {
115                                let mut bytes = value.to_string().into_bytes();
116                                write_header(bytes_ref, [<$opt_header_type Value>]::NAME, &mut bytes)
117                            })
118                        };
119                    )*)?
120
121                    $(
122                        let $has_custom : Vec<((usize, usize),(usize,usize))> = self.custom.iter().map(|(name, value)| {
123                             let mut bytes = value.to_string().into_bytes();
124                             write_header(bytes_ref, &name, &mut bytes)
125                        }).collect();
126                    )?
127
128                    // End the headers
129                    write_headers_end(bytes_ref);
130
131                    $(
132                    let mut [<_ $has_body>] = ();
133
134                    let body_range = self.body.take().as_mut().map(|body| write_body(bytes_ref, body));
135                    )?
136
137                    // End the frame
138                    write_frame_end(bytes_ref);
139
140                    let ptr : *const [u8] = bytes.as_slice();
141                    let slice = unsafe { ptr.as_ref().unwrap() };
142
143                    frame.raw = bytes;
144
145                    $(
146                        if ![<$header_type Value>]::OWNED {
147                            let value = unsafe { std::str::from_utf8_unchecked(&slice[[<$header_name _range>].0..[<$header_name _range>].1]) };
148                            frame.$header_name = [<$header_type Value>]::from_str(value).expect("Should never fail because string valued");
149                        }
150                    )*
151
152                    $($(
153                        if let Some((_,[<$opt_header_name _range>])) = [<$opt_header_name _range>] {
154                            if ![<$opt_header_type Value>]::OWNED {
155                                let value = unsafe { std::str::from_utf8_unchecked(&slice[[<$opt_header_name _range>].0..[<$opt_header_name _range>].1]) };
156                                choose_from_presence!($($opt_header_default)? {
157                                    frame.$opt_header_name = [<$opt_header_type Value>]::from_str(value).expect("Should never fail because string valued");
158                                }, {
159                                    frame.$opt_header_name = Some([<$opt_header_type Value>]::from_str(value).expect("Should never fail because string valued"));
160                                });
161                            }
162                        };
163                    )*)?
164
165                    $(
166                        frame.custom = $has_custom.iter().map(|ranges| {
167                            let name = unsafe { std::str::from_utf8_unchecked(&slice[ranges.0.0..ranges.0.1]) };
168                            let value = unsafe { std::str::from_utf8_unchecked(&slice[ranges.1.0..ranges.1.1]) };
169
170                            CustomValue::new(name, value)
171                        }).collect();
172                    )?
173
174
175                    $(
176                        [<_ $has_body>] = ();
177                        body_range.iter().for_each(|body_range|{
178                            frame.body = &slice[body_range.0..body_range.1]
179                        });
180
181                    )?
182
183                    frame
184                }
185            }
186        }
187    }
188}