use std::cell::UnsafeCell;
use std::cmp::Ordering;
use std::fmt::{Debug, Formatter};
use std::iter::{Iterator, IntoIterator};
use std::mem::transmute;
use crate::misc::stable_deref2::StableDeref2;
pub struct FrozenVec<T>(UnsafeCell<Vec<T>>);
impl<T> FrozenVec<T> {
pub fn new() -> Self {
Self(UnsafeCell::new(Vec::new()))
}
pub fn push(&self, val: T) {
unsafe {
let vec = self.0.get();
(*vec).push(val)
}
}
}
impl<T: StableDeref2> FrozenVec<T> {
pub fn push_get(&self, val: T) -> T::Target<'_> {
self.push(val);
unsafe { self.get_unchecked(self.len() - 1) }
}
pub fn get(&self, index: usize) -> Option<T::Target<'_>> {
unsafe {
let vec = self.0.get();
(*vec).get(index).map(|x| x.deref2())
}
}
pub unsafe fn get_unchecked(&self, index: usize) -> T::Target<'_> {
let vec = self.0.get();
(*vec).get_unchecked(index).deref2()
}
pub fn index(&self, idx: usize) -> T::Target<'_> {
self.get(idx).unwrap_or_else(|| {
panic!(
"index out of bounds: the len is {} but the index is {}",
self.len(),
idx
)
})
}
pub fn len(&self) -> usize {
unsafe {
let vec = self.0.get();
(*vec).len()
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn first(&self) -> Option<T::Target<'_>> {
unsafe {
let vec = self.0.get();
(*vec).first().map(|x| x.deref2())
}
}
pub fn last(&self) -> Option<T::Target<'_>> {
unsafe {
let vec = self.0.get();
(*vec).last().map(|x| x.deref2())
}
}
pub fn iter(&self) -> Iter<T> {
self.into_iter()
}
pub fn into_vec(self) -> Vec<T> {
self.0.into_inner()
}
pub fn as_mut(&mut self) -> &mut Vec<T> {
unsafe { &mut *self.0.get() }
}
pub fn binary_search<'a>(&'a self, x: T::Target<'a>) -> Result<usize, usize>
where
T::Target<'a>: Ord,
{
self.binary_search_by(|p| p.cmp(&x))
}
pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
where
F: FnMut(T::Target<'a>) -> Ordering,
{
let mut size = self.len();
let mut left = 0;
let mut right = size;
while left < right {
let mid = left + size / 2;
let cmp = f(unsafe { self.get_unchecked(mid) });
if cmp == Ordering::Less {
left = mid + 1;
} else if cmp == Ordering::Greater {
right = mid;
} else {
return Ok(mid);
}
size = right - left;
}
Err(left)
}
pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
where
F: FnMut(T::Target<'a>) -> B,
B: Ord,
{
self.binary_search_by(|k| f(k).cmp(b))
}
pub fn partition_point<P>(&self, mut pred: P) -> usize
where
P: FnMut(T::Target<'_>) -> bool,
{
let mut left = 0;
let mut right = self.len();
while left != right {
let mid = left + (right - left) / 2;
let value = unsafe { self.get_unchecked(mid) };
if pred(value) {
left = mid + 1;
} else {
right = mid;
}
}
left
}
}
impl<T> Default for FrozenVec<T> {
fn default() -> Self {
FrozenVec::new()
}
}
impl<T> From<Vec<T>> for FrozenVec<T> {
fn from(vec: Vec<T>) -> Self {
Self(UnsafeCell::new(vec))
}
}
impl<A> FromIterator<A> for FrozenVec<A> {
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = A>,
{
let vec: Vec<_> = iter.into_iter().collect();
vec.into()
}
}
pub struct Iter<'a, T> {
vec: &'a FrozenVec<T>,
idx: usize,
}
impl<'a, T: StableDeref2> Iterator for Iter<'a, T> {
type Item = T::Target<'a>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(ret) = self.vec.get(self.idx) {
self.idx += 1;
Some(ret)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(self.vec.len()))
}
}
impl<'a, T: StableDeref2> IntoIterator for &'a FrozenVec<T> {
type Item = T::Target<'a>;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
Iter { vec: self, idx: 0 }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_iteration() {
let vec = vec!["a", "b", "c", "d"];
let frozen: FrozenVec<_> = vec.clone().into();
assert_eq!(vec, frozen.iter().collect::<Vec<_>>());
for (e1, e2) in vec.iter().zip(frozen.iter()) {
assert_eq!(*e1, e2);
}
assert_eq!(vec.len(), frozen.iter().count())
}
#[test]
fn test_accessors() {
let vec: FrozenVec<String> = FrozenVec::new();
assert_eq!(vec.is_empty(), true);
assert_eq!(vec.len(), 0);
assert_eq!(vec.first(), None);
assert_eq!(vec.last(), None);
assert_eq!(vec.get(1), None);
vec.push("a".to_string());
vec.push("b".to_string());
vec.push("c".to_string());
assert_eq!(vec.is_empty(), false);
assert_eq!(vec.len(), 3);
assert_eq!(vec.first(), Some("a"));
assert_eq!(vec.last(), Some("c"));
assert_eq!(vec.get(1), Some("b"));
}
#[test]
fn test_binary_search() {
let vec: FrozenVec<_> = vec!["ab", "cde", "fghij"].into();
assert_eq!(vec.binary_search("cde"), Ok(1));
assert_eq!(vec.binary_search("cdf"), Err(2));
assert_eq!(vec.binary_search("a"), Err(0));
assert_eq!(vec.binary_search("g"), Err(3));
assert_eq!(vec.binary_search_by_key(&1, |x| x.len()), Err(0));
assert_eq!(vec.binary_search_by_key(&3, |x| x.len()), Ok(1));
assert_eq!(vec.binary_search_by_key(&4, |x| x.len()), Err(2));
assert_eq!(vec.partition_point(|x| x.len() < 4), 2);
assert_eq!(vec.partition_point(|_| false), 0);
assert_eq!(vec.partition_point(|_| true), 3);
}
}
impl<'a, T: StableDeref2 + 'a> Debug for FrozenVec<T> where T::Target<'a>: Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let this = unsafe { transmute::<&Self, &'a Self>(&self) };
f.debug_list().entries(this.iter()).finish()
}
}
impl<'a: 'b, 'b, T: StableDeref2 + 'b> Debug for FrozenSlice<'a, T> where T::Target<'b>: Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let this = unsafe { transmute::<&Self, &'a Self>(&self) };
f.debug_list().entries(this.iter()).finish()
}
}
pub struct FrozenSlice<'a, T>(&'a [T]);
pub struct FrozenSliceIter<'a, T>(std::slice::Iter<'a, T>);
impl<'a, T: StableDeref2> FrozenSlice<'a, T> {
pub fn iter(&self) -> FrozenSliceIter<'a, T> {
FrozenSliceIter(self.0.iter())
}
pub unsafe fn get_unchecked(&self, index: usize) -> T::Target<'a> {
self.0.get_unchecked(index).deref2()
}
pub fn len(&self) -> usize {
self.0.len()
}
}
impl<'a, T> From<&'a FrozenVec<T>> for FrozenSlice<'a, T> {
fn from(vec: &'a FrozenVec<T>) -> Self {
FrozenSlice(&unsafe { &*vec.0.get() })
}
}
impl<'a, T> From<&'a [T]> for FrozenSlice<'a, T> {
fn from(slice: &'a [T]) -> Self {
FrozenSlice(slice)
}
}
impl<'a, T: StableDeref2> IntoIterator for FrozenSlice<'a, T> {
type Item = T::Target<'a>;
type IntoIter = FrozenSliceIter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
FrozenSliceIter(self.0.into_iter())
}
}
impl<'a, T: StableDeref2> Iterator for FrozenSliceIter<'a, T> {
type Item = T::Target<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|x| x.deref2())
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<'a, T> Clone for FrozenSlice<'a, T> {
fn clone(&self) -> Self {
Self(self.0)
}
}
impl<'a, T> Copy for FrozenSlice<'a, T> {}