deb/control/de/
paragraph.rs

1// {{{ Copyright (c) Paul R. Tagliamonte <paultag@debian.org>, 2024
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE. }}}
20
21use super::Error;
22use serde::{
23    de::{self, DeserializeSeed, IntoDeserializer, Visitor},
24    forward_to_deserialize_any,
25};
26use std::iter::Peekable;
27
28// NOTE for future me:
29//
30// The serde #[serde(flatten)] implementaiton fucks us up here due to an
31// internals bug they have. It only calls deserialize_any when enumerating
32// the map, and since we're not self-describing, it'll cause issues for
33// non-string types.
34
35/// Deserializer for deb822 style Control blocks.
36pub(super) struct Deserializer<'a, IteratorT>
37where
38    IteratorT: 'a,
39    IteratorT: Iterator<Item = &'a str>,
40{
41    pub(super) iter: Peekable<IteratorT>,
42}
43
44impl<'a, IteratorT> Deserializer<'a, IteratorT>
45where
46    IteratorT: 'a,
47    IteratorT: Iterator<Item = &'a str>,
48{
49    fn next_float(&mut self) -> Result<f64, Error> {
50        if let Some(next) = self.iter.next() {
51            return next.parse().map_err(|_| Error::InvalidNumber);
52        }
53        Err(Error::EndOfFile)
54    }
55
56    fn next_number(&mut self) -> Result<i128, Error> {
57        if let Some(next) = self.iter.next() {
58            return next.parse().map_err(|_| Error::InvalidNumber);
59        }
60        Err(Error::EndOfFile)
61    }
62}
63
64macro_rules! deserialize_float {
65    ($name:ident, |$num:ident, $visitor:ident| $block:tt) => {
66        fn $name<V>(self, $visitor: V) -> Result<V::Value, Self::Error>
67        where
68            V: Visitor<'de>,
69        {
70            let $num = self.next_float()?;
71            return $block;
72        }
73    };
74}
75
76macro_rules! deserialize_numerical {
77    ($name:ident, |$num:ident, $visitor:ident| $block:tt) => {
78        fn $name<V>(self, $visitor: V) -> Result<V::Value, Self::Error>
79        where
80            V: Visitor<'de>,
81        {
82            let $num = self.next_number()?;
83            return $block;
84        }
85    };
86}
87
88impl<'a, 'de, IteratorT> de::Deserializer<'de> for &mut Deserializer<'a, IteratorT>
89where
90    IteratorT: 'a,
91    IteratorT: Iterator<Item = &'a str>,
92{
93    type Error = Error;
94
95    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
96        if let Some(next) = self.iter.next() {
97            return visitor.visit_str(next);
98        }
99        Err(Error::EndOfFile)
100    }
101
102    forward_to_deserialize_any! {
103        char unit
104        bytes byte_buf str string
105        tuple unit_struct tuple_struct newtype_struct
106        ignored_any
107    }
108
109    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
110    where
111        V: Visitor<'de>,
112    {
113        if let Some(next) = self.iter.next() {
114            return visitor.visit_str(next);
115        }
116        Err(Error::EndOfFile)
117    }
118
119    fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
120        if let Some(next) = self.iter.next() {
121            return visitor.visit_bool(match next.to_lowercase().as_str() {
122                "yes" => true,
123                "no" => false,
124                _ => return Err(Error::InvalidBool),
125            });
126        }
127        Err(Error::EndOfFile)
128    }
129
130    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
131    where
132        V: Visitor<'de>,
133    {
134        if self.iter.peek().is_some() {
135            visitor.visit_some(self)
136        } else {
137            visitor.visit_none()
138        }
139    }
140
141    deserialize_numerical!(deserialize_i8, |num, visitor| {
142        visitor.visit_i8(num as i8)
143    });
144    deserialize_numerical!(deserialize_i16, |num, visitor| {
145        visitor.visit_i16(num as i16)
146    });
147    deserialize_numerical!(deserialize_i32, |num, visitor| {
148        visitor.visit_i32(num as i32)
149    });
150    deserialize_numerical!(deserialize_i64, |num, visitor| {
151        visitor.visit_i64(num as i64)
152    });
153    deserialize_numerical!(deserialize_i128, |num, visitor| {
154        // braces are needed
155        visitor.visit_i128(num)
156    });
157
158    deserialize_numerical!(deserialize_u8, |num, visitor| {
159        visitor.visit_u8(num as u8)
160    });
161    deserialize_numerical!(deserialize_u16, |num, visitor| {
162        visitor.visit_u16(num as u16)
163    });
164    deserialize_numerical!(deserialize_u32, |num, visitor| {
165        visitor.visit_u32(num as u32)
166    });
167    deserialize_numerical!(deserialize_u64, |num, visitor| {
168        visitor.visit_u64(num as u64)
169    });
170    deserialize_numerical!(deserialize_u128, |num, visitor| {
171        visitor.visit_u128(num as u128)
172    });
173
174    deserialize_float!(deserialize_f32, |num, visitor| {
175        visitor.visit_f32(num as f32)
176    });
177    deserialize_float!(deserialize_f64, |num, visitor| {
178        // braces needed
179        visitor.visit_f64(num)
180    });
181
182    fn deserialize_struct<V>(
183        self,
184        _name: &'static str,
185        _fields: &'static [&'static str],
186        _visitor: V,
187    ) -> Result<V::Value, Self::Error>
188    where
189        V: Visitor<'de>,
190    {
191        Err(Error::BadType)
192    }
193
194    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
195    where
196        V: Visitor<'de>,
197    {
198        let mut uw = MapWrapper { de: self };
199        visitor.visit_map(&mut uw)
200    }
201
202    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
203    where
204        V: Visitor<'de>,
205    {
206        // a seq, otherwise known as a "multiline" must have a specific
207        // syntax.
208
209        if let Some(next) = self.iter.next() {
210            return visitor.visit_seq(&mut new_multiline(next.split("\n"))?);
211        }
212        Err(Error::EndOfFile)
213    }
214
215    fn deserialize_enum<V>(
216        self,
217        _: &'static str,
218        _: &'static [&'static str],
219        visitor: V,
220    ) -> Result<V::Value, Self::Error>
221    where
222        V: Visitor<'de>,
223    {
224        if let Some(next) = self.iter.next() {
225            return visitor.visit_enum(next.into_deserializer());
226        }
227        Err(Error::EndOfFile)
228    }
229}
230
231pub(super) struct Multiline<'a, IteratorT>
232where
233    IteratorT: 'a,
234    IteratorT: Iterator<Item = &'a str>,
235{
236    /// Leading token from the same line as the Key, if one exists.
237    pub(super) _leading_token: String,
238
239    /// all subsequent folded lines
240    pub(super) iter: Peekable<IteratorT>,
241}
242
243/// This is its own function to avoid the heartache with the generics
244/// above. This'll simplify things a bit to read without going insane
245/// on trait bounds. Sorry for this.
246pub(super) fn new_multiline<'a, IteratorT>(
247    mut iter: IteratorT,
248) -> Result<Multiline<'a, IteratorT>, Error>
249where
250    IteratorT: 'a,
251    IteratorT: Iterator<Item = &'a str>,
252{
253    let leading_token = iter.next().unwrap_or("");
254
255    // TODO: what to do if the `leading_token` here is set? Warn? I mean
256    // we did document it, soooo?
257
258    Ok(Multiline {
259        _leading_token: leading_token.to_string(),
260        iter: iter.peekable(),
261    })
262}
263
264impl<'a, 'de, IteratorT> de::SeqAccess<'de> for Multiline<'a, IteratorT>
265where
266    IteratorT: 'a,
267    IteratorT: Iterator<Item = &'a str>,
268{
269    type Error = Error;
270
271    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
272    where
273        T: DeserializeSeed<'de>,
274    {
275        if self.iter.peek().is_some() {
276            return seed.deserialize(self).map(Some);
277        };
278
279        Ok(None)
280    }
281}
282
283impl<'a, 'de, IteratorT> de::Deserializer<'de> for &mut Multiline<'a, IteratorT>
284where
285    IteratorT: 'a,
286    IteratorT: Iterator<Item = &'a str>,
287{
288    type Error = Error;
289
290    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
291        if let Some(next) = self.iter.next() {
292            return visitor.visit_str(next);
293        }
294        Err(Error::EndOfFile)
295    }
296
297    forward_to_deserialize_any! {
298        char unit bool
299        bytes byte_buf str string
300        tuple unit_struct tuple_struct enum newtype_struct
301        ignored_any
302
303        i8 i16 i32 i64 i128
304        u8 u16 u32 u64 u128
305        f32 f64
306
307        seq map struct identifier option
308    }
309}
310
311pub(super) struct MapWrapper<'a, 'b, IteratorT>
312where
313    IteratorT: 'a,
314    IteratorT: Iterator<Item = &'a str>,
315{
316    pub(super) de: &'b mut Deserializer<'a, IteratorT>,
317}
318
319impl<'a, 'b, 'de, IteratorT> de::MapAccess<'de> for &'b mut MapWrapper<'a, 'b, IteratorT>
320where
321    IteratorT: 'a,
322    IteratorT: Iterator<Item = &'a str>,
323{
324    type Error = Error;
325
326    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
327    where
328        K: DeserializeSeed<'de>,
329    {
330        if self.de.iter.peek().is_some() {
331            return seed.deserialize(&mut *self.de).map(Some);
332        }
333        Ok(None)
334    }
335
336    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
337    where
338        V: DeserializeSeed<'de>,
339    {
340        seed.deserialize(&mut *self.de)
341    }
342}
343
344// vim: foldmethod=marker