use std::collections::BTreeMap;
use js_int::UInt;
use ruma_common::MilliSecondsSinceUnixEpoch;
use ruma_identifiers::{EventId, RoomId, ServerName, ServerSigningKeyId, UserId};
use serde::{
de::{Error as _, IgnoredAny},
Deserialize, Deserializer, Serialize,
};
use serde_json::{from_str as from_json_str, value::RawValue as RawJsonValue};
use crate::EventType;
#[derive(Clone, Debug, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(untagged)]
pub enum Pdu {
RoomV1Pdu(RoomV1Pdu),
RoomV3Pdu(RoomV3Pdu),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(clippy::exhaustive_structs)]
pub struct RoomV1Pdu {
pub event_id: Box<EventId>,
pub room_id: Box<RoomId>,
pub sender: Box<UserId>,
#[cfg(not(feature = "unstable-pre-spec"))]
pub origin: String,
pub origin_server_ts: MilliSecondsSinceUnixEpoch,
#[serde(rename = "type")]
pub kind: EventType,
pub content: Box<RawJsonValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub state_key: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub prev_events: Vec<(Box<EventId>, EventHash)>,
pub depth: UInt,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub auth_events: Vec<(Box<EventId>, EventHash)>,
#[serde(skip_serializing_if = "Option::is_none")]
pub redacts: Option<Box<EventId>>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub unsigned: BTreeMap<String, Box<RawJsonValue>>,
pub hashes: EventHash,
pub signatures: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, String>>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(clippy::exhaustive_structs)]
pub struct RoomV3Pdu {
pub room_id: Box<RoomId>,
pub sender: Box<UserId>,
#[cfg(not(feature = "unstable-pre-spec"))]
pub origin: String,
pub origin_server_ts: MilliSecondsSinceUnixEpoch,
#[serde(rename = "type")]
pub kind: EventType,
pub content: Box<RawJsonValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub state_key: Option<String>,
pub prev_events: Vec<Box<EventId>>,
pub depth: UInt,
pub auth_events: Vec<Box<EventId>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub redacts: Option<Box<EventId>>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub unsigned: BTreeMap<String, Box<RawJsonValue>>,
pub hashes: EventHash,
pub signatures: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, String>>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct EventHash {
pub sha256: String,
}
impl EventHash {
pub fn new(sha256: String) -> Self {
Self { sha256 }
}
}
impl<'de> Deserialize<'de> for Pdu {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct GetEventId {
event_id: Option<IgnoredAny>,
}
let json = Box::<RawJsonValue>::deserialize(deserializer)?;
if from_json_str::<GetEventId>(json.get()).map_err(D::Error::custom)?.event_id.is_some() {
from_json_str(json.get()).map(Self::RoomV1Pdu).map_err(D::Error::custom)
} else {
from_json_str(json.get()).map(Self::RoomV3Pdu).map_err(D::Error::custom)
}
}
}