cap_primitives/fs/
maybe_owned_file.rs1use crate::fs::{open_unchecked, OpenOptions};
2use maybe_owned::MaybeOwned;
3use std::ops::Deref;
4use std::path::Component;
5use std::{fmt, fs, io, mem};
6#[cfg(racy_asserts)]
7use {crate::fs::file_path, std::path::PathBuf};
8
9pub(super) struct MaybeOwnedFile<'borrow> {
24 inner: MaybeOwned<'borrow, fs::File>,
25
26 #[cfg(racy_asserts)]
27 path: Option<PathBuf>,
28}
29
30impl<'borrow> MaybeOwnedFile<'borrow> {
31 pub(super) fn borrowed(file: &'borrow fs::File) -> Self {
33 #[cfg(racy_asserts)]
34 let path = file_path(file);
35
36 Self {
37 inner: MaybeOwned::Borrowed(file),
38
39 #[cfg(racy_asserts)]
40 path,
41 }
42 }
43
44 pub(super) fn owned(file: fs::File) -> Self {
46 #[cfg(racy_asserts)]
47 let path = file_path(&file);
48
49 Self {
50 inner: MaybeOwned::Owned(file),
51
52 #[cfg(racy_asserts)]
53 path,
54 }
55 }
56
57 #[allow(dead_code)]
59 pub(super) const fn borrowed_noassert(file: &'borrow fs::File) -> Self {
60 Self {
61 inner: MaybeOwned::Borrowed(file),
62
63 #[cfg(racy_asserts)]
64 path: None,
65 }
66 }
67
68 #[allow(dead_code)]
70 pub(super) const fn owned_noassert(file: fs::File) -> Self {
71 Self {
72 inner: MaybeOwned::Owned(file),
73
74 #[cfg(racy_asserts)]
75 path: None,
76 }
77 }
78
79 pub(super) fn descend_to(&mut self, to: MaybeOwnedFile<'borrow>) -> Self {
83 #[cfg(racy_asserts)]
84 let path = self.path.clone();
85
86 #[cfg(racy_asserts)]
87 if let Some(to_path) = file_path(&to) {
88 if let Some(current_path) = &self.path {
89 assert!(
90 to_path.starts_with(current_path),
91 "attempted to descend from {:?} to {:?}",
92 to_path.display(),
93 current_path.display()
94 );
95 }
96 self.path = Some(to_path);
97 }
98
99 Self {
100 inner: mem::replace(&mut self.inner, to.inner),
101
102 #[cfg(racy_asserts)]
103 path,
104 }
105 }
106
107 #[cfg_attr(windows, allow(dead_code))]
110 pub(super) fn into_file(self, options: &OpenOptions) -> io::Result<fs::File> {
111 match self.inner {
112 MaybeOwned::Owned(file) => Ok(file),
113 MaybeOwned::Borrowed(file) => {
114 open_unchecked(file, Component::CurDir.as_ref(), options).map_err(Into::into)
118 }
119 }
120 }
121
122 #[cfg_attr(any(windows, target_os = "freebsd"), allow(dead_code))]
124 pub(super) fn unwrap_owned(self) -> fs::File {
125 match self.inner {
126 MaybeOwned::Owned(file) => file,
127 MaybeOwned::Borrowed(_) => panic!("expected owned file"),
128 }
129 }
130}
131
132impl<'borrow> Deref for MaybeOwnedFile<'borrow> {
133 type Target = fs::File;
134
135 #[inline]
136 fn deref(&self) -> &Self::Target {
137 self.inner.as_ref()
138 }
139}
140
141impl<'borrow> fmt::Debug for MaybeOwnedFile<'borrow> {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 self.deref().fmt(f)
144 }
145}