Skip to main content

sqry_core/schema/
visibility.rs

1//! Canonical visibility enumeration.
2//!
3//! Defines symbol visibility levels for filtering search results.
4
5use serde::{Deserialize, Serialize};
6use std::fmt;
7
8/// Node visibility levels for filtering.
9///
10/// Used to filter search results by the visibility/accessibility
11/// of symbols in the codebase.
12///
13/// # Serialization
14///
15/// All variants serialize to lowercase: `"public"`, `"private"`.
16///
17/// # Examples
18///
19/// ```
20/// use sqry_core::schema::Visibility;
21///
22/// let vis = Visibility::Public;
23/// assert_eq!(vis.as_str(), "public");
24///
25/// let parsed = Visibility::parse("private").unwrap();
26/// assert_eq!(parsed, Visibility::Private);
27/// ```
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
29#[serde(rename_all = "lowercase")]
30#[derive(Default)]
31pub enum Visibility {
32    /// Public symbols (exported, accessible outside defining module).
33    ///
34    /// Includes: `pub`, `export`, `public`, etc. depending on language.
35    #[default]
36    Public,
37
38    /// Private symbols (not exported, internal to defining module).
39    ///
40    /// Includes: no modifier (Rust), `private`, internal, etc.
41    Private,
42}
43
44impl Visibility {
45    /// Returns all variants in definition order.
46    #[must_use]
47    pub const fn all() -> &'static [Self] {
48        &[Self::Public, Self::Private]
49    }
50
51    /// Returns the canonical string representation.
52    #[must_use]
53    pub const fn as_str(self) -> &'static str {
54        match self {
55            Self::Public => "public",
56            Self::Private => "private",
57        }
58    }
59
60    /// Parses a string into a `Visibility`.
61    ///
62    /// Returns `None` if the string doesn't match any known visibility.
63    /// Case-insensitive.
64    #[must_use]
65    pub fn parse(s: &str) -> Option<Self> {
66        match s.to_lowercase().as_str() {
67            "public" | "pub" | "exported" => Some(Self::Public),
68            "private" | "priv" | "internal" => Some(Self::Private),
69            _ => None,
70        }
71    }
72
73    /// Returns `true` if this is public visibility.
74    #[must_use]
75    pub const fn is_public(self) -> bool {
76        matches!(self, Self::Public)
77    }
78
79    /// Returns `true` if this is private visibility.
80    #[must_use]
81    pub const fn is_private(self) -> bool {
82        matches!(self, Self::Private)
83    }
84}
85
86impl fmt::Display for Visibility {
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        f.write_str(self.as_str())
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    #[test]
97    fn test_as_str() {
98        assert_eq!(Visibility::Public.as_str(), "public");
99        assert_eq!(Visibility::Private.as_str(), "private");
100    }
101
102    #[test]
103    fn test_parse() {
104        assert_eq!(Visibility::parse("public"), Some(Visibility::Public));
105        assert_eq!(Visibility::parse("PRIVATE"), Some(Visibility::Private));
106        assert_eq!(Visibility::parse("pub"), Some(Visibility::Public));
107        assert_eq!(Visibility::parse("internal"), Some(Visibility::Private));
108        assert_eq!(Visibility::parse("unknown"), None);
109    }
110
111    #[test]
112    fn test_display() {
113        assert_eq!(format!("{}", Visibility::Public), "public");
114        assert_eq!(format!("{}", Visibility::Private), "private");
115    }
116
117    #[test]
118    fn test_serde_roundtrip() {
119        for vis in Visibility::all() {
120            let json = serde_json::to_string(vis).unwrap();
121            let deserialized: Visibility = serde_json::from_str(&json).unwrap();
122            assert_eq!(*vis, deserialized);
123        }
124    }
125
126    #[test]
127    fn test_classification() {
128        assert!(Visibility::Public.is_public());
129        assert!(!Visibility::Public.is_private());
130        assert!(Visibility::Private.is_private());
131        assert!(!Visibility::Private.is_public());
132    }
133}