1use std::{
2 collections::{HashMap, HashSet},
3 fmt::Debug,
4 hash::{BuildHasherDefault, Hash, Hasher},
5 ops::{Deref, DerefMut},
6 path::{Path, PathBuf},
7 sync::Arc,
8};
9
10pub use camino::{Utf8Component, Utf8Components, Utf8Path, Utf8PathBuf, Utf8Prefix};
11use dashmap::{DashMap, DashSet};
12use indexmap::IndexSet;
13use rspack_cacheable::{
14 cacheable,
15 with::{AsRefStr, AsRefStrConverter},
16};
17use rustc_hash::FxHasher;
18use ustr::IdentityHasher;
19
20pub trait AssertUtf8 {
21 type Output;
22 fn assert_utf8(self) -> Self::Output;
23}
24
25impl AssertUtf8 for PathBuf {
26 type Output = Utf8PathBuf;
27
28 fn assert_utf8(self) -> Self::Output {
34 Utf8PathBuf::from_path_buf(self).unwrap_or_else(|p| {
35 panic!("expected UTF-8 path, got: {}", p.display());
36 })
37 }
38}
39
40impl<'a> AssertUtf8 for &'a Path {
41 type Output = &'a Utf8Path;
42
43 fn assert_utf8(self) -> Self::Output {
49 Utf8Path::from_path(self).unwrap_or_else(|| {
50 panic!("expected UTF-8 path, got: {}", self.display());
51 })
52 }
53}
54
55#[cacheable(with=AsRefStr, hashable)]
56#[derive(Clone, PartialEq, Eq)]
57pub struct ArcPath {
58 path: Arc<Path>,
59 hash: u64,
62}
63
64impl Debug for ArcPath {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 self.path.fmt(f)
67 }
68}
69
70impl ArcPath {
71 pub fn new(path: Arc<Path>) -> Self {
72 let mut hasher = FxHasher::default();
73 path.hash(&mut hasher);
74 let hash = hasher.finish();
75 Self { path, hash }
76 }
77}
78
79impl Deref for ArcPath {
80 type Target = Arc<Path>;
81
82 fn deref(&self) -> &Self::Target {
83 &self.path
84 }
85}
86
87impl DerefMut for ArcPath {
88 fn deref_mut(&mut self) -> &mut Self::Target {
89 &mut self.path
90 }
91}
92
93impl AsRef<Path> for ArcPath {
94 fn as_ref(&self) -> &Path {
95 &self.path
96 }
97}
98
99impl From<PathBuf> for ArcPath {
100 fn from(value: PathBuf) -> Self {
101 ArcPath::new(value.into())
102 }
103}
104
105impl From<&Path> for ArcPath {
106 fn from(value: &Path) -> Self {
107 ArcPath::new(value.into())
108 }
109}
110
111impl From<&Utf8Path> for ArcPath {
112 fn from(value: &Utf8Path) -> Self {
113 ArcPath::new(value.as_std_path().into())
114 }
115}
116
117impl From<&ArcPath> for ArcPath {
118 fn from(value: &ArcPath) -> Self {
119 value.clone()
120 }
121}
122
123impl From<&str> for ArcPath {
124 fn from(value: &str) -> Self {
125 ArcPath::new(<str as std::convert::AsRef<Path>>::as_ref(value).into())
126 }
127}
128
129impl AsRefStrConverter for ArcPath {
130 fn as_str(&self) -> &str {
131 self.path.to_str().expect("expect utf8 str")
132 }
133 fn from_str(s: &str) -> Self {
134 Self::from(Path::new(s))
135 }
136}
137
138impl Hash for ArcPath {
139 #[inline]
140 fn hash<H: Hasher>(&self, state: &mut H) {
141 state.write_u64(self.hash);
142 }
143}
144
145pub type ArcPathMap<V> = HashMap<ArcPath, V, BuildHasherDefault<IdentityHasher>>;
148
149pub type ArcPathSet = HashSet<ArcPath, BuildHasherDefault<IdentityHasher>>;
152
153pub type ArcPathDashMap<V> = DashMap<ArcPath, V, BuildHasherDefault<IdentityHasher>>;
156
157pub type ArcPathDashSet = DashSet<ArcPath, BuildHasherDefault<IdentityHasher>>;
160
161pub type ArcPathIndexSet = IndexSet<ArcPath, BuildHasherDefault<IdentityHasher>>;