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!(TreeVisibility::from_str("public").unwrap(), TreeVisibility::Public);
53        assert_eq!(TreeVisibility::from_str("link-visible").unwrap(), TreeVisibility::LinkVisible);
54        assert_eq!(TreeVisibility::from_str("link_visible").unwrap(), TreeVisibility::LinkVisible);
55        assert_eq!(TreeVisibility::from_str("private").unwrap(), TreeVisibility::Private);
56        assert!(TreeVisibility::from_str("unknown").is_err());
57    }
58
59    #[test]
60    fn test_xor_keys_roundtrip() {
61        let a = [0x11u8; 32];
62        let b = [0x22u8; 32];
63        let masked = xor_keys(&a, &b);
64        let unmasked = xor_keys(&masked, &b);
65        assert_eq!(unmasked, a);
66    }
67}