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}