rust_rcs_core/internet/
parameter.rs

1// Copyright 2023 宋昊文
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::io::Read;
16
17use crate::internet::syntax;
18
19pub struct Parameter<'a> {
20    pub name: &'a [u8],
21    pub value: Option<&'a [u8]>,
22}
23
24impl<'a> Parameter<'a> {
25    pub fn reader(&self) -> ParameterReader {
26        ParameterReader {
27            n: self.name,
28            v: self.value,
29            d: b';',
30            pos: 0,
31        }
32    }
33}
34
35impl<'a> From<&'a [u8]> for Parameter<'a> {
36    /// Build a Parameter from string bytes
37    ///
38    /// # Examples
39    ///
40    /// ```
41    /// let a = "key=value".as_bytes();
42    /// let p = rust_rcs_core::internet::parameter::Parameter::from(a);
43    /// assert_eq!(p.name, "key".as_bytes());
44    /// if let Some(value) = p.value {
45    ///     assert_eq!(value, "value".as_bytes());
46    /// } else {
47    ///     panic!("decode not successful\n");
48    /// }
49    /// ```
50    fn from(s: &'a [u8]) -> Parameter {
51        let mut iter = s.iter();
52
53        if let Some(position) = iter.position(|c| *c == b'=') {
54            return Parameter {
55                name: &s[..position],
56                value: Some(&s[position + 1..]),
57            };
58        }
59
60        return Parameter {
61            name: s,
62            value: None,
63        };
64    }
65}
66
67pub struct ParameterParser<'a> {
68    s: &'a [u8],
69    d: u8,
70    p: usize,
71    ows: bool,
72}
73
74impl<'a> ParameterParser<'a> {
75    pub fn new(s: &'a [u8], d: u8, ows: bool) -> ParameterParser<'a> {
76        ParameterParser { s, d, p: 0, ows }
77    }
78}
79
80impl<'a> Iterator for ParameterParser<'a> {
81    type Item = Parameter<'a>;
82    fn next(&mut self) -> Option<Parameter<'a>> {
83        if self.p < self.s.len() {
84            let chunk;
85            let advance;
86            if let Some(idx) = syntax::index_with_token_escaping(&self.s[self.p..], self.d) {
87                chunk = &self.s[self.p..self.p + idx];
88                advance = idx;
89            } else {
90                chunk = &self.s[self.p..];
91                advance = self.s.len() - self.p;
92            }
93
94            let chunk = syntax::trim(chunk);
95
96            if self.p + advance + 1 < self.s.len() {
97                if self.ows {
98                    self.p = self.p
99                        + advance
100                        + syntax::index_skipping_ows_and_obs_fold(&self.s[self.p + advance + 1..])
101                        + 1;
102                } else {
103                    self.p = self.p + advance + 1;
104                }
105            } else {
106                self.p = self.p + advance + 1;
107            }
108
109            return Some(Parameter::from(chunk));
110        }
111
112        None
113    }
114}
115
116// #[deprecated]
117// pub fn parse_parameters(s: &[u8], delimeter: u8) -> Vec<Parameter> {
118//     let mut parameters = Vec::new();
119
120//     let mut iter = s.split(|c| *c == delimeter);
121
122//     loop {
123//         match iter.next() {
124//             Some(s) => {
125//                 let p = Parameter::from(s);
126//                 parameters.push(p);
127//             }
128//             None => break,
129//         }
130//     }
131
132//     parameters
133// }
134
135// #[deprecated]
136// pub fn search<'a>(parameters: &'a [Parameter], name: &[u8]) -> Option<&'a Parameter<'a>> {
137//     if let Some(position) = parameters.iter().position(|p| p.name == name) {
138//         return Some(&parameters[position]);
139//     }
140//     None
141// }
142
143pub struct ParameterReader<'a> {
144    n: &'a [u8],
145    v: Option<&'a [u8]>,
146    d: u8,
147    pos: usize,
148}
149
150impl<'a> Read for ParameterReader<'a> {
151    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
152        let mut i = 0;
153        let n_length = self.n.len();
154        while self.pos + i < 1 && i < buf.len() {
155            buf[i] = self.d;
156            i += 1;
157        }
158        while self.pos + i >= 1 && self.pos + i < 1 + n_length && i < buf.len() {
159            buf[i] = self.n[self.pos + i - 1];
160            i += 1;
161        }
162        if let Some(v) = self.v {
163            let v_length = v.len();
164            while self.pos + i >= 1 + n_length && self.pos + i < 1 + n_length + 1 && i < buf.len() {
165                buf[i] = b'=';
166                i += 1;
167            }
168            while self.pos + i >= 1 + n_length + 1
169                && self.pos + i < 1 + n_length + 1 + v_length
170                && i < buf.len()
171            {
172                buf[i] = v[self.pos + i - 1 - n_length - 1];
173                i += 1;
174            }
175        }
176        self.pos += i;
177        Ok(i)
178    }
179}