Skip to main content

sim_table_core/
path.rs

1//! Table path segments and the shared legal-segment predicate.
2
3/// Whether `name` is a legal single table path segment.
4///
5/// This is the exact predicate `sim-table-db` enforces in its `child_path`
6/// check: a segment is illegal when it is empty, the relative `.`/`..` markers,
7/// or contains a path separator (`/` or `\`). Everything else is legal.
8pub fn is_legal_table_segment(name: &str) -> bool {
9    !(name.is_empty() || name == "." || name == ".." || name.contains('/') || name.contains('\\'))
10}
11
12/// A validated, slash-joinable sequence of table path segments.
13#[derive(Clone, Debug, Default, PartialEq, Eq)]
14pub struct TablePath {
15    segments: Vec<String>,
16}
17
18impl TablePath {
19    /// Create an empty path.
20    pub fn new() -> Self {
21        Self::default()
22    }
23
24    /// The accumulated segments, in order.
25    pub fn segments(&self) -> &[String] {
26        &self.segments
27    }
28
29    /// Append `segment`, validating it with [`is_legal_table_segment`].
30    pub fn push(&mut self, segment: &str) -> Result<(), TablePathError> {
31        if !is_legal_table_segment(segment) {
32            return Err(TablePathError::IllegalSegment(segment.to_owned()));
33        }
34        self.segments.push(segment.to_owned());
35        Ok(())
36    }
37
38    /// Join the segments with `/`.
39    pub fn join(&self) -> String {
40        self.segments.join("/")
41    }
42}
43
44/// Why a [`TablePath`] operation failed.
45#[derive(Clone, Debug, PartialEq, Eq)]
46pub enum TablePathError {
47    /// The given segment did not satisfy [`is_legal_table_segment`].
48    IllegalSegment(String),
49}