use std::fmt;
use std::marker::PhantomData;
use std::sync::atomic::{AtomicU64, Ordering};
#[derive(Debug, thiserror::Error)]
#[error("edit rejected by sink: {0}")]
pub struct Error(pub String);
impl Error {
pub fn new(reason: impl Into<String>) -> Self {
Error(reason.into())
}
}
pub struct Id<K: ?Sized> {
raw: u64,
_kind: PhantomData<fn() -> K>,
}
impl<K: ?Sized> Id<K> {
fn next() -> Self {
static NEXT: AtomicU64 = AtomicU64::new(0);
Id {
raw: NEXT.fetch_add(1, Ordering::Relaxed),
_kind: PhantomData,
}
}
}
impl<K: ?Sized> Clone for Id<K> {
fn clone(&self) -> Self {
*self
}
}
impl<K: ?Sized> Copy for Id<K> {}
impl<K: ?Sized> PartialEq for Id<K> {
fn eq(&self, other: &Self) -> bool {
self.raw == other.raw
}
}
impl<K: ?Sized> Eq for Id<K> {}
impl<K: ?Sized> fmt::Debug for Id<K> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Id").field(&self.raw).finish()
}
}
pub struct Set<T: ?Sized> {
sinks: Vec<(Id<T>, Box<T>)>,
}
impl<T: ?Sized> Default for Set<T> {
fn default() -> Self {
Self { sinks: Vec::new() }
}
}
impl<T: ?Sized> Set<T> {
pub fn add(&mut self, sink: Box<T>) -> Id<T> {
let id = Id::next();
self.sinks.push((id, sink));
id
}
pub fn remove(&mut self, id: Id<T>) {
self.sinks.retain(|(sid, _)| *sid != id);
}
pub fn is_empty(&self) -> bool {
self.sinks.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.sinks.iter().map(|(_, s)| &**s)
}
}