qubit-fs 0.2.1

Provider-neutral synchronous and asynchronous filesystem abstraction for Rust
Documentation
// =============================================================================
//    Copyright (c) 2025 - 2026 Haixing Hu.
//
//    SPDX-License-Identifier: Apache-2.0
//
//    Licensed under the Apache License, Version 2.0.
// =============================================================================

//! One validated logical path component.

use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FmtResult;

use crate::error::FsError;
use crate::error::FsOperation;
use crate::error::FsResult;

/// A non-empty logical component that cannot express hierarchy or traversal.
///
/// # Examples
///
/// ```rust
/// use qubit_fs::path::PathComponent;
///
/// let component = PathComponent::parse("reports")?;
/// assert_eq!("reports", component.as_str());
/// # Ok::<(), qubit_fs::FsError>(())
/// ```
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct PathComponent(
    /// Validated component text containing no hierarchy or traversal marker.
    String,
);

impl PathComponent {
    /// Parses one logical component.
    ///
    /// Returns an invalid-path error for empty input, separators, traversal
    /// markers, or NUL. This method performs no native-path conversion.
    ///
    /// # Parameters
    /// - `text`: Component text to validate.
    ///
    /// # Errors
    /// Returns an invalid-path error when `text` is empty, contains a
    /// separator, is a traversal marker, or contains NUL.
    pub fn parse(text: &str) -> FsResult<Self> {
        if text.is_empty() || matches!(text, "." | "..") || text.contains('/') || text.contains('\0') {
            return Err(FsError::invalid_path(
                FsOperation::ParsePath,
                "path component must be a non-empty non-traversal component",
            ));
        }
        Ok(Self(text.to_owned()))
    }

    /// Returns the validated logical component text.
    #[inline]
    #[must_use]
    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl Display for PathComponent {
    /// Formats the validated component without changing its lexical spelling.
    #[inline]
    fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
        formatter.write_str(self.as_str())
    }
}