Skip to main content

strict_path/path/virtual_path/
fs.rs

1use super::VirtualPath;
2
3impl<Marker> VirtualPath<Marker> {
4    /// SUMMARY:
5    /// Write bytes to the underlying system path. Accepts `&str`, `String`, `&[u8]`, `Vec<u8]`, etc.
6    #[inline]
7    pub fn write<C: AsRef<[u8]>>(&self, contents: C) -> std::io::Result<()> {
8        self.inner.write(contents)
9    }
10
11    /// SUMMARY:
12    /// Append bytes to the underlying system path (create if missing). Accepts `&str`, `&[u8]`, etc.
13    ///
14    /// PARAMETERS:
15    /// - `data` (`AsRef<[u8]>`): Bytes to append to the file.
16    ///
17    /// RETURNS:
18    /// - `()`: Returns nothing on success.
19    ///
20    /// ERRORS:
21    /// - `std::io::Error`: Propagates OS errors when the file cannot be opened or written.
22    ///
23    /// EXAMPLE:
24    /// ```rust
25    /// # use strict_path::VirtualRoot;
26    /// # let root = std::env::temp_dir().join("strict-path-vpath-append");
27    /// # std::fs::create_dir_all(&root)?;
28    /// # let vroot: VirtualRoot = VirtualRoot::try_new(&root)?;
29    /// // Untrusted input from request/CLI/config/etc.
30    /// let log_file = "logs/activity.log";
31    /// let vpath = vroot.virtual_join(log_file)?;
32    /// vpath.create_parent_dir_all()?;
33    /// vpath.append("[2025-01-01] Operation A\n")?;
34    /// vpath.append("[2025-01-01] Operation B\n")?;
35    /// let contents = vpath.read_to_string()?;
36    /// assert!(contents.contains("Operation A"));
37    /// assert!(contents.contains("Operation B"));
38    /// # std::fs::remove_dir_all(&root)?;
39    /// # Ok::<_, Box<dyn std::error::Error>>(())
40    /// ```
41    #[inline]
42    pub fn append<C: AsRef<[u8]>>(&self, data: C) -> std::io::Result<()> {
43        self.inner.append(data)
44    }
45
46    /// SUMMARY:
47    /// Create or truncate the file at this virtual path and return a writable handle.
48    ///
49    /// PARAMETERS:
50    /// - _none_
51    ///
52    /// RETURNS:
53    /// - `std::fs::File`: Writable handle scoped to the same virtual root restriction.
54    ///
55    /// ERRORS:
56    /// - `std::io::Error`: Propagates operating-system errors when the parent directory is missing or file creation fails.
57    ///
58    /// EXAMPLE:
59    /// ```rust
60    /// # use strict_path::VirtualRoot;
61    /// # use std::io::Write;
62    /// # let root = std::env::temp_dir().join("strict-path-virtual-create-file");
63    /// # std::fs::create_dir_all(&root)?;
64    /// # let vroot: VirtualRoot = VirtualRoot::try_new(&root)?;
65    /// let report = vroot.virtual_join("reports/summary.txt")?;
66    /// report.create_parent_dir_all()?;
67    /// let mut file = report.create_file()?;
68    /// file.write_all(b"summary")?;
69    /// # std::fs::remove_dir_all(&root)?;
70    /// # Ok::<_, Box<dyn std::error::Error>>(())
71    /// ```
72    #[inline]
73    pub fn create_file(&self) -> std::io::Result<std::fs::File> {
74        self.inner.create_file()
75    }
76
77    /// SUMMARY:
78    /// Open the file at this virtual path in read-only mode.
79    ///
80    /// PARAMETERS:
81    /// - _none_
82    ///
83    /// RETURNS:
84    /// - `std::fs::File`: Read-only handle scoped to the same virtual root restriction.
85    ///
86    /// ERRORS:
87    /// - `std::io::Error`: Propagates operating-system errors when the file is missing or inaccessible.
88    ///
89    /// EXAMPLE:
90    /// ```rust
91    /// # use strict_path::VirtualRoot;
92    /// # use std::io::{Read, Write};
93    /// # let root = std::env::temp_dir().join("strict-path-virtual-open-file");
94    /// # std::fs::create_dir_all(&root)?;
95    /// # let vroot: VirtualRoot = VirtualRoot::try_new(&root)?;
96    /// let report = vroot.virtual_join("reports/summary.txt")?;
97    /// report.create_parent_dir_all()?;
98    /// report.write("summary")?;
99    /// let mut file = report.open_file()?;
100    /// let mut contents = String::new();
101    /// file.read_to_string(&mut contents)?;
102    /// assert_eq!(contents, "summary");
103    /// # std::fs::remove_dir_all(&root)?;
104    /// # Ok::<_, Box<dyn std::error::Error>>(())
105    /// ```
106    #[inline]
107    pub fn open_file(&self) -> std::io::Result<std::fs::File> {
108        self.inner.open_file()
109    }
110
111    /// SUMMARY:
112    /// Return an options builder for advanced file opening (read+write, append, exclusive create, etc.).
113    ///
114    /// PARAMETERS:
115    /// - _none_
116    ///
117    /// RETURNS:
118    /// - `StrictOpenOptions<Marker>`: Builder to configure file opening options.
119    ///
120    /// EXAMPLE:
121    /// ```rust
122    /// # use strict_path::VirtualRoot;
123    /// # use std::io::{Read, Write, Seek, SeekFrom};
124    /// # let root = std::env::temp_dir().join("vpath-open-with-example");
125    /// # std::fs::create_dir_all(&root)?;
126    /// # let vroot: VirtualRoot = VirtualRoot::try_new(&root)?;
127    /// // Untrusted input from request/CLI/config/etc.
128    /// let data_file = "cache/state.bin";
129    /// let cache_path = vroot.virtual_join(data_file)?;
130    /// cache_path.create_parent_dir_all()?;
131    ///
132    /// // Open with read+write access, create if missing
133    /// let mut file = cache_path.open_with()
134    ///     .read(true)
135    ///     .write(true)
136    ///     .create(true)
137    ///     .open()?;
138    /// file.write_all(b"state")?;
139    /// file.seek(SeekFrom::Start(0))?;
140    /// let mut buf = [0u8; 5];
141    /// file.read_exact(&mut buf)?;
142    /// assert_eq!(&buf, b"state");
143    /// # std::fs::remove_dir_all(&root)?;
144    /// # Ok::<_, Box<dyn std::error::Error>>(())
145    /// ```
146    #[inline]
147    pub fn open_with(&self) -> crate::path::strict_path::StrictOpenOptions<'_, Marker> {
148        self.inner.open_with()
149    }
150
151    /// SUMMARY:
152    /// Create all directories in the underlying system path if missing.
153    #[inline]
154    pub fn create_dir_all(&self) -> std::io::Result<()> {
155        self.inner.create_dir_all()
156    }
157
158    /// SUMMARY:
159    /// Create the directory at this virtual location (non‑recursive). Fails if parent missing.
160    #[inline]
161    pub fn create_dir(&self) -> std::io::Result<()> {
162        self.inner.create_dir()
163    }
164
165    /// SUMMARY:
166    /// Create only the immediate parent of this virtual path (non‑recursive). `Ok(())` at virtual root.
167    #[inline]
168    pub fn create_parent_dir(&self) -> std::io::Result<()> {
169        match self.virtualpath_parent() {
170            Ok(Some(parent)) => parent.create_dir(),
171            Ok(None) => Ok(()),
172            Err(crate::StrictPathError::PathEscapesBoundary { .. }) => Ok(()),
173            Err(e) => Err(std::io::Error::new(std::io::ErrorKind::Other, e)),
174        }
175    }
176
177    /// SUMMARY:
178    /// Recursively create all missing directories up to the immediate parent. `Ok(())` at virtual root.
179    #[inline]
180    pub fn create_parent_dir_all(&self) -> std::io::Result<()> {
181        match self.virtualpath_parent() {
182            Ok(Some(parent)) => parent.create_dir_all(),
183            Ok(None) => Ok(()),
184            Err(crate::StrictPathError::PathEscapesBoundary { .. }) => Ok(()),
185            Err(e) => Err(std::io::Error::new(std::io::ErrorKind::Other, e)),
186        }
187    }
188
189    /// SUMMARY:
190    /// Remove the file at the underlying system path.
191    #[inline]
192    pub fn remove_file(&self) -> std::io::Result<()> {
193        self.inner.remove_file()
194    }
195
196    /// SUMMARY:
197    /// Remove the directory at the underlying system path.
198    #[inline]
199    pub fn remove_dir(&self) -> std::io::Result<()> {
200        self.inner.remove_dir()
201    }
202
203    /// SUMMARY:
204    /// Recursively remove the directory and its contents at the underlying system path.
205    #[inline]
206    pub fn remove_dir_all(&self) -> std::io::Result<()> {
207        self.inner.remove_dir_all()
208    }
209}