[tor-commits] [tor/maint-0.3.3] rust: Add new protover::ProtoEntry type which uses new datatypes.
nickm at torproject.org
nickm at torproject.org
Tue Apr 3 23:16:04 UTC 2018
commit 54c964332b27104e56442128f8ce85110af89c96
Author: Isis Lovecruft <isis at torproject.org>
Date: Wed Mar 21 01:18:02 2018 +0000
rust: Add new protover::ProtoEntry type which uses new datatypes.
This replaces the `protover::SupportedProtocols` (why would you have a type just
for things which are supported?) with a new, more generic type,
`protover::ProtoEntry`, which utilises the new, more memory-efficient datatype
in protover::protoset.
* REMOVE `get_supported_protocols()` and `SupportedProtocols::tor_supported()`
(since they were never used separately) and collapse their functionality into
a single `ProtoEntry::supported()` method.
* REMOVE `SupportedProtocols::from_proto_entries()` and reimplement its
functionality as the more rusty `impl FromStr for ProtoEntry`.
* REMOVE `get_proto_and_vers()` function and refactor it into the more rusty
`impl FromStr for ProtoEntry`.
* FIXES part of #24031: https://bugs.torproject.org/24031
---
src/rust/protover/protover.rs | 144 ++++++++++++++++++++++--------------------
1 file changed, 75 insertions(+), 69 deletions(-)
diff --git a/src/rust/protover/protover.rs b/src/rust/protover/protover.rs
index 1ccad4af4..1f62e70f1 100644
--- a/src/rust/protover/protover.rs
+++ b/src/rust/protover/protover.rs
@@ -1,20 +1,19 @@
// Copyright (c) 2016-2017, The Tor Project, Inc. */
// See LICENSE for licensing information */
-use external::c_tor_version_as_new_as;
-
+use std::collections::HashMap;
+use std::collections::hash_map;
+use std::fmt;
use std::str;
use std::str::FromStr;
-use std::fmt;
-use std::collections::{HashMap, HashSet};
-use std::ops::Range;
use std::string::String;
-use std::u32;
use tor_util::strings::NUL_BYTE;
+use external::c_tor_version_as_new_as;
use errors::ProtoverError;
use protoset::Version;
+use protoset::ProtoSet;
/// The first version of Tor that included "proto" entries in its descriptors.
/// Authorities should use this to decide whether to guess proto lines.
@@ -142,82 +141,89 @@ pub fn get_supported_protocols() -> &'static str {
.unwrap_or("")
}
-pub struct SupportedProtocols(HashMap<Proto, Versions>);
-
-impl SupportedProtocols {
- pub fn from_proto_entries<I, S>(protocol_strs: I) -> Result<Self, &'static str>
- where
- I: Iterator<Item = S>,
- S: AsRef<str>,
- {
- let mut parsed = HashMap::new();
- for subproto in protocol_strs {
- let (name, version) = get_proto_and_vers(subproto.as_ref())?;
- parsed.insert(name, version);
- }
- Ok(SupportedProtocols(parsed))
+/// A map of protocol names to the versions of them which are supported.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct ProtoEntry(HashMap<Protocol, ProtoSet>);
+
+impl Default for ProtoEntry {
+ fn default() -> ProtoEntry {
+ ProtoEntry( HashMap::new() )
}
+}
- /// Translates a string representation of a protocol list to a
- /// SupportedProtocols instance.
- ///
- /// # Examples
- ///
- /// ```
- /// use protover::SupportedProtocols;
- ///
- /// let supported_protocols = SupportedProtocols::from_proto_entries_string(
- /// "HSDir=1-2 HSIntro=3-4"
- /// );
- /// ```
- pub fn from_proto_entries_string(
- proto_entries: &str,
- ) -> Result<Self, &'static str> {
- Self::from_proto_entries(proto_entries.split(" "))
+impl ProtoEntry {
+ /// Get an iterator over the `Protocol`s and their `ProtoSet`s in this `ProtoEntry`.
+ pub fn iter(&self) -> hash_map::Iter<Protocol, ProtoSet> {
+ self.0.iter()
}
/// Translate the supported tor versions from a string into a
- /// HashMap, which is useful when looking up a specific
+ /// ProtoEntry, which is useful when looking up a specific
/// subprotocol.
- ///
- fn tor_supported() -> Result<Self, &'static str> {
- Self::from_proto_entries_string(get_supported_protocols())
+ pub fn supported() -> Result<Self, ProtoverError> {
+ let supported: &'static str = get_supported_protocols();
+
+ supported.parse()
+ }
+
+ pub fn get(&self, protocol: &Protocol) -> Option<&ProtoSet> {
+ self.0.get(protocol)
+ }
+
+ pub fn insert(&mut self, key: Protocol, value: ProtoSet) {
+ self.0.insert(key, value);
+ }
+
+ pub fn remove(&mut self, key: &Protocol) -> Option<ProtoSet> {
+ self.0.remove(key)
+ }
+
+ pub fn is_empty(&self) -> bool {
+ self.0.is_empty()
}
}
-/// Parse the subprotocol type and its version numbers.
-///
-/// # Inputs
-///
-/// * A `protocol_entry` string, comprised of a keyword, an "=" sign, and one
-/// or more version numbers.
-///
-/// # Returns
-///
-/// A `Result` whose `Ok` value is a tuple of `(Proto, HashSet<u32>)`, where the
-/// first element is the subprotocol type (see `protover::Proto`) and the last
-/// element is a(n unordered) set of unique version numbers which are supported.
-/// Otherwise, the `Err` value of this `Result` is a description of the error
-///
-fn get_proto_and_vers<'a>(
- protocol_entry: &'a str,
-) -> Result<(Proto, Versions), &'static str> {
- let mut parts = protocol_entry.splitn(2, "=");
+impl FromStr for ProtoEntry {
+ type Err = ProtoverError;
- let proto = match parts.next() {
- Some(n) => n,
- None => return Err("invalid protover entry"),
- };
+ /// Parse a string of subprotocol types and their version numbers.
+ ///
+ /// # Inputs
+ ///
+ /// * A `protocol_entry` string, comprised of a keywords, an "=" sign, and
+ /// one or more version numbers, each separated by a space. For example,
+ /// `"Cons=3-4 HSDir=1"`.
+ ///
+ /// # Returns
+ ///
+ /// A `Result` whose `Ok` value is a `ProtoEntry`, where the
+ /// first element is the subprotocol type (see `protover::Protocol`) and the last
+ /// element is an ordered set of `(low, high)` unique version numbers which are supported.
+ /// Otherwise, the `Err` value of this `Result` is a `ProtoverError`.
+ fn from_str(protocol_entry: &str) -> Result<ProtoEntry, ProtoverError> {
+ let mut proto_entry: ProtoEntry = ProtoEntry::default();
+ let entries = protocol_entry.split(' ');
+
+ for entry in entries {
+ let mut parts = entry.splitn(2, '=');
+
+ let proto = match parts.next() {
+ Some(n) => n,
+ None => return Err(ProtoverError::Unparseable),
+ };
- let vers = match parts.next() {
- Some(n) => n,
- None => return Err("invalid protover entry"),
- };
+ let vers = match parts.next() {
+ Some(n) => n,
+ None => return Err(ProtoverError::Unparseable),
+ };
+ let versions: ProtoSet = vers.parse()?;
+ let proto_name: Protocol = proto.parse()?;
- let versions = Versions::from_version_string(vers)?;
- let proto_name = proto.parse()?;
+ proto_entry.insert(proto_name, versions);
+ }
- Ok((proto_name, versions))
+ Ok(proto_entry)
+ }
}
/// Parses a single subprotocol entry string into subprotocol and version
More information about the tor-commits
mailing list