serialization/
serialize.rs

1//! Provides all serialisation related methods and their respective formats.
2use crate::Serialize;
3use crate::error::SerializationError;
4use crate::format::SerializationFormat;
5use anyhow::Error;
6use std::io::Write;
7
8/// Shorthand for [`Result<T, SerializationError>`].
9type Result<T> = std::result::Result<T, SerializationError>;
10
11/// A simple wrapper function that calls [`serialize`] and writes the result to `writer`.
12///
13/// This method also calls `writer.flush()`
14#[allow(clippy::missing_errors_doc)]
15pub fn serialize_to<T>(
16    subject: &T,
17    format: &SerializationFormat,
18    mut writer: impl Write,
19) -> Result<()>
20where
21    T: ?Sized + Serialize,
22{
23    let binary = serialize(subject, format)?;
24    writer
25        .write_all(&binary)
26        .map_err(SerializationError::from)?;
27
28    writer.flush().map_err(SerializationError::from)?;
29
30    Ok(())
31}
32
33/// Attempts to serialise `subject` into the specified format and returns the result as a `Vec<u8>`.
34///
35/// # Arguments
36///
37/// * `subject`: The data structure to serialise.
38/// * `format`: A [`SerializationFormat`] that indicates which serialisation format to use.
39///
40/// returns: `Result<Vec<u8>>`
41///
42/// # Errors
43/// This method returns a [`SerializationError`] if any of the steps for serialisation fails.
44/// See [`SerializationError`] for specific details on each error scenario.
45///
46/// # Examples
47///
48/// ```
49/// # use serde::*;
50/// # use serialization::*;
51///
52/// # #[derive(Serialize)]
53/// # struct Foo {
54/// #     bar: String,
55/// # }
56///
57/// # fn main() -> anyhow::Result<()> {
58/// serialize(&Foo { bar: "baz".to_string() }, &SerializationFormat::JSON)?;
59/// #     Ok(())
60/// # }
61/// ```
62#[inline]
63pub fn serialize<T>(subject: &T, format: &SerializationFormat) -> Result<Vec<u8>>
64where
65    T: ?Sized + Serialize,
66{
67    match format {
68        SerializationFormat::JSON => serialize_json(subject),
69        SerializationFormat::MessagePack => serialize_messagepack(subject),
70        SerializationFormat::Toml => serialize_toml(subject),
71    }
72}
73
74/// Attempts to serialise `subject` into JSON and returns the string as a `Vec<u8>`.
75#[allow(clippy::missing_errors_doc)]
76pub fn serialize_json<T>(subject: &T) -> Result<Vec<u8>>
77where
78    T: ?Sized + Serialize,
79{
80    #[cfg(not(feature = "dev"))]
81    let json = serde_json::to_string(subject)
82        .map_err(|error| SerializationError::Serialize(Error::from(error)))?;
83    #[cfg(feature = "dev")]
84    let json = serde_json::to_string_pretty(subject)
85        .map_err(|error| SerializationError::Serialize(Error::from(error)))?;
86
87    Ok(json.into_bytes())
88}
89
90/// Attempts to serialise `subject` into `MessagePack` and returns as a `Vec<u8>`.
91#[allow(clippy::missing_errors_doc)]
92#[cfg_attr(not(feature = "msgpack"), allow(unused_variables))]
93pub fn serialize_messagepack<T>(subject: &T) -> Result<Vec<u8>>
94where
95    T: ?Sized + Serialize,
96{
97    #[cfg(not(feature = "msgpack"))]
98    return Err(SerializationError::FormatUnavailable("msgpack"));
99
100    #[cfg(feature = "msgpack")]
101    rmp_serde::to_vec(subject).map_err(|error| SerializationError::Serialize(Error::from(error)))
102}
103
104/// Attempts to serialise `subject` into `TOML` and returns the string as a `Vec<u8>`.
105#[allow(clippy::missing_errors_doc)]
106#[allow(clippy::missing_errors_doc, unused_variables)]
107pub fn serialize_toml<T>(subject: &T) -> Result<Vec<u8>>
108where
109    T: ?Sized + Serialize,
110{
111    #[cfg(not(feature = "toml"))]
112    return Err(SerializationError::FormatUnavailable("toml"));
113
114    #[cfg(all(feature = "toml", not(feature = "dev")))]
115    let toml = toml::to_string(subject)
116        .map_err(|error| SerializationError::Serialize(Error::from(error)))?;
117    #[cfg(all(feature = "toml", feature = "dev"))]
118    let toml = toml::to_string_pretty(subject)
119        .map_err(|error| SerializationError::Serialize(Error::from(error)))?;
120
121    #[cfg(feature = "toml")]
122    Ok(toml.into_bytes())
123}