use crate::types::misc::LongIdent;
use crate::{Error, Result};
use tor_llcrypto::pk::rsa::RsaIdentity;
#[derive(Clone, Debug)]
pub struct RelayFamily(Vec<RsaIdentity>);
impl RelayFamily {
pub fn new() -> Self {
RelayFamily(Vec::new())
}
pub fn contains(&self, rsa_id: &RsaIdentity) -> bool {
self.0.contains(rsa_id)
}
pub fn members(&self) -> impl Iterator<Item = &RsaIdentity> {
self.0.iter()
}
}
impl Default for RelayFamily {
fn default() -> Self {
RelayFamily::new()
}
}
impl std::str::FromStr for RelayFamily {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
let v: Result<Vec<RsaIdentity>> = s
.split(crate::parse::tokenize::is_sp)
.map(|e| e.parse::<LongIdent>().map(|v| v.into()))
.filter(Result::is_ok)
.collect();
Ok(RelayFamily(v?))
}
}
#[cfg(test)]
mod test {
#![allow(clippy::unwrap_used)]
use super::*;
use crate::Result;
#[test]
fn family() -> Result<()> {
let f = "nickname1 nickname2 $ffffffffffffffffffffffffffffffffffffffff=foo eeeeeeeeeeeeeeeeeeeEEEeeeeeeeeeeeeeeeeee ddddddddddddddddddddddddddddddddd $cccccccccccccccccccccccccccccccccccccccc~blarg ".parse::<RelayFamily>()?;
let v = vec![
RsaIdentity::from_bytes(
&hex::decode("ffffffffffffffffffffffffffffffffffffffff").unwrap()[..],
)
.unwrap(),
RsaIdentity::from_bytes(
&hex::decode("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee").unwrap()[..],
)
.unwrap(),
RsaIdentity::from_bytes(
&hex::decode("cccccccccccccccccccccccccccccccccccccccc").unwrap()[..],
)
.unwrap(),
];
assert_eq!(f.0, v);
Ok(())
}
#[test]
fn test_contains() -> Result<()> {
let family =
"ffffffffffffffffffffffffffffffffffffffff eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
.parse::<RelayFamily>()?;
let in_family = RsaIdentity::from_bytes(
&hex::decode("ffffffffffffffffffffffffffffffffffffffff").unwrap()[..],
)
.unwrap();
let not_in_family = RsaIdentity::from_bytes(
&hex::decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap()[..],
)
.unwrap();
assert!(family.contains(&in_family), "Relay not found in family");
assert!(
!family.contains(¬_in_family),
"Extra relay found in family"
);
Ok(())
}
}