Skip to main content

strat9_kernel/namespace/
mod.rs

1//! Minimal namespace binding (temporary global table).
2//!
3//! Maps path prefixes to IPC ports for scheme dispatch.
4
5use crate::{sync::SpinLock, syscall::error::SyscallError};
6use alloc::{
7    collections::BTreeMap,
8    string::{String, ToString},
9};
10
11struct Namespace {
12    bindings: BTreeMap<String, u64>,
13}
14
15impl Namespace {
16    /// Creates a new instance.
17    const fn new() -> Self {
18        Namespace {
19            bindings: BTreeMap::new(),
20        }
21    }
22}
23
24static NAMESPACE: SpinLock<Namespace> = SpinLock::new(Namespace::new());
25
26/// Performs the bind operation.
27pub fn bind(path: &str, port_id: u64) -> Result<(), SyscallError> {
28    if path.is_empty() || !path.starts_with('/') {
29        return Err(SyscallError::InvalidArgument);
30    }
31    let mut ns = NAMESPACE.lock();
32    ns.bindings.insert(path.to_string(), port_id);
33    Ok(())
34}
35
36/// Performs the unbind operation.
37pub fn unbind(path: &str) -> Result<(), SyscallError> {
38    let mut ns = NAMESPACE.lock();
39    ns.bindings.remove(path).ok_or(SyscallError::BadHandle)?;
40    Ok(())
41}
42
43/// List all current namespace bindings (path -> port_id).
44pub fn list_all_bindings() -> alloc::vec::Vec<(String, u64)> {
45    let ns = NAMESPACE.lock();
46    ns.bindings.iter().map(|(k, v)| (k.clone(), *v)).collect()
47}
48
49/// Resolve a path to the longest matching prefix.
50///
51/// Returns (port_id, remaining_path).
52pub fn resolve(path: &str) -> Option<(u64, String)> {
53    let ns = NAMESPACE.lock();
54    let mut best: Option<(&String, &u64)> = None;
55    for (prefix, port) in ns.bindings.iter() {
56        if path.starts_with(prefix) {
57            // Ensure prefix boundary (exact match or next char is '/')
58            if path.len() == prefix.len() || path.as_bytes().get(prefix.len()) == Some(&b'/') {
59                match best {
60                    Some((best_prefix, _)) if best_prefix.len() >= prefix.len() => {}
61                    _ => best = Some((prefix, port)),
62                }
63            }
64        }
65    }
66    best.map(|(prefix, port)| {
67        let remaining = path[prefix.len()..].to_string();
68        (*port, remaining)
69    })
70}