leptos_reactive/
serialization.rs

1use cfg_if::cfg_if;
2use std::rc::Rc;
3use thiserror::Error;
4
5/// Describes errors that can occur while serializing and deserializing data,
6/// typically during the process of streaming [`Resource`](crate::Resource)s from
7/// the server to the client.
8#[derive(Debug, Clone, Error)]
9pub enum SerializationError {
10    /// Errors that occur during serialization.
11    #[error("error serializing Resource: {0}")]
12    Serialize(Rc<dyn std::error::Error>),
13    /// Errors that occur during deserialization.
14    #[error("error deserializing Resource: {0}")]
15    Deserialize(Rc<dyn std::error::Error>),
16}
17
18/// Describes an object that can be serialized to or from a supported format
19/// Currently those are JSON and Cbor
20///
21/// This is primarily used for serializing and deserializing [`Resource`](crate::Resource)s
22/// so they can begin on the server and be resolved on the client, but can be used
23/// for any data that needs to be serialized/deserialized.
24///
25/// This trait is intended to abstract over various serialization crates,
26/// as selected between by the crate features `serde` (default), `serde-lite`,
27/// and `miniserde`.
28pub trait Serializable
29where
30    Self: Sized,
31{
32    /// Serializes the object to a string.
33    fn ser(&self) -> Result<String, SerializationError>;
34
35    /// Deserializes the object from some bytes.
36    fn de(bytes: &str) -> Result<Self, SerializationError>;
37}
38
39cfg_if! {
40    if #[cfg(feature = "rkyv")] {
41        use rkyv::{Archive, CheckBytes, Deserialize, Serialize, ser::serializers::AllocSerializer, de::deserializers::SharedDeserializeMap, validation::validators::DefaultValidator};
42        use base64::Engine as _;
43        use base64::engine::general_purpose::STANDARD_NO_PAD;
44
45        impl<T> Serializable for T
46        where
47        T: Serialize<AllocSerializer<1024>>,
48        T: Archive,
49        T::Archived: for<'b> CheckBytes<DefaultValidator<'b>> + Deserialize<T, SharedDeserializeMap>,
50        {
51            fn ser(&self) -> Result<String, SerializationError> {
52                let bytes = rkyv::to_bytes::<T, 1024>(self).map_err(|e| SerializationError::Serialize(Rc::new(e)))?;
53                Ok(STANDARD_NO_PAD.encode(bytes))
54            }
55
56            fn de(serialized: &str) -> Result<Self, SerializationError> {
57                let bytes = STANDARD_NO_PAD.decode(serialized.as_bytes()).map_err(|e| SerializationError::Deserialize(Rc::new(e)))?;
58                rkyv::from_bytes::<T>(&bytes).map_err(|e| SerializationError::Deserialize(Rc::new(e)))
59            }
60        }
61    }
62    // prefer miniserde if it's chosen
63    else if #[cfg(feature = "miniserde")] {
64        use miniserde::{json, Deserialize, Serialize};
65
66        impl<T> Serializable for T
67        where
68            T: Serialize + Deserialize,
69        {
70            fn ser(&self) -> Result<String, SerializationError> {
71                Ok(json::to_string(&self))
72            }
73
74            fn de(json: &str) -> Result<Self, SerializationError> {
75                json::from_str(json).map_err(|e| SerializationError::Deserialize(Rc::new(e)))
76            }
77        }
78
79    }
80    // use serde-lite if enabled
81    else if #[cfg(feature = "serde-lite")] {
82        use serde_lite::{Deserialize, Serialize};
83
84        impl<T> Serializable for T
85        where
86            T: Serialize + Deserialize,
87        {
88            fn ser(&self) -> Result<String, SerializationError> {
89                let intermediate = self
90                    .serialize()
91                    .map_err(|e| SerializationError::Serialize(Rc::new(e)))?;
92                serde_json::to_string(&intermediate).map_err(|e| SerializationError::Serialize(Rc::new(e)))
93            }
94
95            fn de(json: &str) -> Result<Self, SerializationError> {
96                let intermediate =
97                    serde_json::from_str(json).map_err(|e| SerializationError::Deserialize(Rc::new(e)))?;
98                Self::deserialize(&intermediate).map_err(|e| SerializationError::Deserialize(Rc::new(e)))
99            }
100        }
101
102    }
103    // otherwise, or if serde is chosen, default to serde
104    else {
105        use serde::{de::DeserializeOwned, Serialize};
106
107        impl<T> Serializable for T
108        where
109            T: DeserializeOwned + Serialize,
110        {
111            fn ser(&self) -> Result<String, SerializationError> {
112                serde_json::to_string(&self).map_err(|e| SerializationError::Serialize(Rc::new(e)))
113            }
114
115            fn de(json: &str) -> Result<Self, SerializationError> {
116                serde_json::from_str(json).map_err(|e| SerializationError::Deserialize(Rc::new(e)))
117            }
118
119        }
120    }
121}