Skip to main content

tf_types/
trust_domain.rs

1//! Trust-domain parser mirroring `tools/tf-types-ts/src/core/trust-domain.ts`.
2
3#[derive(Debug, thiserror::Error, PartialEq, Eq)]
4pub enum TrustDomainParseError {
5    #[error("empty trust-domain")]
6    Empty,
7    #[error("malformed DNS trust-domain: {0:?}")]
8    BadDns(String),
9}
10
11#[derive(Clone, Debug, PartialEq, Eq)]
12pub enum TrustDomainKind {
13    Dns,
14    Local,
15}
16
17#[derive(Clone, Debug, PartialEq, Eq)]
18pub struct ParsedTrustDomain {
19    pub kind: TrustDomainKind,
20    pub value: String,
21    pub raw: String,
22}
23
24pub fn parse_trust_domain(s: &str) -> Result<ParsedTrustDomain, TrustDomainParseError> {
25    if s.is_empty() {
26        return Err(TrustDomainParseError::Empty);
27    }
28    if let Some(rest) = s.strip_prefix("local/") {
29        if rest.is_empty() {
30            return Err(TrustDomainParseError::Empty);
31        }
32        return Ok(ParsedTrustDomain {
33            kind: TrustDomainKind::Local,
34            value: rest.to_owned(),
35            raw: s.to_owned(),
36        });
37    }
38    if !is_dns_like(s) {
39        return Err(TrustDomainParseError::BadDns(s.to_owned()));
40    }
41    Ok(ParsedTrustDomain {
42        kind: TrustDomainKind::Dns,
43        value: s.to_ascii_lowercase(),
44        raw: s.to_owned(),
45    })
46}
47
48pub fn trust_domain_equals(a: &str, b: &str) -> bool {
49    match (parse_trust_domain(a), parse_trust_domain(b)) {
50        (Ok(pa), Ok(pb)) => pa.kind == pb.kind && pa.value == pb.value,
51        _ => false,
52    }
53}
54
55fn is_dns_like(s: &str) -> bool {
56    let bytes = s.as_bytes();
57    if bytes.is_empty() {
58        return false;
59    }
60    let first = bytes[0];
61    let last = bytes[bytes.len() - 1];
62    if !is_alnum(first) || !is_alnum(last) {
63        return false;
64    }
65    bytes
66        .iter()
67        .all(|b| is_alnum(*b) || *b == b'.' || *b == b'-')
68}
69
70fn is_alnum(b: u8) -> bool {
71    b.is_ascii_alphanumeric()
72}