use leptos::prelude::*;
use std::ops::{Deref, DerefMut};
pub struct OptionLocalRwSignal<T> {
#[cfg(feature = "ssr")]
_data: std::marker::PhantomData<fn() -> T>,
#[cfg(not(feature = "ssr"))]
inner: RwSignal<Option<T>, LocalStorage>,
#[cfg(debug_assertions)]
defined_at: &'static std::panic::Location<'static>,
}
impl<T> OptionLocalRwSignal<T>
where
T: 'static,
{
#[track_caller]
pub fn new() -> Self {
Self {
#[cfg(feature = "ssr")]
_data: std::marker::PhantomData,
#[cfg(not(feature = "ssr"))]
inner: RwSignal::new_local(None),
#[cfg(debug_assertions)]
defined_at: std::panic::Location::caller(),
}
}
#[track_caller]
#[allow(unused_mut)]
pub fn read_only(mut self) -> OptionLocalSignal<T> {
#[cfg(not(feature = "ssr"))]
{
let new_inner = ArcRwSignal::from(self.inner);
self.inner = RwSignal::from_local(new_inner);
}
OptionLocalSignal {
inner: self,
#[cfg(debug_assertions)]
defined_at: std::panic::Location::caller(),
}
}
}
impl<T> Default for OptionLocalRwSignal<T>
where
T: 'static,
{
#[track_caller]
fn default() -> Self {
Self::new()
}
}
impl<T> Clone for OptionLocalRwSignal<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for OptionLocalRwSignal<T> {}
impl<T> DefinedAt for OptionLocalRwSignal<T> {
#[inline(always)]
fn defined_at(&self) -> Option<&'static std::panic::Location<'static>> {
#[cfg(debug_assertions)]
{
Some(self.defined_at)
}
#[cfg(not(debug_assertions))]
{
None
}
}
}
#[cfg(feature = "ssr")]
pub type OptionLocalGuard<T> = NoneGuard<T>;
#[cfg(not(feature = "ssr"))]
pub type OptionLocalGuard<T> = guards::ReadGuard<Option<T>, guards::Plain<Option<T>>>;
impl<T> ReadUntracked for OptionLocalRwSignal<T>
where
T: 'static,
{
type Value = OptionLocalGuard<T>;
#[inline(always)]
fn try_read_untracked(&self) -> Option<Self::Value> {
#[cfg(feature = "ssr")]
{
Some(NoneGuard::default())
}
#[cfg(not(feature = "ssr"))]
{
self.inner.try_read_untracked()
}
}
}
impl<T> Track for OptionLocalRwSignal<T>
where
T: 'static,
{
#[inline(always)]
fn track(&self) {
#[cfg(feature = "ssr")]
{
}
#[cfg(not(feature = "ssr"))]
{
self.inner.track();
}
}
}
impl<T> Notify for OptionLocalRwSignal<T>
where
T: 'static,
{
#[inline(always)]
fn notify(&self) {
#[cfg(feature = "ssr")]
{
leptos::logging::warn!(
"Attempted to notify an OptionLocalRwSignal on the server; this has no effect."
);
}
#[cfg(not(feature = "ssr"))]
{
self.inner.notify();
}
}
}
impl<T> Write for OptionLocalRwSignal<T>
where
T: 'static,
{
type Value = Option<T>;
#[inline(always)]
fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
#[cfg(feature = "ssr")]
{
leptos::logging::warn!(
"Attempted to write to an OptionLocalRwSignal on the server; this has no effect."
);
None::<NoneGuard<T>>
}
#[cfg(not(feature = "ssr"))]
{
self.inner.try_write()
}
}
#[inline(always)]
fn try_write_untracked(&self) -> Option<impl DerefMut<Target = Self::Value>> {
#[cfg(feature = "ssr")]
{
leptos::logging::warn!(
"Attempted to write to an OptionLocalRwSignal on the server; this has no effect."
);
None::<NoneGuard<T>>
}
#[cfg(not(feature = "ssr"))]
{
self.inner.try_write_untracked()
}
}
}
impl<T> IsDisposed for OptionLocalRwSignal<T>
where
T: 'static,
{
#[inline(always)]
fn is_disposed(&self) -> bool {
#[cfg(feature = "ssr")]
{
false
}
#[cfg(not(feature = "ssr"))]
{
self.inner.is_disposed()
}
}
}
pub struct NoneGuard<T> {
_data: std::marker::PhantomData<T>,
}
impl<T> Default for NoneGuard<T> {
fn default() -> Self {
Self {
_data: std::marker::PhantomData,
}
}
}
impl<T> Deref for NoneGuard<T> {
type Target = Option<T>;
fn deref(&self) -> &Self::Target {
&None
}
}
impl<T> DerefMut for NoneGuard<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
panic!("Attempted to mutably dereference a NoneGuard");
}
}
impl<T> UntrackableGuard for NoneGuard<T> {
fn untrack(&mut self) {
panic!("Attempted to untrack a NoneGuard");
}
}
pub struct OptionLocalSignal<T> {
#[cfg(debug_assertions)]
defined_at: &'static std::panic::Location<'static>,
inner: OptionLocalRwSignal<T>,
}
impl<T> Clone for OptionLocalSignal<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for OptionLocalSignal<T> {}
impl<T> DefinedAt for OptionLocalSignal<T> {
#[inline(always)]
fn defined_at(&self) -> Option<&'static std::panic::Location<'static>> {
#[cfg(debug_assertions)]
{
Some(self.defined_at)
}
#[cfg(not(debug_assertions))]
{
None
}
}
}
impl<T> ReadUntracked for OptionLocalSignal<T>
where
T: 'static,
{
type Value = OptionLocalGuard<T>;
#[inline(always)]
fn try_read_untracked(&self) -> Option<Self::Value> {
self.inner.try_read_untracked()
}
}
impl<T> Track for OptionLocalSignal<T>
where
T: 'static,
{
#[inline(always)]
fn track(&self) {
self.inner.track();
}
}