diff --git a/src/canonicalization.rs b/src/canonicalization.rs index fa3950d..b90460e 100644 --- a/src/canonicalization.rs +++ b/src/canonicalization.rs @@ -1,3 +1,6 @@ +use std::str::FromStr; + +#[derive(Clone, Copy, Debug)] pub enum CanonicalizationType { Relaxed, Simple, @@ -9,7 +12,28 @@ impl Default for CanonicalizationType { } } -#[derive(Default)] +impl ToString for CanonicalizationType { + fn to_string(&self) -> String { + match self { + CanonicalizationType::Relaxed => String::from("relaxed"), + CanonicalizationType::Simple => String::from("simple"), + } + } +} + +impl FromStr for CanonicalizationType { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "relaxed" => Ok(CanonicalizationType::Relaxed), + "simple" => Ok(CanonicalizationType::Simple), + _ => Err(format!("{s}: invalid canonicalization type")), + } + } +} + +#[derive(Clone, Copy, Debug, Default)] pub struct Canonicalization { header_alg: CanonicalizationType, body_alg: CanonicalizationType, @@ -41,6 +65,31 @@ impl Canonicalization { } } +impl ToString for Canonicalization { + fn to_string(&self) -> String { + format!( + "{}/{}", + self.header_alg.to_string(), + self.body_alg.to_string() + ) + } +} + +impl FromStr for Canonicalization { + type Err = String; + + fn from_str(s: &str) -> Result { + let elems: Vec<&str> = s.split('/').collect(); + if elems.len() != 2 { + return Err(format!("{s}: invalid canonicalization")); + } + Ok(Self { + header_alg: elems[0].parse()?, + body_alg: elems[1].parse()?, + }) + } +} + fn to_lowercase(c: &mut u8) { if *c >= b'A' && *c <= b'Z' { *c += 32 diff --git a/src/config.rs b/src/config.rs index 76beea1..7098bbf 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,4 @@ +use crate::canonicalization::Canonicalization; use clap::Parser; use std::collections::HashSet; use std::fs::File; @@ -8,6 +9,8 @@ use std::path::PathBuf; #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] pub struct Config { + #[arg(short, long, default_value_t = Canonicalization::default())] + canonicalization: Canonicalization, #[arg(short, long)] domain: Vec, #[arg(short = 'D', long, value_name = "FILE")] @@ -34,6 +37,10 @@ impl Config { Ok(cnf) } + pub fn canonicalization(&self) -> Canonicalization { + self.canonicalization + } + pub fn domains(&self) -> &[String] { &self.domain }