61 lines
1.8 KiB
Rust
61 lines
1.8 KiB
Rust
use serde::ser::{Serialize, SerializeMap, Serializer};
|
|
use serde_json::Value;
|
|
|
|
use crate::error::AppError;
|
|
|
|
use super::interface::SessionState;
|
|
|
|
const SESSION_STATE_FORMAT_VERSION: u8 = 1;
|
|
|
|
struct StoredSessionStateRef<'a> {
|
|
state: &'a SessionState,
|
|
}
|
|
|
|
impl Serialize for StoredSessionStateRef<'_> {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
let mut map = serializer.serialize_map(Some(2))?;
|
|
map.serialize_entry("v", &SESSION_STATE_FORMAT_VERSION)?;
|
|
map.serialize_entry("state", self.state)?;
|
|
map.end()
|
|
}
|
|
}
|
|
|
|
pub fn serialize_session_state(session_state: &SessionState) -> Result<String, AppError> {
|
|
let stored = StoredSessionStateRef {
|
|
state: session_state,
|
|
};
|
|
serde_json::to_string(&stored).map_err(AppError::Json)
|
|
}
|
|
|
|
pub fn deserialize_session_state(value: &str) -> Result<SessionState, AppError> {
|
|
let value: Value = serde_json::from_str(value)?;
|
|
let Value::Object(mut obj) = value else {
|
|
return Err(AppError::Config("invalid session state format".into()));
|
|
};
|
|
|
|
if let Some(Value::Object(_)) = obj.get("state")
|
|
&& let Some(Value::Number(v)) = obj.get("v")
|
|
{
|
|
let version = v
|
|
.as_u64()
|
|
.and_then(|n| u8::try_from(n).ok())
|
|
.ok_or_else(|| AppError::Config("invalid session state format version".into()))?;
|
|
|
|
if version != SESSION_STATE_FORMAT_VERSION {
|
|
return Err(AppError::Config(format!(
|
|
"unsupported session state format version: {version}"
|
|
)));
|
|
}
|
|
|
|
let Some(Value::Object(state)) = obj.remove("state") else {
|
|
return Err(AppError::Config("missing session state".into()));
|
|
};
|
|
return Ok(state);
|
|
}
|
|
|
|
Ok(obj)
|
|
}
|