| 1 | use std::cell::UnsafeCell; |
| 2 | use std::cmp::Ordering; |
| 3 | use std::iter::FromIterator; |
| 4 | use std::ops::Index; |
| 5 | |
| 6 | use stable_deref_trait::StableDeref; |
| 7 | |
| 8 | /// Append-only version of `std::vec::Vec` where |
| 9 | /// insertion does not require mutable access |
| 10 | pub struct FrozenVec<T> { |
| 11 | vec: UnsafeCell<Vec<T>>, |
| 12 | // XXXManishearth do we need a reentrancy guard here as well? |
| 13 | // StableDeref may not guarantee that there are no side effects |
| 14 | } |
| 15 | |
| 16 | // safety: UnsafeCell implies !Sync |
| 17 | |
| 18 | impl<T> FrozenVec<T> { |
| 19 | /// Constructs a new, empty vector. |
| 20 | pub const fn new() -> Self { |
| 21 | Self { |
| 22 | vec: UnsafeCell::new(Vec::new()), |
| 23 | } |
| 24 | } |
| 25 | } |
| 26 | |
| 27 | impl<T> FrozenVec<T> { |
| 28 | // these should never return &T |
| 29 | // these should never delete any entries |
| 30 | |
| 31 | /// Appends an element to the back of the vector. |
| 32 | pub fn push(&self, val: T) { |
| 33 | unsafe { |
| 34 | let vec: *mut Vec = self.vec.get(); |
| 35 | (*vec).push(val) |
| 36 | } |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | impl<T: StableDeref> FrozenVec<T> { |
| 41 | /// Push, immediately getting a reference to the element |
| 42 | pub fn push_get(&self, val: T) -> &T::Target { |
| 43 | unsafe { |
| 44 | let vec = self.vec.get(); |
| 45 | (*vec).push(val); |
| 46 | &*(&**(*vec).get_unchecked((*vec).len() - 1) as *const T::Target) |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | /// Returns a reference to an element. |
| 51 | pub fn get(&self, index: usize) -> Option<&T::Target> { |
| 52 | unsafe { |
| 53 | let vec = self.vec.get(); |
| 54 | (*vec).get(index).map(|x| &**x) |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | /// Returns a reference to an element, without doing bounds checking. |
| 59 | /// |
| 60 | /// ## Safety |
| 61 | /// |
| 62 | /// `index` must be in bounds, i.e. it must be less than `self.len()` |
| 63 | pub unsafe fn get_unchecked(&self, index: usize) -> &T::Target { |
| 64 | let vec = self.vec.get(); |
| 65 | (*vec).get_unchecked(index) |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | impl<T: Copy> FrozenVec<T> { |
| 70 | /// Returns a copy of an element. |
| 71 | pub fn get_copy(&self, index: usize) -> Option<T> { |
| 72 | unsafe { |
| 73 | let vec: *mut Vec = self.vec.get(); |
| 74 | (*vec).get(index).copied() |
| 75 | } |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | impl<T> FrozenVec<T> { |
| 80 | /// Returns the number of elements in the vector. |
| 81 | pub fn len(&self) -> usize { |
| 82 | unsafe { |
| 83 | let vec: *mut Vec = self.vec.get(); |
| 84 | (*vec).len() |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | /// Returns `true` if the vector contains no elements. |
| 89 | pub fn is_empty(&self) -> bool { |
| 90 | self.len() == 0 |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | impl<T: StableDeref> FrozenVec<T> { |
| 95 | /// Returns the first element of the vector, or `None` if empty. |
| 96 | pub fn first(&self) -> Option<&T::Target> { |
| 97 | unsafe { |
| 98 | let vec: *mut Vec = self.vec.get(); |
| 99 | (*vec).first().map(|x: &T| &**x) |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | /// Returns the last element of the vector, or `None` if empty. |
| 104 | pub fn last(&self) -> Option<&T::Target> { |
| 105 | unsafe { |
| 106 | let vec: *mut Vec = self.vec.get(); |
| 107 | (*vec).last().map(|x: &T| &**x) |
| 108 | } |
| 109 | } |
| 110 | /// Returns an iterator over the vector. |
| 111 | pub fn iter(&self) -> Iter<T> { |
| 112 | self.into_iter() |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | impl<T: StableDeref> FrozenVec<T> { |
| 117 | /// Converts the frozen vector into a plain vector. |
| 118 | pub fn into_vec(self) -> Vec<T> { |
| 119 | self.vec.into_inner() |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | impl<T: StableDeref> FrozenVec<T> { |
| 124 | // binary search functions: they need to be reimplemented here to be safe (instead of calling |
| 125 | // their equivalents directly on the underlying Vec), as they run user callbacks that could |
| 126 | // reentrantly call other functions on this vector |
| 127 | |
| 128 | /// Binary searches this sorted vector for a given element, analogous to [slice::binary_search]. |
| 129 | pub fn binary_search(&self, x: &T::Target) -> Result<usize, usize> |
| 130 | where |
| 131 | T::Target: Ord, |
| 132 | { |
| 133 | self.binary_search_by(|p| p.cmp(x)) |
| 134 | } |
| 135 | |
| 136 | /// Binary searches this sorted vector with a comparator function, analogous to |
| 137 | /// [slice::binary_search_by]. |
| 138 | pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize> |
| 139 | where |
| 140 | F: FnMut(&'a T::Target) -> Ordering, |
| 141 | { |
| 142 | let mut size = self.len(); |
| 143 | let mut left = 0; |
| 144 | let mut right = size; |
| 145 | while left < right { |
| 146 | let mid = left + size / 2; |
| 147 | |
| 148 | // safety: like the core algorithm, mid is always within original vector len; in |
| 149 | // pathlogical cases, user could push to the vector in the meantime, but this can only |
| 150 | // increase the length, keeping this safe |
| 151 | let cmp = f(unsafe { self.get_unchecked(mid) }); |
| 152 | |
| 153 | if cmp == Ordering::Less { |
| 154 | left = mid + 1; |
| 155 | } else if cmp == Ordering::Greater { |
| 156 | right = mid; |
| 157 | } else { |
| 158 | return Ok(mid); |
| 159 | } |
| 160 | |
| 161 | size = right - left; |
| 162 | } |
| 163 | Err(left) |
| 164 | } |
| 165 | |
| 166 | /// Binary searches this sorted vector with a key extraction function, analogous to |
| 167 | /// [slice::binary_search_by_key]. |
| 168 | pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize> |
| 169 | where |
| 170 | F: FnMut(&'a T::Target) -> B, |
| 171 | B: Ord, |
| 172 | { |
| 173 | self.binary_search_by(|k| f(k).cmp(b)) |
| 174 | } |
| 175 | |
| 176 | /// Returns the index of the partition point according to the given predicate |
| 177 | /// (the index of the first element of the second partition), analogous to |
| 178 | /// [slice::partition_point]. |
| 179 | pub fn partition_point<P>(&self, mut pred: P) -> usize |
| 180 | where |
| 181 | P: FnMut(&T::Target) -> bool, |
| 182 | { |
| 183 | let mut left = 0; |
| 184 | let mut right = self.len(); |
| 185 | |
| 186 | while left != right { |
| 187 | let mid = left + (right - left) / 2; |
| 188 | // safety: like in binary_search_by |
| 189 | let value = unsafe { self.get_unchecked(mid) }; |
| 190 | if pred(value) { |
| 191 | left = mid + 1; |
| 192 | } else { |
| 193 | right = mid; |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | left |
| 198 | } |
| 199 | |
| 200 | // TODO add more |
| 201 | } |
| 202 | |
| 203 | impl<T> std::convert::AsMut<Vec<T>> for FrozenVec<T> { |
| 204 | /// Get mutable access to the underlying vector. |
| 205 | /// |
| 206 | /// This is safe, as it requires a `&mut self`, ensuring nothing is using |
| 207 | /// the 'frozen' contents. |
| 208 | fn as_mut(&mut self) -> &mut Vec<T> { |
| 209 | unsafe { &mut *self.vec.get() } |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | impl<T> Default for FrozenVec<T> { |
| 214 | fn default() -> Self { |
| 215 | FrozenVec::new() |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | impl<T: Clone> Clone for FrozenVec<T> { |
| 220 | fn clone(&self) -> Self { |
| 221 | Self { |
| 222 | vec: unsafe { self.vec.get().as_ref().unwrap() }.clone().into(), |
| 223 | } |
| 224 | } |
| 225 | } |
| 226 | |
| 227 | impl<T> From<Vec<T>> for FrozenVec<T> { |
| 228 | fn from(vec: Vec<T>) -> Self { |
| 229 | Self { |
| 230 | vec: UnsafeCell::new(vec), |
| 231 | } |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | impl<T: StableDeref> Index<usize> for FrozenVec<T> { |
| 236 | type Output = T::Target; |
| 237 | fn index(&self, idx: usize) -> &T::Target { |
| 238 | self.get(index:idx).unwrap_or_else(|| { |
| 239 | panic!( |
| 240 | "index out of bounds: the len is {} but the index is {}" , |
| 241 | self.len(), |
| 242 | idx |
| 243 | ) |
| 244 | }) |
| 245 | } |
| 246 | } |
| 247 | |
| 248 | impl<A> FromIterator<A> for FrozenVec<A> { |
| 249 | fn from_iter<T>(iter: T) -> Self |
| 250 | where |
| 251 | T: IntoIterator<Item = A>, |
| 252 | { |
| 253 | let vec: Vec<_> = iter.into_iter().collect(); |
| 254 | vec.into() |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | /// Iterator over FrozenVec, obtained via `.iter()` |
| 259 | /// |
| 260 | /// It is safe to push to the vector during iteration |
| 261 | pub struct Iter<'a, T> { |
| 262 | vec: &'a FrozenVec<T>, |
| 263 | idx: usize, |
| 264 | } |
| 265 | |
| 266 | impl<'a, T: StableDeref> Iterator for Iter<'a, T> { |
| 267 | type Item = &'a T::Target; |
| 268 | fn next(&mut self) -> Option<&'a T::Target> { |
| 269 | if let Some(ret: &::Target) = self.vec.get(self.idx) { |
| 270 | self.idx += 1; |
| 271 | Some(ret) |
| 272 | } else { |
| 273 | None |
| 274 | } |
| 275 | } |
| 276 | } |
| 277 | |
| 278 | impl<'a, T: StableDeref> IntoIterator for &'a FrozenVec<T> { |
| 279 | type Item = &'a T::Target; |
| 280 | type IntoIter = Iter<'a, T>; |
| 281 | fn into_iter(self) -> Iter<'a, T> { |
| 282 | Iter { vec: self, idx: 0 } |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | impl<T: StableDeref + PartialEq> PartialEq for FrozenVec<T> |
| 287 | where |
| 288 | T::Target: PartialEq, |
| 289 | { |
| 290 | fn eq(&self, other: &Self) -> bool { |
| 291 | unsafe { self.vec.get().as_ref() == other.vec.get().as_ref() } |
| 292 | } |
| 293 | } |
| 294 | |
| 295 | #[test ] |
| 296 | fn test_iteration() { |
| 297 | let vec = vec!["a" , "b" , "c" , "d" ]; |
| 298 | let frozen: FrozenVec<_> = vec.clone().into(); |
| 299 | |
| 300 | assert_eq!(vec, frozen.iter().collect::<Vec<_>>()); |
| 301 | for (e1, e2) in vec.iter().zip(frozen.iter()) { |
| 302 | assert_eq!(*e1, e2); |
| 303 | } |
| 304 | |
| 305 | assert_eq!(vec.len(), frozen.iter().count()) |
| 306 | } |
| 307 | |
| 308 | #[test ] |
| 309 | fn test_accessors() { |
| 310 | let vec: FrozenVec<String> = FrozenVec::new(); |
| 311 | |
| 312 | assert!(vec.is_empty()); |
| 313 | assert_eq!(vec.len(), 0); |
| 314 | assert_eq!(vec.first(), None); |
| 315 | assert_eq!(vec.last(), None); |
| 316 | assert_eq!(vec.get(1), None); |
| 317 | |
| 318 | vec.push("a" .to_string()); |
| 319 | vec.push("b" .to_string()); |
| 320 | vec.push("c" .to_string()); |
| 321 | |
| 322 | assert!(!vec.is_empty()); |
| 323 | assert_eq!(vec.len(), 3); |
| 324 | assert_eq!(vec.first(), Some("a" )); |
| 325 | assert_eq!(vec.last(), Some("c" )); |
| 326 | assert_eq!(vec.get(1), Some("b" )); |
| 327 | } |
| 328 | |
| 329 | #[test ] |
| 330 | fn test_non_stable_deref() { |
| 331 | #[derive (Copy, Clone, Debug, PartialEq, Eq)] |
| 332 | struct Moo(i32); |
| 333 | let vec: FrozenVec<Moo> = FrozenVec::new(); |
| 334 | |
| 335 | assert!(vec.is_empty()); |
| 336 | assert_eq!(vec.len(), 0); |
| 337 | assert_eq!(vec.get_copy(1), None); |
| 338 | |
| 339 | vec.push(Moo(1)); |
| 340 | vec.push(Moo(2)); |
| 341 | vec.push(Moo(3)); |
| 342 | |
| 343 | assert!(!vec.is_empty()); |
| 344 | assert_eq!(vec.len(), 3); |
| 345 | assert_eq!(vec.get_copy(1), Some(Moo(2))); |
| 346 | } |
| 347 | |
| 348 | #[test ] |
| 349 | fn test_binary_search() { |
| 350 | let vec: FrozenVec<_> = vec!["ab" , "cde" , "fghij" ].into(); |
| 351 | |
| 352 | assert_eq!(vec.binary_search("cde" ), Ok(1)); |
| 353 | assert_eq!(vec.binary_search("cdf" ), Err(2)); |
| 354 | assert_eq!(vec.binary_search("a" ), Err(0)); |
| 355 | assert_eq!(vec.binary_search("g" ), Err(3)); |
| 356 | |
| 357 | assert_eq!(vec.binary_search_by_key(&1, |x| x.len()), Err(0)); |
| 358 | assert_eq!(vec.binary_search_by_key(&3, |x| x.len()), Ok(1)); |
| 359 | assert_eq!(vec.binary_search_by_key(&4, |x| x.len()), Err(2)); |
| 360 | |
| 361 | assert_eq!(vec.partition_point(|x| x.len() < 4), 2); |
| 362 | assert_eq!(vec.partition_point(|_| false), 0); |
| 363 | assert_eq!(vec.partition_point(|_| true), 3); |
| 364 | } |
| 365 | |