dioxus_storage 0.0.1

A simple storage library for Dioxus
Documentation
use crate::storage::*;
use once_cell::sync::Lazy;
use postcard::to_allocvec;
use serde::{de::DeserializeOwned, Serialize};
use std::{
    marker::PhantomData,
    sync::{Arc, RwLock},
};

static STORAGE: Lazy<PersistentStorageContext<ServerStorage>> = Lazy::new(|| {
    #[cfg(target_arch = "wasm32")]
    let storage: Arc<RwLock<PersistentStorage>> = Arc::new(RwLock::new(serde_from_string(
        &web_sys::window()
            .expect("should have a window")
            .document()
            .expect("should have a document")
            .get_element_by_id("dioxus-storage")
            .expect("should have a dioxus-storage element")
            .get_attribute("data-serialized")
            .expect("should have a dioxus-storage element with data-serialized attribute"),
    )));
    #[cfg(not(target_arch = "wasm32"))]
    let storage = Arc::new(RwLock::new(PersistentStorage::default()));

    PersistentStorageContext {
        storage,
        ..Default::default()
    }
});

#[derive(Clone, Debug, Default)]
pub struct PersistentStorageContext<T> {
    pub storage: Arc<RwLock<PersistentStorage>>,
    pub phantom: PhantomData<T>,
}

impl<C> PersistentStorageContext<C> {
    pub fn get<T: DeserializeOwned>(&self) -> Option<T> {
        let mut storage = self.storage.write().ok()?;
        let idx = storage.idx;
        storage.idx += 1;
        let data = storage.data.get(idx)?;
        let data = postcard::from_bytes(data).unwrap();
        Some(data)
    }

    pub fn set<T: Serialize>(&self, value: &T) {
        let data = to_allocvec(&value).unwrap();
        let mut storage = self.storage.write().unwrap();
        storage.data.push(data);
    }
}

#[derive(Clone, Debug, Default)]
struct ServerStorage;

impl StorageBacking for ServerStorage {
    type Key = ();

    fn set<T: Serialize>(_: Self::Key, value: &T) {
        STORAGE.set(value);
    }

    #[allow(clippy::needless_return)]
    fn get<T: DeserializeOwned>(_: &Self::Key) -> Option<T> {
        #[cfg(target_arch = "wasm32")]
        return STORAGE.get();
        #[cfg(not(target_arch = "wasm32"))]
        return None;
    }
}

#[allow(clippy::needless_return)]
pub fn get_data() -> String {
    #[cfg(not(target_arch = "wasm32"))]
    {
        let serialized = serde_to_string(&*STORAGE.storage.read().unwrap());
        return format!(
            r#"<meta id="dioxus-storage" data-serialized="{serialized}" hidden="true"/>"#
        );
    }
    #[cfg(target_arch = "wasm32")]
    return "".to_string();
}

pub fn server_state<T: 'static + Serialize + DeserializeOwned>(init: impl FnOnce() -> T) -> T {
    storage_entry::<ServerStorage, T>((), init)
}

#[macro_export]
macro_rules! server_state {
    ($f: expr) => {{
        let r;
        #[cfg(not(target_arch = "wasm32"))]
        {
            r = server_state($f);
        }
        #[cfg(target_arch = "wasm32")]
        {
            r = server_state(|| panic!("server state not found"));
        }
        r
    }};
}