wasm4fun_storage/storage.rs
1// Copyright Claudio Mattera 2022.
2//
3// Distributed under the MIT License or the Apache 2.0 License at your option.
4// See the accompanying files License-MIT.txt and License-Apache-2.0.txt, or
5// online at
6// https://opensource.org/licenses/MIT
7// https://opensource.org/licenses/Apache-2.0
8
9#[cfg(feature = "storage")]
10use serde::{de::DeserializeOwned, Serialize};
11
12#[cfg(feature = "storage")]
13use postcard::from_bytes as from_postcard_slice;
14
15#[cfg(feature = "storage")]
16use postcard::to_slice as to_postcard_slice;
17
18#[cfg(feature = "storage")]
19use wasm4fun_core::{diskr, diskw};
20
21use wasm4fun_log::debug;
22
23/// Store a payload to disk
24///
25/// The payload must implement [`Serialize`], and it is serialized using
26/// [serde] and [postcard] crates.
27///
28/// # Example
29///
30/// ```no_run
31/// use serde::Serialize;
32///
33/// use wasm4fun_storage::store;
34///
35/// #[derive(Default, Serialize)]
36/// struct SomeStruct {
37/// field: u8,
38/// other_field: f32,
39/// }
40///
41/// let payload: SomeStruct = Default::default();
42///
43/// const BUFFER_LENGTH: usize = 8;
44///
45/// store::<SomeStruct, BUFFER_LENGTH>(payload);
46/// ```
47///
48/// # Panics
49///
50/// This function panics if the serialized data is larger than
51/// `BUFFER_LENGTH` bytes.
52///
53/// # Note
54///
55/// Regardless of the value of `BUFFER_LENGTH`, WASM-4 only supports storage
56/// for up to 1024 bytes.
57#[cfg(feature = "storage")]
58pub fn store<T, const BUFFER_LENGTH: usize>(payload: T)
59where
60 T: Serialize,
61{
62 let mut buffer: [u8; BUFFER_LENGTH] = [0; BUFFER_LENGTH];
63
64 let slice: &[u8] = match to_postcard_slice(&payload, &mut buffer) {
65 Ok(slice) => slice,
66 Err(message) => {
67 debug!("Could not serialize payload");
68 debug!("Reason: {}", message);
69 panic!("Could not serialize payload");
70 }
71 };
72
73 debug!("Payload serialized to {} bytes", slice.len());
74
75 let bytes_written = unsafe { diskw(slice.as_ptr(), slice.len() as u32) };
76 if bytes_written != slice.len() as u32 {
77 debug!("Could not write payload");
78 debug!("Written {} bytes instead of {}", bytes_written, slice.len());
79 }
80}
81
82/// Load a payload from disk
83///
84/// The payload must implement [`DeserializeOwned`], and it is serialized using
85/// [serde] and [postcard] crates.
86/// [`DeserializeOwned`] is functionally equivalent to
87/// [`Deserialize`][serde::Deserialize], with the additional constraint that
88/// `T` can be deserialized without borrowing any data from the deserializer.
89///
90/// # Example
91///
92/// ```no_run
93/// use serde::Deserialize;
94///
95/// use wasm4fun_storage::load;
96///
97/// #[derive(Default, Deserialize)]
98/// struct SomeStruct {
99/// field: u8,
100/// other_field: f32,
101/// }
102///
103/// const BUFFER_LENGTH: usize = 8;
104///
105/// let payload: SomeStruct = load::<SomeStruct, BUFFER_LENGTH>();
106/// ```
107///
108/// # Panics
109///
110/// This function panics if the deserialized data is larger than
111/// `BUFFER_LENGTH` bytes.
112///
113/// # Note
114///
115/// Regardless of the value of `BUFFER_LENGTH`, WASM-4 only supports storage
116/// for up to 1024 bytes.
117#[cfg(feature = "storage")]
118pub fn load<T, const BUFFER_LENGTH: usize>() -> T
119where
120 T: Default + DeserializeOwned,
121{
122 let mut buffer: [u8; BUFFER_LENGTH] = [0; BUFFER_LENGTH];
123
124 let bytes_read = unsafe { diskr(buffer.as_mut_ptr(), buffer.len() as u32) };
125
126 let data: &[u8] = &buffer[0..bytes_read as usize];
127 let payload: T = match from_postcard_slice(data) {
128 Ok(payload) => payload,
129 Err(message) => {
130 debug!("Could not deserialize payload");
131 debug!("Reason: {}", message);
132 Default::default()
133 }
134 };
135 debug!("Loaded payload");
136 payload
137}
138
139#[cfg(not(feature = "storage"))]
140pub fn store<T, const BUFFER_LENGTH: usize>(_payload: T) {
141 debug!("Storage not enabled");
142}
143
144#[cfg(not(feature = "storage"))]
145pub fn load<T, const BUFFER_LENGTH: usize>() -> T
146where
147 T: Default,
148{
149 debug!("Storage not enabled");
150 Default::default()
151}