diff --git a/Cargo.lock b/Cargo.lock index 5ec9f0ef9..df405015f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3441,6 +3441,7 @@ dependencies = [ "bitflags", "derive_more", "digest 0.10.3", + "educe", "hex", "hex-literal", "once_cell", diff --git a/crates/tor-netdoc/Cargo.toml b/crates/tor-netdoc/Cargo.toml index 8906635b5..c86524b93 100644 --- a/crates/tor-netdoc/Cargo.toml +++ b/crates/tor-netdoc/Cargo.toml @@ -36,6 +36,7 @@ bitflags = "1" time = { version = "0.3", features = ["std", "parsing", "macros"] } derive_more = "0.99" digest = "0.10.0" +educe = "0.4.6" hex = "0.4" once_cell = "1" phf = { version = "0.10.0", features = ["macros"] } diff --git a/crates/tor-netdoc/src/parse/parser.rs b/crates/tor-netdoc/src/parse/parser.rs index 70e43f54f..7328278f7 100644 --- a/crates/tor-netdoc/src/parse/parser.rs +++ b/crates/tor-netdoc/src/parse/parser.rs @@ -18,6 +18,8 @@ use crate::parse::rules::*; use crate::parse::tokenize::*; use crate::{ParseErrorKind as EK, Result}; +use educe::Educe; + /// Describe the rules for one section of a document. /// /// The rules are represented as a mapping from token index to @@ -36,55 +38,37 @@ pub(crate) struct SectionRules { } /// The entry or entries for a particular keyword within a document. -#[derive(Clone)] -enum TokVal<'a, K: Keyword> { - /// No value has been found. - None, - /// A single value has been found; we're storing it in place. - Some(Item<'a, K>), - /// Multiple values have been found; they go in a vector. - Multi(Vec>), -} +#[derive(Clone, Educe)] +#[educe(Default)] +struct TokVal<'a, K: Keyword>(Vec>); + impl<'a, K: Keyword> TokVal<'a, K> { + /// Return the number of Items for this value. + fn none() -> Self { + Default::default() + } /// Return the number of Items for this value. fn count(&self) -> usize { - match self { - TokVal::None => 0, - TokVal::Some(_) => 1, - TokVal::Multi(v) => v.len(), - } + self.0.len() } /// Return the first Item for this value, or None if there wasn't one. fn first(&self) -> Option<&Item<'a, K>> { - match self { - TokVal::None => None, - TokVal::Some(t) => Some(t), - TokVal::Multi(v) => Some(&v[0]), - } + self.0.get(0) } /// Return the Item for this value, if there is exactly one. fn singleton(&self) -> Option<&Item<'a, K>> { - match self { - TokVal::None => None, - TokVal::Some(t) => Some(t), - TokVal::Multi(_) => None, + match &*self.0 { + &[ref x] => Some(x), + _ => None, } } /// Return all the Items for this value, as a slice. fn as_slice(&self) -> &[Item<'a, K>] { - match self { - TokVal::None => &[], - TokVal::Some(t) => std::slice::from_ref(t), - TokVal::Multi(v) => &v[..], - } + &self.0 } /// Return the last Item for this value, if any. fn last(&self) -> Option<&Item<'a, K>> { - match self { - TokVal::None => None, - TokVal::Some(t) => Some(t), - TokVal::Multi(v) => Some(&v[v.len() - 1]), - } + self.0.last() } } @@ -108,7 +92,7 @@ impl<'a, T: Keyword> Section<'a, T> { fn new() -> Self { let n = T::n_vals(); let mut v = Vec::with_capacity(n); - v.resize(n, TokVal::None); + v.resize(n, TokVal::none()); Section { v, first: None, @@ -166,19 +150,9 @@ impl<'a, T: Keyword> Section<'a, T> { fn add_tok(&mut self, t: T, item: Item<'a, T>) { let idx = Keyword::idx(t); if idx >= self.v.len() { - self.v.resize(idx + 1, TokVal::None); + self.v.resize(idx + 1, TokVal::none()); } - let m = &mut self.v[idx]; - - match m { - TokVal::None => *m = TokVal::Some(item), - TokVal::Some(x) => { - *m = TokVal::Multi(vec![x.clone(), item]); - } - TokVal::Multi(ref mut v) => { - v.push(item); - } - }; + self.v[idx].0.push(item); if self.first.is_none() { self.first = Some(t); }