1use std::convert::AsRef;
2use std::fmt;
3use std::path::{Path, PathBuf};
4
5use crate::{StrMap, StrMapConfig};
6
7type Result<T, E = fst::Error> = std::result::Result<T, E>;
8type InsertResult<R> = std::result::Result<R, InsertDuplicateError>;
9
10#[cfg(unix)]
11pub fn path_to_bytes<F, T>(path: &Path, func: F) -> T
12where
13 F: FnOnce(&[u8]) -> T,
14{
15 use std::os::unix::ffi::OsStrExt;
16
17 func(path.as_os_str().as_bytes())
18}
19
20#[cfg(unix)]
21pub fn bytes_to_path(path: &[u8]) -> PathBuf {
22 use std::ffi::OsStr;
23 use std::os::unix::ffi::OsStrExt;
24
25 Path::new(OsStr::from_bytes(path)).to_path_buf()
26}
27
28#[cfg(windows)]
29pub fn path_to_bytes<F, T>(path: &Path, func: F) -> T
30where
31 F: FnOnce(&[u8]) -> T,
32{
33 use std::char::decode_utf16;
34 use std::os::windows::ffi::OsStrExt;
35
36 let iter = decode_utf16(path.as_os_str().encode_wide());
37
38 let mut byte_repr = Vec::new();
39 let mut buf = [0; 4];
40 for item in iter {
41 match item {
42 Ok(c) => {
43 let slice = c.encode_utf8(&mut buf).as_bytes();
44 if slice == b"\\" {
45 byte_repr.push(b'/');
46 } else {
47 byte_repr.extend_from_slice(slice);
48 }
49 }
50 Err(err) => {
51 byte_repr.push(0xff);
52 byte_repr.extend_from_slice(&u16::to_le_bytes(err.unpaired_surrogate()));
53 }
54 }
55 }
56
57 func(&byte_repr)
58}
59
60#[cfg(windows)]
61pub fn bytes_to_path(mut path: &[u8]) -> PathBuf {
62 use std::ffi::OsString;
63 use std::os::windows::ffi::OsStringExt;
64
65 let mut wide: Vec<u16> = Vec::with_capacity(path.len());
66 while path.len() > 0 {
67 let stop = path.iter().position(|i| *i == 0xff).unwrap_or(path.len());
68
69 if stop > 0 {
70 let (chunk, next_path) = path.split_at(stop);
71 path = next_path;
72
73 let chunk = std::str::from_utf8(chunk).unwrap();
74 wide.extend(chunk.encode_utf16());
75 } else {
76 wide.push(u16::from_le_bytes([path[1], path[2]]));
77 path = &path[3..];
78 }
79 }
80
81 OsString::from_wide(&wide).into()
82}
83
84pub struct PathMap<T> {
86 inner: StrMap<T>,
87}
88
89impl<T> PathMap<T> {
90 pub fn empty() -> Self {
91 Self {
92 inner: StrMap::empty(),
93 }
94 }
95
96 pub fn len(&self) -> usize {
97 self.inner.len()
98 }
99
100 pub fn insert(&mut self, key: &Path, value: T) -> InsertResult<()> {
101 path_to_bytes(key, |key| self.inner.insert(key, value))
102 .map_err(|_| InsertDuplicateError::new(key))
103 }
104
105 pub fn insert_many<P: AsRef<Path>>(
106 &mut self,
107 keys: &[P],
108 vals: Vec<T>,
109 opts: &StrMapConfig,
110 ) -> Result<()> {
111 let len = keys.len();
112 assert_eq!(vals.len(), len);
113 let mut keys_data = Vec::new();
114 let mut keys_idx = Vec::with_capacity(len + 1);
115 keys_idx.push(0);
116
117 for key in keys {
118 let key = key.as_ref();
119 let start = keys_data.len();
120 path_to_bytes(key, |key| keys_data.extend_from_slice(key));
121 keys_idx.push(keys_data.len());
122
123 if self.inner.has_key(&keys_data[start..]) {
124 return Err(InsertDuplicateError::new(key).into_fst());
125 }
126 }
127
128 let mut keys_dupe = std::collections::HashSet::new();
129 let mut key_args = Vec::with_capacity(len);
130 for i in 0..len {
131 let key = &keys_data[keys_idx[i]..keys_idx[i + 1]];
132 if !keys_dupe.insert(key) {
133 return Err(InsertDuplicateError::new(keys[i].as_ref()).into_fst());
134 }
135 key_args.push(key);
136 }
137 drop(keys_dupe);
138 drop(keys_idx);
139
140 self.inner.insert_many_unchecked(&key_args, vals, opts)
141 }
142
143 pub fn first(&self) -> Option<(PathBuf, &T)> {
144 self.inner
145 .first()
146 .map(|(path, item)| (bytes_to_path(&path), item))
147 }
148
149 pub fn next(&self, curr: &Path) -> Option<(PathBuf, &T)> {
150 path_to_bytes(curr, |curr| self.inner.next(curr))
151 .map(|(path, item)| (bytes_to_path(&path), item))
152 }
153
154 pub fn should_rebalance(&self) -> bool {
155 self.inner.should_rebalance()
156 }
157
158 pub fn rebalance(&mut self, opts: &StrMapConfig) -> Result<()> {
159 self.inner.rebalance(opts)
160 }
161
162 pub fn has_key(&self, key: &Path) -> bool {
163 path_to_bytes(key, |key| self.inner.has_key(key))
164 }
165
166 pub fn get(&self, key: &Path) -> Option<&T> {
167 path_to_bytes(key, |key| self.inner.get(key))
168 }
169
170 pub fn get_mut(&mut self, key: &Path) -> Option<&mut T> {
171 path_to_bytes(key, |key| self.inner.get_mut(key))
172 }
173
174 pub fn delete(&mut self, key: &Path) -> bool {
175 path_to_bytes(key, |key| self.inner.delete(key))
176 }
177}
178
179#[derive(Debug)]
180pub struct InsertDuplicateError {
181 key: PathBuf,
182}
183
184impl InsertDuplicateError {
185 fn new(key: &Path) -> Self {
186 Self {
187 key: key.to_path_buf(),
188 }
189 }
190
191 pub fn key(&self) -> &Path {
192 &self.key
193 }
194
195 fn into_io(self) -> std::io::Error {
196 std::io::Error::new(std::io::ErrorKind::AlreadyExists, self)
197 }
198
199 fn into_fst(self) -> fst::Error {
200 self.into_io().into()
201 }
202}
203
204impl std::error::Error for InsertDuplicateError {}
205
206impl fmt::Display for InsertDuplicateError {
207 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
208 write!(
209 f,
210 "trying to insert at existing key \"{}\"",
211 self.key.display()
212 )
213 }
214}