use super::access::{IAccess, IAccessMut, Poisoning};
use super::pointers::ISharedPointer;
use super::service_traits::{IOwned, IShared};
use std::fmt;
use std::ops::Deref;
#[repr(transparent)]
pub struct Shared<S: ?Sized + IShared> {
inner: S::Pointer,
}
impl<S: ?Sized + IShared> Shared<S> {
pub fn new(inner: S::Pointer) -> Self {
Self { inner }
}
pub fn into_inner(self) -> S::Pointer {
self.inner
}
pub fn inner(&self) -> &S::Pointer {
&self.inner
}
pub fn inner_mut(&mut self) -> &mut S::Pointer {
&mut self.inner
}
pub fn is(&self, other: &Self) -> bool {
self.inner.ptr_eq(other.inner())
}
pub fn access<U, F>(&self, f: F) -> U
where
S::Pointer: IAccess,
F: FnOnce(Poisoning<&<S::Pointer as IAccess>::Target>) -> U,
{
self.inner.access(f)
}
pub fn try_access<U, F>(&self, f: F) -> Option<U>
where
S::Pointer: IAccess,
F: FnOnce(Poisoning<&<S::Pointer as IAccess>::Target>) -> U,
{
self.inner.try_access(f)
}
pub fn access_mut<U, F>(&self, f: F) -> U
where
S::Pointer: IAccessMut,
F: FnOnce(Poisoning<&mut <S::Pointer as IAccess>::Target>) -> U,
{
self.inner.access_mut(f)
}
pub fn try_access_mut<U, F>(&self, f: F) -> Option<U>
where
S::Pointer: IAccessMut,
F: FnOnce(Poisoning<&mut <S::Pointer as IAccess>::Target>) -> U,
{
self.inner.try_access_mut(f)
}
}
impl<S: ?Sized + IShared> Deref for Shared<S>
where
S::Pointer: Deref,
{
type Target = <S::Pointer as Deref>::Target;
fn deref(&self) -> &Self::Target {
self.inner.deref()
}
}
impl<S: ?Sized + IShared> Clone for Shared<S> {
fn clone(&self) -> Self {
Shared {
inner: self.inner.clone(),
}
}
}
impl<S: ?Sized + IShared> fmt::Debug for Shared<S>
where
S::Pointer: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Shared")
.field("inner", &self.inner)
.finish()
}
}
pub enum Instance<S: ?Sized + IShared + IOwned> {
Shared(S::Pointer),
Owned(S::Instance),
}
impl<S: ?Sized + IShared + IOwned> Instance<S> {
pub fn from_shared(inner: S::Pointer) -> Self {
Self::Shared(inner)
}
pub fn from_owned(inner: S::Instance) -> Self {
Self::Owned(inner)
}
pub fn access<U, F>(&self, accessor: F) -> U
where
S::Pointer: IAccess<Target = S::Instance>,
F: FnOnce(Poisoning<&S::Instance>) -> U,
{
match self {
Self::Shared(s) => s.access(accessor),
Self::Owned(l) => accessor(Poisoning::Healthy(l)),
}
}
pub fn try_access<U, F>(&self, accessor: F) -> Option<U>
where
S::Pointer: IAccess<Target = S::Instance>,
F: FnOnce(Poisoning<&S::Instance>) -> U,
{
match self {
Self::Shared(s) => s.try_access(accessor),
Self::Owned(l) => Some(accessor(Poisoning::Healthy(l))),
}
}
pub fn access_mut<U, F>(&mut self, accessor: F) -> U
where
S::Pointer: IAccessMut<Target = S::Instance>,
F: FnOnce(Poisoning<&mut S::Instance>) -> U,
{
match self {
Self::Shared(s) => s.access_mut(accessor),
Self::Owned(l) => accessor(Poisoning::Healthy(l)),
}
}
pub fn try_access_mut<U, F>(&mut self, accessor: F) -> Option<U>
where
S::Pointer: IAccessMut<Target = S::Instance>,
F: FnOnce(Poisoning<&mut S::Instance>) -> U,
{
match self {
Self::Shared(s) => s.try_access_mut(accessor),
Self::Owned(l) => Some(accessor(Poisoning::Healthy(l))),
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::Access;
use std::rc::Rc;
#[test]
fn shared_is() {
let s1 = Shared::<u32>::new(Rc::new(Access::new(100)));
let s2 = s1.clone();
assert!(s1.is(&s2));
}
}