1pub mod strict_path;
2
3#[cfg(feature = "virtual-path")]
4pub mod virtual_path;
5
6#[cfg(test)]
7mod tests;
8
9use crate::StrictPathError;
10use std::ffi::OsStr;
11use std::path::PathBuf;
12
13pub(crate) fn validate_extension(
21 extension: &OsStr,
22 context_path: &std::path::Path,
23) -> Result<(), StrictPathError> {
24 for &byte in extension.as_encoded_bytes() {
25 if byte == b'/' {
28 return Err(StrictPathError::path_resolution_error(
29 context_path.to_path_buf(),
30 std::io::Error::new(
31 std::io::ErrorKind::InvalidInput,
32 "extension must not contain path separators",
33 ),
34 ));
35 }
36 #[cfg(windows)]
37 if byte == b'\\' {
38 return Err(StrictPathError::path_resolution_error(
39 context_path.to_path_buf(),
40 std::io::Error::new(
41 std::io::ErrorKind::InvalidInput,
42 "extension must not contain path separators",
43 ),
44 ));
45 }
46 if byte == 0 {
47 return Err(StrictPathError::path_resolution_error(
48 context_path.to_path_buf(),
49 std::io::Error::new(
50 std::io::ErrorKind::InvalidInput,
51 "extension must not contain NUL bytes",
52 ),
53 ));
54 }
55 }
56 Ok(())
57}
58
59#[inline]
63pub(crate) fn with_validated_extension(
64 base: &std::path::Path,
65 extension: &OsStr,
66) -> Result<PathBuf, StrictPathError> {
67 validate_extension(extension, base)?;
68 Ok(base.with_extension(extension))
69}