rust_rcs_core/cpim/
cpim_namespace.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::borrow::Cow;
16use std::collections::BTreeMap;
17
18use crate::internet::header::Header;
19
20pub struct CPIMNamespace {
21    registered_namespaces: BTreeMap<Vec<u8>, Vec<u8>>,
22}
23
24impl<'r> CPIMNamespace {
25    pub fn new() -> CPIMNamespace {
26        CPIMNamespace {
27            registered_namespaces: BTreeMap::new(),
28        }
29    }
30
31    pub fn register(&mut self, n: &[u8], v: &[u8]) {
32        let n = n.to_vec();
33        let v = v.to_vec();
34        self.registered_namespaces.insert(n, v);
35    }
36
37    pub fn as_inflator(&'r self) -> Box<dyn Fn(&Header) -> (Vec<u8>, &[u8]) + 'r> {
38        Box::new(|header| {
39            let mut iter = header.get_name().iter();
40            if let Some(position) = iter.position(|c| *c == b'.') {
41                for (k, v) in &self.registered_namespaces {
42                    if &header.get_name()[..position] == k {
43                        let mut inflated = b"<".to_vec();
44                        inflated.extend(v);
45                        inflated.extend(b">.");
46                        inflated.extend(iter);
47                        return (inflated, header.get_value());
48                    }
49                }
50            }
51
52            (header.get_name().to_vec(), header.get_value())
53        })
54    }
55
56    pub fn as_deflator(&'r self) -> Box<dyn Fn(&Header) -> (Option<Header>, Cow<Header>) + 'r> {
57        Box::new(|header| {
58            for (k, v) in &self.registered_namespaces {
59                if header.get_name().starts_with(k) {
60                    if k.len() < header.get_name().len() {
61                        if header.get_name()[k.len()] == b'.' {
62                            let mut ns = k.clone();
63                            ns.extend(b"<");
64                            ns.extend_from_slice(header.get_name());
65                            ns.extend(b">");
66                            let h1 = Header::new(b"NS", ns);
67                            let mut deflated = v.clone();
68                            if k.len() == 0 {
69                                deflated.extend(b".");
70                                deflated.extend_from_slice(header.get_name());
71                            } else {
72                                deflated.extend_from_slice(&header.get_name()[..k.len()]);
73                            }
74                            let h2 = Header::new(deflated, header.get_value().to_vec());
75                            return (Some(h1), Cow::Owned(h2));
76                        }
77                    }
78                }
79            }
80
81            (None, Cow::Borrowed(header))
82        })
83    }
84}