1#[cfg(feature = "deflate")]
14mod deflate;
15#[cfg(feature = "zstd")]
16mod zstd;
17
18use std::fmt;
19
20pub const STREAM_ENCODING_DICTIONARY: &[u8] = concat!(
29 "::policy-body\nš§: B.",
31 ".H3\nData-Length: ",
32 "\n\n",
33 "ExposeRecord(",
34 ") :- Have(",
35 "), Field(",
36 ",'By','0','V.",
37 ".H3'), not Field(",
38 ",'By','1',_).\n",
39 "SelectAdvertisedCandidate(",
40 ") :- Advertised(",
41 "), AdvertisedField(",
42 "','0','",
43 "'), not AdvertisedField(",
44 ",'1',_), PeerConfidential(",
45 "SelectStoredRecord(",
46 "::as unknown\n",
48 "::as\nš§: S.",
49 ".H3\nBy: V.",
50 ".H3\nMark: ",
51 "\nš§: P.",
52 ".H3\nChallenge-side0: ",
53 "\nChallenge-side1: ",
54 "\nChannel-Binding: ",
55 "\nProof-Profile: lace-iltp-peer-proof-v3\nProof-Role: side0\n",
56 "š§: B.svyLzSM7ffc91i~XDbkMnuOsdjsw_6GrXpTSckqHlpO.H3\nData-Length: 0\n\n\n",
57 "::policy B.",
59 ".H3\n::policy-known\n",
60 "::policy-missing\n",
61 "\n::offers\nS.",
63 ".H3\n\tBy: V.",
64 ".H3\n\t",
65 ": ",
66 "\nP.",
67 ".H3\n\t:Length: ",
68 "\n\t:Type: S\n\tData-Length: ",
69 "\n\tMark: ",
70 "\n\n::offers-unshared\n",
71 "::symbols\n",
72 " 1\n\n",
73 "::response\nš§: S.",
75 ".H3\nBy: V.",
76 ".H3\nMark: ",
77 "\nš§: P.",
78 ".H3\n",
79 "\nš§: B.",
80 ".H3\nData-Length: ",
81 "\n\n",
82 "::offers-changed\n+ S.",
84 ".H3\n- S.",
85 ".H3\n\n",
86 "::want\nS.",
87 ".H3\nP.",
88 ".H3\n\n",
89 "\n::round-end\n::offers-changed\n\n::want\n\n",
91)
92.as_bytes();
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
96pub enum StreamEncoding {
97 Identity,
99 #[cfg(feature = "deflate")]
102 Deflate12c,
103 #[cfg(feature = "zstd")]
106 Zstd20c,
107}
108
109impl StreamEncoding {
110 pub const COMPILED: &'static [Self] = &[
112 #[cfg(feature = "zstd")]
113 Self::Zstd20c,
114 #[cfg(feature = "deflate")]
115 Self::Deflate12c,
116 ];
117
118 pub fn token(self) -> &'static str {
119 match self {
120 Self::Identity => "identity",
121 #[cfg(feature = "deflate")]
122 Self::Deflate12c => "deflate12c",
123 #[cfg(feature = "zstd")]
124 Self::Zstd20c => "zstd20c",
125 }
126 }
127
128 pub fn from_token(token: &str) -> Option<Self> {
130 match token {
131 "identity" => Some(Self::Identity),
132 #[cfg(feature = "deflate")]
133 "deflate12c" => Some(Self::Deflate12c),
134 #[cfg(feature = "zstd")]
135 "zstd20c" => Some(Self::Zstd20c),
136 _ => None,
137 }
138 }
139
140 pub fn parse_list<'a>(
144 tokens: impl IntoIterator<Item = &'a str>,
145 ) -> Result<Vec<Self>, &'static str> {
146 let encodings = tokens
147 .into_iter()
148 .map(|token| {
149 Self::from_token(token)
150 .ok_or("stream encoding token is unknown or not compiled into this build")
151 })
152 .collect::<Result<Vec<_>, _>>()?;
153 StreamOffers::new(&encodings)?;
154 Ok(encodings)
155 }
156
157 pub fn select(sender_encode: &[Self], receiver_decode: &[Self]) -> Self {
161 sender_encode
162 .iter()
163 .copied()
164 .find(|encoding| *encoding == Self::Identity || receiver_decode.contains(encoding))
165 .unwrap_or(Self::Identity)
166 }
167}
168
169#[derive(Debug, Clone, Default, PartialEq, Eq)]
172pub struct StreamOffers {
173 decode: Vec<StreamEncoding>,
175 encode: Vec<StreamEncoding>,
177}
178
179impl StreamOffers {
180 pub fn new(encodings: &[StreamEncoding]) -> Result<Self, &'static str> {
183 if encodings.contains(&StreamEncoding::Identity) {
184 return Err("stream encodings must not list identity, which is always implied");
185 }
186 for (index, encoding) in encodings.iter().enumerate() {
187 if encodings[..index].contains(encoding) {
188 return Err("stream encodings must not repeat a token");
189 }
190 }
191 let mut decode = encodings.to_vec();
192 decode.sort_by_key(|encoding| encoding.token());
193 Ok(Self {
194 decode,
195 encode: encodings.to_vec(),
196 })
197 }
198
199 pub(super) fn known(tokens: Vec<&str>) -> Vec<StreamEncoding> {
202 tokens
203 .into_iter()
204 .filter_map(StreamEncoding::from_token)
205 .collect()
206 }
207
208 pub(super) fn from_lists(decode: Vec<StreamEncoding>, encode: Vec<StreamEncoding>) -> Self {
209 Self { decode, encode }
210 }
211
212 pub fn decode(&self) -> &[StreamEncoding] {
214 &self.decode
215 }
216
217 pub fn encode(&self) -> &[StreamEncoding] {
220 &self.encode
221 }
222
223 pub fn select(sender: &Self, receiver: &Self) -> StreamEncoding {
225 StreamEncoding::select(&sender.encode, &receiver.decode)
226 }
227}
228
229#[derive(Debug, Clone, PartialEq, Eq)]
230pub enum StreamEncodingError {
231 Malformed(String),
236 Local(String),
238}
239
240impl fmt::Display for StreamEncodingError {
241 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
242 match self {
243 Self::Malformed(detail) => write!(f, "malformed ILTP stream encoding: {detail}"),
244 Self::Local(detail) => write!(f, "ILTP stream encoding failed: {detail}"),
245 }
246 }
247}
248
249impl std::error::Error for StreamEncodingError {}
250
251pub struct StreamEncoder(Encoder);
253
254enum Encoder {
255 Identity,
256 #[cfg(feature = "deflate")]
257 Deflate(deflate::Encoder),
258 #[cfg(feature = "zstd")]
259 Zstd(zstd::Encoder),
260}
261
262#[cfg_attr(
264 not(any(feature = "deflate", feature = "zstd")),
265 allow(unused_variables)
266)]
267impl StreamEncoder {
268 pub fn new(encoding: StreamEncoding) -> Result<Self, StreamEncodingError> {
270 let level = match encoding {
271 StreamEncoding::Identity => 0,
272 #[cfg(feature = "deflate")]
273 StreamEncoding::Deflate12c => deflate::DEFAULT_LEVEL,
274 #[cfg(feature = "zstd")]
275 StreamEncoding::Zstd20c => zstd::DEFAULT_LEVEL,
276 };
277 Self::with_level(encoding, level)
278 }
279
280 pub fn with_level(encoding: StreamEncoding, level: i32) -> Result<Self, StreamEncodingError> {
283 Ok(Self(match encoding {
284 StreamEncoding::Identity => Encoder::Identity,
285 #[cfg(feature = "deflate")]
286 StreamEncoding::Deflate12c => Encoder::Deflate(deflate::Encoder::new(level)?),
287 #[cfg(feature = "zstd")]
288 StreamEncoding::Zstd20c => Encoder::Zstd(zstd::Encoder::new(level)?),
289 }))
290 }
291
292 pub fn encode(
300 &mut self,
301 input: &[u8],
302 mode: EncodeMode,
303 output: &mut [u8],
304 ) -> Result<EncodeProgress, StreamEncodingError> {
305 match &mut self.0 {
306 Encoder::Identity => {
307 let count = match mode {
308 EncodeMode::Write => input.len().min(output.len()),
309 EncodeMode::Flush | EncodeMode::End => 0,
310 };
311 output[..count].copy_from_slice(&input[..count]);
312 Ok(EncodeProgress {
313 consumed: count,
314 produced: count,
315 done: mode != EncodeMode::Write || count == input.len(),
316 })
317 }
318 #[cfg(feature = "deflate")]
319 Encoder::Deflate(encoder) => encoder.encode(input, mode, output),
320 #[cfg(feature = "zstd")]
321 Encoder::Zstd(encoder) => encoder.encode(input, mode, output),
322 }
323 }
324
325 pub fn is_identity(&self) -> bool {
327 matches!(self.0, Encoder::Identity)
328 }
329}
330
331#[derive(Debug, Clone, Copy, PartialEq, Eq)]
333pub enum EncodeMode {
334 Write,
335 Flush,
336 End,
337}
338
339pub const ENCODE_MIN_OUTPUT: usize = 16;
342
343#[derive(Debug, Clone, Copy, PartialEq, Eq)]
347pub struct EncodeProgress {
348 pub consumed: usize,
349 pub produced: usize,
350 pub done: bool,
351}
352
353#[derive(Debug, Clone, Copy, PartialEq, Eq)]
356pub struct DecodeProgress {
357 pub consumed: usize,
358 pub produced: usize,
359}
360
361pub struct StreamDecoder(Decoder);
363
364enum Decoder {
365 Identity,
366 #[cfg(feature = "deflate")]
367 Deflate(deflate::Decoder),
368 #[cfg(feature = "zstd")]
369 Zstd(zstd::Decoder),
370}
371
372impl StreamDecoder {
373 pub fn new(encoding: StreamEncoding) -> Result<Self, StreamEncodingError> {
374 Ok(Self(match encoding {
375 StreamEncoding::Identity => Decoder::Identity,
376 #[cfg(feature = "deflate")]
377 StreamEncoding::Deflate12c => Decoder::Deflate(deflate::Decoder::new()?),
378 #[cfg(feature = "zstd")]
379 StreamEncoding::Zstd20c => Decoder::Zstd(zstd::Decoder::new()?),
380 }))
381 }
382
383 pub fn decode(
389 &mut self,
390 input: &[u8],
391 output: &mut [u8],
392 ) -> Result<DecodeProgress, StreamEncodingError> {
393 match &mut self.0 {
394 Decoder::Identity => {
395 let count = input.len().min(output.len());
396 output[..count].copy_from_slice(&input[..count]);
397 Ok(DecodeProgress {
398 consumed: count,
399 produced: count,
400 })
401 }
402 #[cfg(feature = "deflate")]
403 Decoder::Deflate(decoder) => decoder.decode(input, output),
404 #[cfg(feature = "zstd")]
405 Decoder::Zstd(decoder) => decoder.decode(input, output),
406 }
407 }
408
409 pub fn is_ended(&self) -> bool {
412 match &self.0 {
413 Decoder::Identity => true,
414 #[cfg(feature = "deflate")]
415 Decoder::Deflate(decoder) => decoder.is_ended(),
416 #[cfg(feature = "zstd")]
417 Decoder::Zstd(decoder) => decoder.is_ended(),
418 }
419 }
420}