Skip to main content

hashtree_core/
visibility.rs

1//! Tree visibility helpers
2
3use std::str::FromStr;
4
5/// Tree visibility modes
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum TreeVisibility {
8    Public,
9    LinkVisible,
10    Private,
11}
12
13impl TreeVisibility {
14    pub fn as_str(&self) -> &'static str {
15        match self {
16            TreeVisibility::Public => "public",
17            TreeVisibility::LinkVisible => "link-visible",
18            TreeVisibility::Private => "private",
19        }
20    }
21}
22
23impl FromStr for TreeVisibility {
24    type Err = String;
25
26    fn from_str(s: &str) -> Result<Self, Self::Err> {
27        let normalized = s.trim().to_ascii_lowercase();
28        match normalized.as_str() {
29            "public" => Ok(TreeVisibility::Public),
30            "link-visible" | "link_visible" | "linkvisible" => Ok(TreeVisibility::LinkVisible),
31            "private" => Ok(TreeVisibility::Private),
32            _ => Err(format!("invalid visibility: {}", s)),
33        }
34    }
35}
36
37/// XOR two 32-byte keys (used for link-visible key masking)
38pub fn xor_keys(a: &[u8; 32], b: &[u8; 32]) -> [u8; 32] {
39    let mut out = [0u8; 32];
40    for i in 0..32 {
41        out[i] = a[i] ^ b[i];
42    }
43    out
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn test_visibility_parse() {
52        assert_eq!(
53            TreeVisibility::from_str("public").unwrap(),
54            TreeVisibility::Public
55        );
56        assert_eq!(
57            TreeVisibility::from_str("link-visible").unwrap(),
58            TreeVisibility::LinkVisible
59        );
60        assert_eq!(
61            TreeVisibility::from_str("link_visible").unwrap(),
62            TreeVisibility::LinkVisible
63        );
64        assert_eq!(
65            TreeVisibility::from_str("private").unwrap(),
66            TreeVisibility::Private
67        );
68        assert!(TreeVisibility::from_str("unknown").is_err());
69    }
70
71    #[test]
72    fn test_xor_keys_roundtrip() {
73        let a = [0x11u8; 32];
74        let b = [0x22u8; 32];
75        let masked = xor_keys(&a, &b);
76        let unmasked = xor_keys(&masked, &b);
77        assert_eq!(unmasked, a);
78    }
79}