Documentation
extern crate alloc;

use core::fmt;

use super::UnsafeSeqLock;
use alloc::sync::Arc;

pub fn arc<T>(value: T) -> (ArcSeqLockWriter<T>, ArcSeqLockReader<T>) {
    let wt = ArcSeqLockWriter::new(value);
    let rd = wt.reader();
    (wt, rd)
}

#[repr(transparent)]
pub struct ArcSeqLockWriter<T>(alloc::sync::Arc<UnsafeSeqLock<T>>);

impl<T> ArcSeqLockWriter<T> {
    pub fn new(value: T) -> Self {
        Self(Arc::new(UnsafeSeqLock::new(value)))
    }
    pub fn reader(&self) -> ArcSeqLockReader<T> {
        ArcSeqLockReader(self.0.clone())
    }
}

impl<T: Copy> ArcSeqLockWriter<T> {
    pub fn write(&mut self, value: T) {
        unsafe { self.0.write(value) }
    }
    pub fn read(&self) -> T {
        unsafe { self.0.read() }
    }
}

impl<T: fmt::Debug + Copy> fmt::Debug for ArcSeqLockWriter<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.read().fmt(f)
    }
}

#[derive(Clone)]
#[repr(transparent)]
pub struct ArcSeqLockReader<T>(Arc<UnsafeSeqLock<T>>);

impl<T: Copy> ArcSeqLockReader<T> {
    pub fn read(&self) -> T {
        unsafe { self.0.read() }
    }
    pub fn read_version(&self) -> (u64, T) {
        unsafe { self.0.read_version() }
    }
    pub fn try_read(&self) -> Option<T> {
        unsafe { self.0.try_read() }
    }
    pub fn try_read_version(&self) -> Option<(u64, T)> {
        unsafe { self.0.try_read_version() }
    }
}

impl<T: fmt::Debug + Copy> fmt::Debug for ArcSeqLockReader<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.read().fmt(f)
    }
}