Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 0 additions & 204 deletions src/sealed.rs

This file was deleted.

8 changes: 8 additions & 0 deletions src/sealed/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//! Collections that never leak references to their content, and therefore can be safely accessed via shared references.

mod queue;
mod set;
mod utils;

pub use queue::Queue;
pub use set::Set;
121 changes: 121 additions & 0 deletions src/sealed/queue.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
use super::utils::UnsafeWrapper;
use std::collections::{VecDeque, vec_deque};
use std::fmt;

/// FIFO queue that never leaks references to its content
pub struct Queue<T>(UnsafeWrapper<VecDeque<T>>);

impl<T> Queue<T> {
pub fn new() -> Self {
Self(UnsafeWrapper::new(VecDeque::new()))
}

pub fn with_capacity(capacity: usize) -> Self {
Self(UnsafeWrapper::new(VecDeque::with_capacity(capacity)))
}

pub fn push(&self, item: T) {
// SAFETY: `with()` is never invoked recursively
unsafe { self.0.with(|inner| inner.push_back(item)) }
}

pub fn pop(&self) -> Option<T> {
// SAFETY: `with()` is never invoked recursively
unsafe { self.0.with(|inner| inner.pop_front()) }
}

pub fn contains(&self, item: &T) -> bool
where
T: PartialEq<T>,
{
// SAFETY: `with()` is never invoked recursively
unsafe { self.0.with(|inner| inner.contains(item)) }
}

pub fn remove_all(&self, item: &T) -> bool
where
T: PartialEq<T>,
{
// SAFETY: `with()` is never invoked recursively
unsafe {
self.0.with(|inner| {
let initial_len = inner.len();
inner.retain(|e| e != item);
inner.len() != initial_len
})
}
}

pub fn clear(&self) {
// SAFETY: `with()` is never invoked recursively
unsafe { self.0.with(|inner| inner.clear()) }
}

pub fn len(&self) -> usize {
// SAFETY: `with()` is never invoked recursively
unsafe { self.0.with(|inner| inner.len()) }
}

pub fn capacity(&self) -> usize {
// SAFETY: `with()` is never invoked recursively
unsafe { self.0.with(|inner| inner.capacity()) }
}

pub fn is_empty(&self) -> bool {
self.len() == 0
}

pub fn into_inner(self) -> VecDeque<T> {
self.0.into_inner()
}
}

impl<T> From<VecDeque<T>> for Queue<T> {
fn from(vec_deque: VecDeque<T>) -> Self {
Self(UnsafeWrapper::new(vec_deque))
}
}

impl<T: fmt::Debug> fmt::Debug for Queue<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// SAFETY: `with()` is never invoked recursively
unsafe { self.0.with(|inner| inner.fmt(f)) }
}
}

impl<T> Default for Queue<T> {
fn default() -> Self {
Self::new()
}
}

impl<T: Clone> Clone for Queue<T> {
fn clone(&self) -> Self {
// SAFETY: `with()` is never invoked recursively
unsafe { self.0.with(|inner| Self(UnsafeWrapper::new(inner.clone()))) }
}
}

impl<T> IntoIterator for Queue<T> {
type Item = T;
type IntoIter = vec_deque::IntoIter<T>;

fn into_iter(self) -> Self::IntoIter {
self.0.into_inner().into_iter()
}
}

#[cfg(test)]
mod tests {
use super::*;
use static_assertions::{assert_impl_all, assert_not_impl_any};
use std::{rc::Rc, sync::Arc};

#[test]
fn test_queue_is_send_but_not_sync() {
assert_impl_all!(Queue<usize>: std::marker::Send);
assert_not_impl_any!(Queue<Rc<usize>>: std::marker::Send);
assert_not_impl_any!(Queue<Arc<usize>>: Sync);
assert_not_impl_any!(Arc<Queue<usize>>: std::marker::Send, Sync);
}
}
Loading