Lines
100 %
Functions
83.33 %
Branches
//! Implement parsing for the `pow-params` line within the `HsDescInner` layer
#[cfg_attr(not(feature = "hs-pow-full"), path = "pow/v1_stub.rs")]
pub mod v1;
use crate::doc::hsdesc::inner::HsInnerKwd;
use crate::parse::tokenize::Item;
use crate::{NetdocErrorKind as EK, Result};
use std::collections::HashSet;
use std::mem::Discriminant;
use v1::PowParamsV1;
/// A list of parsed `pow-params` lines, at most one per scheme
///
#[derive(Debug, Clone)]
pub struct PowParamSet(Vec<PowParams>);
impl PowParamSet {
/// Reference all parameters as a slice in arbitrary order
pub(super) fn slice(&self) -> &[PowParams] {
&self.0
}
/// Parse a slice of `pow-params` items
/// Unrecognized schemes are ignored. Duplicate schemes result in an error.
pub(super) fn from_items(items: &[Item<'_, HsInnerKwd>]) -> Result<Self> {
// Parse each one individually,
// verifying each time we don't have a duplicated enum discriminant.
let mut inner = Vec::new();
let mut schemes_seen: HashSet<Discriminant<PowParams>> = HashSet::new();
for item in items {
if let Some(parsed) = PowParams::try_from_item(item)? {
if schemes_seen.insert(std::mem::discriminant(&parsed)) {
// Parsed params with a scheme we haven't seen before
inner.push(parsed);
} else {
return Err(EK::DuplicateToken
.with_msg(item.kwd_str().to_owned())
.at_pos(item.pos()));
Ok(Self(inner))
/// The contents of a `pow-params` line with any recognized scheme.
/// These use a text format defined by:
/// <https://spec.torproject.org/rend-spec/hsdesc-encrypt.html#second-layer-plaintext>
#[non_exhaustive]
pub enum PowParams {
/// Parameters for the `v1` scheme
/// This scheme uses the Equi-X asymmetric puzzle, in an iterated
/// construction with Blake2b for effort adjustment. The Tor specification
/// describes this puzzle construction and references the underlying
/// algorithms:
/// <https://spec.torproject.org/hspow-spec/v1-equix.html>
V1(PowParamsV1),
impl PowParams {
/// Parse a single `pow-params` line from an `Item`
/// If the scheme is recognized, returns a PowParams or a parse error.
/// If the scheme is unknown, returns None.
/// If the scheme field is missing entirely, returns a parse error.
fn try_from_item(item: &Item<'_, HsInnerKwd>) -> Result<Option<Self>> {
let scheme = item.required_arg(0)?;
if scheme == "v1" {
Ok(Some(PowParams::V1(PowParamsV1::from_item(item)?)))
Ok(None)