Skip to main content

ruvix_shell/commands/
caps.rs

1//! Capability table command implementation.
2
3use crate::ShellBackend;
4use alloc::format;
5use alloc::string::String;
6
7/// Convert object type to display string.
8fn object_type_str(obj_type: u8) -> &'static str {
9    match obj_type {
10        0 => "Task",
11        1 => "Region",
12        2 => "Queue",
13        3 => "Timer",
14        4 => "VecStore",
15        5 => "GraphStore",
16        6 => "RvfMount",
17        7 => "Sensor",
18        _ => "Unknown",
19    }
20}
21
22/// Format rights bitmap as string.
23fn format_rights(rights: u32) -> String {
24    let mut s = String::with_capacity(8);
25
26    // Standard rights
27    if rights & 0x01 != 0 { s.push('R'); } else { s.push('-'); }
28    if rights & 0x02 != 0 { s.push('W'); } else { s.push('-'); }
29    if rights & 0x04 != 0 { s.push('X'); } else { s.push('-'); }
30    if rights & 0x08 != 0 { s.push('G'); } else { s.push('-'); }
31    if rights & 0x10 != 0 { s.push('P'); } else { s.push('-'); }
32    if rights & 0x20 != 0 { s.push('D'); } else { s.push('-'); }
33
34    s
35}
36
37/// Execute the caps command.
38#[must_use]
39pub fn execute<B: ShellBackend>(backend: &B, task_id: Option<u32>) -> String {
40    let entries = backend.capability_entries(task_id);
41
42    if entries.is_empty() {
43        return match task_id {
44            Some(id) => format!("No capabilities for task {}.", id),
45            None => String::from("No capabilities."),
46        };
47    }
48
49    let header = match task_id {
50        Some(id) => format!("Capability Table (Task {})\n", id),
51        None => String::from("Capability Table (All Tasks)\n"),
52    };
53
54    let mut output = header;
55    output.push_str("===========================\n");
56    output.push_str("  HANDLE  OBJECT_ID         TYPE       RIGHTS  BADGE    DEPTH\n");
57    output.push_str("  ------  ----------------  ---------  ------  -------  -----\n");
58
59    for entry in &entries {
60        let line = format!(
61            "  {:>6}  0x{:016X}  {:<9}  {}  {:>7}  {:>5}\n",
62            entry.handle,
63            entry.object_id,
64            object_type_str(entry.object_type),
65            format_rights(entry.rights),
66            entry.badge,
67            entry.depth
68        );
69        output.push_str(&line);
70    }
71
72    output.push_str(&format!("\nTotal: {} capability(ies)", entries.len()));
73
74    // Add rights legend
75    output.push_str("\n\nRights: R=Read, W=Write, X=Execute, G=Grant, P=Prove, D=Delete");
76
77    output
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn test_object_type_str() {
86        assert_eq!(object_type_str(0), "Task");
87        assert_eq!(object_type_str(1), "Region");
88        assert_eq!(object_type_str(4), "VecStore");
89        assert_eq!(object_type_str(255), "Unknown");
90    }
91
92    #[test]
93    fn test_format_rights() {
94        assert_eq!(format_rights(0x00), "------");
95        assert_eq!(format_rights(0x01), "R-----");
96        assert_eq!(format_rights(0x07), "RWX---");
97        assert_eq!(format_rights(0x3F), "RWXGPD");
98        assert_eq!(format_rights(0x15), "R-X-P-"); // 0x15 = 0b00010101 = R, X, P bits
99        assert_eq!(format_rights(0x29), "R--G-D"); // 0x29 = 0b00101001 = R, G, D bits
100    }
101}