ockam_multiaddr/
codec.rs

1use super::{Buffer, Checked, Code, Codec, Protocol};
2use crate::proto::{DnsAddr, Node, Project, Secure, Service, Space, Tcp, Udp, Worker};
3use crate::{Error, ProtoValue};
4use core::fmt;
5use unsigned_varint::decode;
6
7pub struct StdCodec;
8
9impl Codec for StdCodec {
10    fn split_str<'a>(
11        &self,
12        _prefix: &str,
13        input: &'a str,
14    ) -> Result<(Checked<&'a str>, &'a str), Error> {
15        if let Some(p) = input.find('/') {
16            let (x, y) = input.split_at(p);
17            Ok((Checked(x), y))
18        } else {
19            Ok((Checked(input), ""))
20        }
21    }
22
23    fn split_bytes<'a>(
24        &self,
25        code: Code,
26        input: &'a [u8],
27    ) -> Result<(Checked<&'a [u8]>, &'a [u8]), Error> {
28        match code {
29            #[cfg(feature = "std")]
30            crate::proto::Ip4::CODE => {
31                if input.len() < 4 {
32                    return Err(Error::required_bytes(crate::proto::Ip4::CODE, 4));
33                }
34                let (x, y) = input.split_at(4);
35                Ok((Checked(x), y))
36            }
37            #[cfg(feature = "std")]
38            crate::proto::Ip6::CODE => {
39                if input.len() < 16 {
40                    return Err(Error::required_bytes(crate::proto::Ip6::CODE, 16));
41                }
42                let (x, y) = input.split_at(16);
43                Ok((Checked(x), y))
44            }
45            Tcp::CODE => {
46                if input.len() < 2 {
47                    return Err(Error::required_bytes(Tcp::CODE, 2));
48                }
49                let (x, y) = input.split_at(2);
50                Ok((Checked(x), y))
51            }
52            Udp::CODE => {
53                if input.len() < 2 {
54                    return Err(Error::required_bytes(Udp::CODE, 2));
55                }
56                let (x, y) = input.split_at(2);
57                Ok((Checked(x), y))
58            }
59            c @ Worker::CODE
60            | c @ DnsAddr::CODE
61            | c @ Service::CODE
62            | c @ Node::CODE
63            | c @ Project::CODE
64            | c @ Space::CODE
65            | c @ Secure::CODE => {
66                let (len, input) = decode::usize(input)?;
67                if input.len() < len {
68                    return Err(Error::required_bytes(c, len));
69                }
70                let (x, y) = input.split_at(len);
71                Ok((Checked(x), y))
72            }
73            _ => Err(Error::unregistered(code)),
74        }
75    }
76
77    fn is_valid_bytes(&self, code: Code, input: Checked<&[u8]>) -> bool {
78        match code {
79            Worker::CODE => Worker::read_bytes(input).is_ok(),
80            #[cfg(feature = "std")]
81            crate::proto::Ip4::CODE => crate::proto::Ip4::read_bytes(input).is_ok(),
82            #[cfg(feature = "std")]
83            crate::proto::Ip6::CODE => crate::proto::Ip6::read_bytes(input).is_ok(),
84            Tcp::CODE => Tcp::read_bytes(input).is_ok(),
85            Udp::CODE => Udp::read_bytes(input).is_ok(),
86            DnsAddr::CODE => DnsAddr::read_bytes(input).is_ok(),
87            Service::CODE => Service::read_bytes(input).is_ok(),
88            Node::CODE => Node::read_bytes(input).is_ok(),
89            Project::CODE => Project::read_bytes(input).is_ok(),
90            Space::CODE => Space::read_bytes(input).is_ok(),
91            Secure::CODE => Secure::read_bytes(input).is_ok(),
92            _ => false,
93        }
94    }
95
96    fn write_bytes(&self, val: &ProtoValue, buf: &mut dyn Buffer) -> Result<(), Error> {
97        match val.code() {
98            Worker::CODE => Worker::read_bytes(val.data())?.write_bytes(buf),
99            #[cfg(feature = "std")]
100            crate::proto::Ip4::CODE => crate::proto::Ip4::read_bytes(val.data())?.write_bytes(buf),
101            #[cfg(feature = "std")]
102            crate::proto::Ip6::CODE => crate::proto::Ip6::read_bytes(val.data())?.write_bytes(buf),
103            Tcp::CODE => Tcp::read_bytes(val.data())?.write_bytes(buf),
104            Udp::CODE => Udp::read_bytes(val.data())?.write_bytes(buf),
105            DnsAddr::CODE => DnsAddr::read_bytes(val.data())?.write_bytes(buf),
106            Service::CODE => Service::read_bytes(val.data())?.write_bytes(buf),
107            Node::CODE => Node::read_bytes(val.data())?.write_bytes(buf),
108            Project::CODE => Project::read_bytes(val.data())?.write_bytes(buf),
109            Space::CODE => Space::read_bytes(val.data())?.write_bytes(buf),
110            Secure::CODE => Secure::read_bytes(val.data())?.write_bytes(buf),
111            code => return Err(Error::unregistered(code)),
112        }
113        Ok(())
114    }
115
116    fn transcode_str(
117        &self,
118        prefix: &str,
119        value: Checked<&str>,
120        buf: &mut dyn Buffer,
121    ) -> Result<(), Error> {
122        match prefix {
123            Worker::PREFIX => {
124                Worker::read_str(value)?.write_bytes(buf);
125                Ok(())
126            }
127            #[cfg(feature = "std")]
128            crate::proto::Ip4::PREFIX => {
129                crate::proto::Ip4::read_str(value)?.write_bytes(buf);
130                Ok(())
131            }
132            #[cfg(feature = "std")]
133            crate::proto::Ip6::PREFIX => {
134                crate::proto::Ip6::read_str(value)?.write_bytes(buf);
135                Ok(())
136            }
137            Tcp::PREFIX => {
138                Tcp::read_str(value)?.write_bytes(buf);
139                Ok(())
140            }
141            Udp::PREFIX => {
142                Udp::read_str(value)?.write_bytes(buf);
143                Ok(())
144            }
145            DnsAddr::PREFIX => {
146                DnsAddr::read_str(value)?.write_bytes(buf);
147                Ok(())
148            }
149            Service::PREFIX => {
150                Service::read_str(value)?.write_bytes(buf);
151                Ok(())
152            }
153            Node::PREFIX => {
154                Node::read_str(value)?.write_bytes(buf);
155                Ok(())
156            }
157            Project::PREFIX => {
158                Project::read_str(value)?.write_bytes(buf);
159                Ok(())
160            }
161            Space::PREFIX => {
162                Space::read_str(value)?.write_bytes(buf);
163                Ok(())
164            }
165            Secure::PREFIX => {
166                Secure::read_str(value)?.write_bytes(buf);
167                Ok(())
168            }
169            _ => Err(Error::unregistered_prefix(prefix)),
170        }
171    }
172
173    fn transcode_bytes(
174        &self,
175        code: Code,
176        value: Checked<&[u8]>,
177        f: &mut fmt::Formatter,
178    ) -> Result<(), Error> {
179        match code {
180            Worker::CODE => {
181                Worker::read_bytes(value)?.write_str(f)?;
182                Ok(())
183            }
184            #[cfg(feature = "std")]
185            crate::proto::Ip4::CODE => {
186                crate::proto::Ip4::read_bytes(value)?.write_str(f)?;
187                Ok(())
188            }
189            #[cfg(feature = "std")]
190            crate::proto::Ip6::CODE => {
191                crate::proto::Ip6::read_bytes(value)?.write_str(f)?;
192                Ok(())
193            }
194            Tcp::CODE => {
195                Tcp::read_bytes(value)?.write_str(f)?;
196                Ok(())
197            }
198            Udp::CODE => {
199                Udp::read_bytes(value)?.write_str(f)?;
200                Ok(())
201            }
202            DnsAddr::CODE => {
203                DnsAddr::read_bytes(value)?.write_str(f)?;
204                Ok(())
205            }
206            Service::CODE => {
207                Service::read_bytes(value)?.write_str(f)?;
208                Ok(())
209            }
210            Node::CODE => {
211                Node::read_bytes(value)?.write_str(f)?;
212                Ok(())
213            }
214            Project::CODE => {
215                Project::read_bytes(value)?.write_str(f)?;
216                Ok(())
217            }
218            Space::CODE => {
219                Space::read_bytes(value)?.write_str(f)?;
220                Ok(())
221            }
222            Secure::CODE => {
223                Secure::read_bytes(value)?.write_str(f)?;
224                Ok(())
225            }
226            _ => Err(Error::unregistered(code)),
227        }
228    }
229}