use std::fmt;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, Weak};
pub struct Blob<T> {
data: Arc<dyn AsRef<[T]> + Send + Sync>,
id: u64,
}
impl<T> fmt::Debug for Blob<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Blob").field("id", &self.id).finish()
}
}
impl<T> PartialEq for Blob<T> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl<T> Clone for Blob<T> {
fn clone(&self) -> Self {
Self {
data: Arc::clone(&self.data),
id: self.id,
}
}
}
impl<T> AsRef<[T]> for Blob<T> {
fn as_ref(&self) -> &[T] {
self.data()
}
}
impl<T> From<Vec<T>> for Blob<T>
where
T: 'static + Send + Sync,
{
fn from(vec: Vec<T>) -> Self {
let boxed: Box<[T]> = vec.into();
Self::new(Arc::new(boxed))
}
}
static ID_COUNTER: AtomicU64 = AtomicU64::new(0);
impl<T> Blob<T> {
pub fn new(data: Arc<dyn AsRef<[T]> + Send + Sync>) -> Self {
Self {
data,
id: ID_COUNTER.fetch_add(1, Ordering::Relaxed),
}
}
pub fn from_raw_parts(data: Arc<dyn AsRef<[T]> + Send + Sync>, id: u64) -> Self {
Self { data, id }
}
pub fn into_raw_parts(self) -> (Arc<dyn AsRef<[T]> + Send + Sync>, u64) {
(self.data, self.id)
}
pub fn len(&self) -> usize {
self.data().len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn data(&self) -> &[T] {
self.data.as_ref().as_ref()
}
pub fn id(&self) -> u64 {
self.id
}
pub fn downgrade(&self) -> WeakBlob<T> {
WeakBlob {
data: Arc::downgrade(&self.data),
id: self.id,
}
}
}
pub struct WeakBlob<T> {
data: Weak<dyn AsRef<[T]> + Send + Sync>,
id: u64,
}
impl<T> Clone for WeakBlob<T> {
fn clone(&self) -> Self {
Self {
data: Weak::clone(&self.data),
id: self.id,
}
}
}
impl<T> WeakBlob<T> {
pub fn id(&self) -> u64 {
self.id
}
pub fn upgrade(&self) -> Option<Blob<T>> {
Some(Blob {
data: self.data.upgrade()?,
id: self.id,
})
}
}