Netdoc: tweak definition for keywords to accommodate annotations

The macro can now define annotations that don't count as regular
keywords.  Additionally, the Keyword trait is now tweaked to take
advantage of the fact that every Keyword is Copy.
This commit is contained in:
Nick Mathewson 2020-05-27 13:09:22 -04:00
parent 75d24e6742
commit 9742f3ac42
4 changed files with 23 additions and 7 deletions

View File

@ -25,11 +25,13 @@ pub trait Keyword: Hash + Eq + PartialEq + Copy + Clone {
fn from_idx(i: usize) -> Option<Self>;
/// Find a string corresponding to this keyword. This may not be the
/// actual string from the document; it is indended for reporting errors.
fn to_str(&self) -> &'static str;
fn to_str(self) -> &'static str;
/// Return the index for this keyword.
fn idx(self) -> usize;
/// Return the number of indices for this keyword.
fn n_vals() -> usize;
/// Return true iff this keyword denotes an annotation.
fn is_annotation(self) -> bool;
/// Convert from an index to a human-readable string.
fn idx_to_str(i: usize) -> &'static str {
Self::from_idx(i)
@ -37,7 +39,7 @@ pub trait Keyword: Hash + Eq + PartialEq + Copy + Clone {
.unwrap_or("<out of range>")
}
/// Return a new TokenFmtBuilder for creating rules about this keyword.
fn rule(&self) -> rules::TokenFmtBuilder<Self> {
rules::TokenFmtBuilder::new(*self)
fn rule(self) -> rules::TokenFmtBuilder<Self> {
rules::TokenFmtBuilder::new(self)
}
}

View File

@ -21,7 +21,7 @@
/// ```
macro_rules! decl_keyword {
{ $(#[$meta:meta])* $v:vis
$name:ident { $( $($s:literal)|+ => $i:ident),* $(,)? } } => {
$name:ident { $( $($anno:ident)? $($s:literal)|+ => $i:ident),* $(,)? } } => {
#[derive(Copy,Clone,Eq,PartialEq,Debug,std::hash::Hash)]
#[allow(non_camel_case_types)]
$(#[$meta])*
@ -61,7 +61,7 @@ macro_rules! decl_keyword {
};
VALS.get(i).copied()
}
fn to_str(&self) -> &'static str {
fn to_str(self) -> &'static str {
use $name::*;
match self {
// TODO: this turns "accept" | "reject" into
@ -72,6 +72,17 @@ macro_rules! decl_keyword {
ANN_UNRECOGNIZED => "<unrecognized annotation>"
}
}
fn is_annotation(self) -> bool {
use $name::*;
match self {
$( $i => decl_keyword![@impl is_anno $($anno)? ], )*
UNRECOGNIZED => false,
ANN_UNRECOGNIZED => true,
}
}
}
}
};
[ @impl is_anno annotation ] => ( true );
[ @impl is_anno $x:ident ] => ( compile_error!("unrecognized keyword; not annotation") );
[ @impl is_anno ] => ( false );
}

View File

@ -1,7 +1,7 @@
//! Parsing implementation for Tor microdescriptors.
//!
//! A "microdescriptor" is an incomplete, infrequently-changing
//! summary of a relay's informatino information that is generated by
//! summary of a relay's information that is generated by
//! the directory authorities.
//!
//! Microdescriptors are much smaller than router descriptors, and
@ -41,6 +41,7 @@ pub struct Microdesc {
decl_keyword! {
/// Keyword type for recognized objects in microdescriptors.
MicrodescKW {
annotation "last-listed" => A_LAST_LISTED,
"onion-key" => ONION_KEY,
"ntor-onion-key" => NTOR_ONION_KEY,
"family" => FAMILY,

View File

@ -113,6 +113,8 @@ decl_keyword! {
/// RouterKW is an instance of Keyword, used to denote the different
/// Items that are recognized as appearing in a router descriptor.
RouterKW {
annotation "@source" => A_SOURCE,
annotation "@downloaded-at" => A_DOWNLOADED_AT,
"accept" | "reject" => POLICY,
"bandwidth" => BANDWIDTH,
"bridge-distribution-request" => BRIDGE_DISTRIBUTION_REQUEST,