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}