pub struct StrictPath<Marker = ()> { /* private fields */ }Expand description
SUMMARY:
Hold a validated, system-facing filesystem path guaranteed to be within a PathBoundary.
DETAILS:
Use when you need system-facing I/O with safety proofs. For user-facing display and rooted
virtual operations prefer VirtualPath. Operations like strict_join and
strictpath_parent preserve guarantees. Display shows the real system path. String
accessors are prefixed with strictpath_ to avoid confusion.
Implementations§
Source§impl<Marker> StrictPath<Marker>
impl<Marker> StrictPath<Marker>
Sourcepub fn with_boundary<P: AsRef<Path>>(dir_path: P) -> Result<Self>
pub fn with_boundary<P: AsRef<Path>>(dir_path: P) -> Result<Self>
SUMMARY:
Create the base StrictPath anchored at the provided boundary directory.
PARAMETERS:
dir_path(AsRef<Path>): Boundary directory (must exist).
RETURNS:
Result<StrictPath<Marker>>: Base path (“” join) within the boundary.
ERRORS:
StrictPathError::InvalidRestriction: If the boundary cannot be created/validated.
NOTE: Prefer passing PathBoundary in reusable flows.
Sourcepub fn with_boundary_create<P: AsRef<Path>>(dir_path: P) -> Result<Self>
pub fn with_boundary_create<P: AsRef<Path>>(dir_path: P) -> Result<Self>
SUMMARY:
Create the base StrictPath, creating the boundary directory if missing.
Sourcepub fn strictpath_to_string_lossy(&self) -> Cow<'_, str>
pub fn strictpath_to_string_lossy(&self) -> Cow<'_, str>
SUMMARY:
Return a lossy String view of the system path. Prefer .interop_path() only for unavoidable third-party interop.
Sourcepub fn strictpath_to_str(&self) -> Option<&str>
pub fn strictpath_to_str(&self) -> Option<&str>
SUMMARY:
Return the underlying system path as &str if valid UTF‑8; otherwise None.
Sourcepub fn interop_path(&self) -> &OsStr
pub fn interop_path(&self) -> &OsStr
SUMMARY:
Return the underlying system path as &OsStr for unavoidable third-party AsRef<Path> interop.
Sourcepub fn strictpath_display(&self) -> Display<'_>
pub fn strictpath_display(&self) -> Display<'_>
SUMMARY:
Return a Display wrapper that shows the real system path.
Sourcepub fn unstrict(self) -> PathBuf
pub fn unstrict(self) -> PathBuf
SUMMARY:
Consume and return the inner PathBuf (escape hatch). Prefer .interop_path() (third-party adapters only) to borrow.
Sourcepub fn virtualize(self) -> VirtualPath<Marker>
pub fn virtualize(self) -> VirtualPath<Marker>
SUMMARY:
Convert this StrictPath into a user‑facing VirtualPath.
Sourcepub fn change_marker<NewMarker>(self) -> StrictPath<NewMarker>
pub fn change_marker<NewMarker>(self) -> StrictPath<NewMarker>
SUMMARY: Change the compile-time marker while reusing the validated strict path.
WHEN TO USE:
- After authenticating/authorizing a user and granting them access to a path
- When escalating or downgrading permissions (e.g., ReadOnly → ReadWrite)
- When reinterpreting a path’s domain (e.g., TempStorage → UserUploads)
WHEN NOT TO USE:
- When converting between path types - conversions preserve markers automatically
- When the current marker already matches your needs - no transformation needed
- When you haven’t verified authorization - NEVER change markers without checking permissions
PARAMETERS:
_none_
RETURNS:
StrictPath<NewMarker>: Same boundary-checked system path encoded with the new marker.
ERRORS:
_none_
SECURITY: The caller MUST ensure the new marker reflects real-world permissions. This method does not perform any authorization checks.
EXAMPLE:
// Verify user can write before granting write access
fn authorize_write_access(
user_id: &str,
path: StrictPath<(UserFiles, ReadOnly)>
) -> Result<StrictPath<(UserFiles, ReadWrite)>, &'static str> {
if user_id == "admin" {
Ok(path.change_marker()) // ✅ Transform after authorization check
} else {
Err("insufficient permissions") // ❌ User lacks write permission
}
}
// Function requiring write permission - enforces type safety at compile time
fn write_log_entry(path: StrictPath<(UserFiles, ReadWrite)>, content: &str) -> io::Result<()> {
path.write(content.as_bytes())
}
// Start with read-only access
let read_only_path: StrictPath<(UserFiles, ReadOnly)> =
boundary.strict_join("logs/app.log")?.change_marker();
// Elevate permissions after authorization
let read_write_path = authorize_write_access("admin", read_only_path)
.expect("user must have sufficient permissions");
// Now we can call functions requiring write access
write_log_entry(read_write_path, "Application started")?;Type Safety Guarantee:
The following code fails to compile because you cannot pass a path with one marker type to a function expecting a different marker type. This compile-time check enforces that permission changes are explicit and cannot be bypassed accidentally.
let read_only_path: StrictPath<ReadOnly> = boundary.strict_join("logs/app.log").unwrap();
fn require_write(_: StrictPath<WritePermission>) {}
// ❌ Compile error: expected `StrictPath<WritePermission>`, found `StrictPath<ReadOnly>`
require_write(read_only_path);Sourcepub fn try_into_boundary(self) -> Result<PathBoundary<Marker>>
pub fn try_into_boundary(self) -> Result<PathBoundary<Marker>>
SUMMARY:
Consume and return a new PathBoundary anchored at this strict path.
RETURNS:
Result<PathBoundary<Marker>>: Boundary anchored at the strict path’s system location (must already exist and be a directory).
ERRORS:
StrictPathError::InvalidRestriction: If the strict path does not exist or is not a directory.
Sourcepub fn try_into_boundary_create(self) -> Result<PathBoundary<Marker>>
pub fn try_into_boundary_create(self) -> Result<PathBoundary<Marker>>
SUMMARY:
Consume and return a PathBoundary, creating the directory if missing.
RETURNS:
Result<PathBoundary<Marker>>: Boundary anchored at the strict path’s system location (created if necessary).
ERRORS:
StrictPathError::InvalidRestriction: If creation or canonicalization fails.
Sourcepub fn strict_join<P: AsRef<Path>>(&self, path: P) -> Result<Self>
pub fn strict_join<P: AsRef<Path>>(&self, path: P) -> Result<Self>
SUMMARY: Join a path segment and re-validate against the boundary.
NOTE:
Never wrap .interop_path() in Path::new() to use Path::join() — that defeats all security. Always use this method.
After .unstrict() (explicit escape hatch), you own a PathBuf and can do whatever you need.
PARAMETERS:
path(AsRef<Path>): Segment or absolute path to validate.
RETURNS:
Result<StrictPath<Marker>>: Validated path inside the boundary.
ERRORS:
StrictPathError::PathResolutionError,StrictPathError::PathEscapesBoundary.
Sourcepub fn strictpath_parent(&self) -> Result<Option<Self>>
pub fn strictpath_parent(&self) -> Result<Option<Self>>
SUMMARY:
Return the parent as a new StrictPath, or None at the boundary root.
Sourcepub fn strictpath_with_file_name<S: AsRef<OsStr>>(
&self,
file_name: S,
) -> Result<Self>
pub fn strictpath_with_file_name<S: AsRef<OsStr>>( &self, file_name: S, ) -> Result<Self>
SUMMARY: Return a new path with file name changed, re‑validating against the boundary.
Sourcepub fn strictpath_with_extension<S: AsRef<OsStr>>(
&self,
extension: S,
) -> Result<Self>
pub fn strictpath_with_extension<S: AsRef<OsStr>>( &self, extension: S, ) -> Result<Self>
SUMMARY: Return a new path with extension changed; error at the boundary root.
Sourcepub fn strictpath_file_name(&self) -> Option<&OsStr>
pub fn strictpath_file_name(&self) -> Option<&OsStr>
Returns the file name component of the system path, if any.
Sourcepub fn strictpath_file_stem(&self) -> Option<&OsStr>
pub fn strictpath_file_stem(&self) -> Option<&OsStr>
Returns the file stem of the system path, if any.
Sourcepub fn strictpath_extension(&self) -> Option<&OsStr>
pub fn strictpath_extension(&self) -> Option<&OsStr>
Returns the extension of the system path, if any.
Sourcepub fn strictpath_starts_with<P: AsRef<Path>>(&self, p: P) -> bool
pub fn strictpath_starts_with<P: AsRef<Path>>(&self, p: P) -> bool
Returns true if the system path starts with the given prefix.
Sourcepub fn strictpath_ends_with<P: AsRef<Path>>(&self, p: P) -> bool
pub fn strictpath_ends_with<P: AsRef<Path>>(&self, p: P) -> bool
Returns true if the system path ends with the given suffix.
Sourcepub fn read_dir(&self) -> Result<ReadDir>
pub fn read_dir(&self) -> Result<ReadDir>
SUMMARY: Read directory entries at this path (discovery). Re‑join names through strict/virtual APIs before I/O.
Sourcepub fn read_to_string(&self) -> Result<String>
pub fn read_to_string(&self) -> Result<String>
Reads the file contents as String.
Sourcepub fn write<C: AsRef<[u8]>>(&self, contents: C) -> Result<()>
pub fn write<C: AsRef<[u8]>>(&self, contents: C) -> Result<()>
SUMMARY:
Write bytes to the file (create if missing). Accepts any AsRef<[u8]> (e.g., &str, &[u8]).
Sourcepub fn create_file(&self) -> Result<File>
pub fn create_file(&self) -> Result<File>
SUMMARY: Create or truncate the file at this strict path and return a writable handle.
PARAMETERS:
- none
RETURNS:
std::fs::File: Writable handle scoped to this boundary.
ERRORS:
std::io::Error: Propagates OS errors when the parent directory is missing or file creation fails.
EXAMPLE:
let log_path: StrictPath = boundary.strict_join("logs/app.log")?;
log_path.create_parent_dir_all()?;
let mut file = log_path.create_file()?;
file.write_all(b"session started")?;Sourcepub fn open_file(&self) -> Result<File>
pub fn open_file(&self) -> Result<File>
SUMMARY: Open the file at this strict path in read-only mode.
PARAMETERS:
- none
RETURNS:
std::fs::File: Read-only handle scoped to this boundary.
ERRORS:
std::io::Error: Propagates OS errors when the file is missing or inaccessible.
EXAMPLE:
let transcript: StrictPath = boundary.strict_join("logs/session.log")?;
transcript.create_parent_dir_all()?;
transcript.write("session start")?;
let mut file = transcript.open_file()?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
assert_eq!(contents, "session start");Sourcepub fn create_dir_all(&self) -> Result<()>
pub fn create_dir_all(&self) -> Result<()>
Creates all directories in the system path if missing (like std::fs::create_dir_all).
Sourcepub fn create_dir(&self) -> Result<()>
pub fn create_dir(&self) -> Result<()>
Creates the directory at the system path (non-recursive, like std::fs::create_dir).
Fails if the parent directory does not exist. Use create_dir_all to
create missing parent directories recursively.
Sourcepub fn create_parent_dir(&self) -> Result<()>
pub fn create_parent_dir(&self) -> Result<()>
SUMMARY:
Create only the immediate parent directory (non‑recursive). Ok(()) at the boundary root.
Sourcepub fn create_parent_dir_all(&self) -> Result<()>
pub fn create_parent_dir_all(&self) -> Result<()>
SUMMARY:
Recursively create all missing directories up to the immediate parent. Ok(()) at boundary.
Sourcepub fn strict_symlink<P: AsRef<Path>>(&self, link_path: P) -> Result<()>
pub fn strict_symlink<P: AsRef<Path>>(&self, link_path: P) -> Result<()>
SUMMARY:
Create a symbolic link at link_path pointing to this path (same boundary required).
On Windows, file vs directory symlink is selected by target metadata (or best‑effort when missing).
Relative paths are resolved as siblings; absolute paths are validated against the boundary.
Sourcepub fn strict_hard_link<P: AsRef<Path>>(&self, link_path: P) -> Result<()>
pub fn strict_hard_link<P: AsRef<Path>>(&self, link_path: P) -> Result<()>
SUMMARY:
Create a hard link at link_path pointing to this path (same boundary; caller creates parents).
Relative paths are resolved as siblings; absolute paths are validated against the boundary.
Sourcepub fn strict_rename<P: AsRef<Path>>(&self, dest: P) -> Result<()>
pub fn strict_rename<P: AsRef<Path>>(&self, dest: P) -> Result<()>
SUMMARY: Rename/move within the same boundary. Relative destinations are siblings; absolute are validated. Parents are not created automatically.
Sourcepub fn strict_copy<P: AsRef<Path>>(&self, dest: P) -> Result<u64>
pub fn strict_copy<P: AsRef<Path>>(&self, dest: P) -> Result<u64>
SUMMARY: Copy within the same boundary. Relative destinations are siblings; absolute are validated. Parents are not created automatically. Returns bytes copied.
Sourcepub fn remove_file(&self) -> Result<()>
pub fn remove_file(&self) -> Result<()>
SUMMARY: Remove the file at this path.
Sourcepub fn remove_dir(&self) -> Result<()>
pub fn remove_dir(&self) -> Result<()>
SUMMARY: Remove the directory at this path.
Sourcepub fn remove_dir_all(&self) -> Result<()>
pub fn remove_dir_all(&self) -> Result<()>
SUMMARY: Recursively remove the directory and its contents.
Trait Implementations§
Source§impl<Marker: Clone> Clone for StrictPath<Marker>
impl<Marker: Clone> Clone for StrictPath<Marker>
Source§fn clone(&self) -> StrictPath<Marker>
fn clone(&self) -> StrictPath<Marker>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<Marker> Debug for StrictPath<Marker>
impl<Marker> Debug for StrictPath<Marker>
Source§impl<Marker> Hash for StrictPath<Marker>
impl<Marker> Hash for StrictPath<Marker>
Source§impl<Marker> Ord for StrictPath<Marker>
impl<Marker> Ord for StrictPath<Marker>
Source§impl<Marker> PartialEq<StrictPath<Marker>> for VirtualPath<Marker>
impl<Marker> PartialEq<StrictPath<Marker>> for VirtualPath<Marker>
Source§impl<Marker> PartialEq<VirtualPath<Marker>> for StrictPath<Marker>
Available on crate feature virtual-path only.
impl<Marker> PartialEq<VirtualPath<Marker>> for StrictPath<Marker>
virtual-path only.