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(&self, serializer: S) -> Result 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 { let stored = StoredSessionStateRef { state: session_state, }; serde_json::to_string(&stored).map_err(AppError::Json) } pub fn deserialize_session_state(value: &str) -> Result { 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) }