This commit is contained in:
Erik Johnston
2026-03-05 13:33:11 +00:00
parent e5984eec33
commit f4b96c0b3f
3 changed files with 123 additions and 31 deletions
+57 -19
View File
@@ -5,6 +5,12 @@
use std::{fmt::Display, str::FromStr};
use anyhow::Error;
use once_cell::sync::OnceCell;
use pyo3::{
types::PyAnyMethods, Borrowed, Bound, FromPyObject, Py, PyAny, PyErr, PyResult, Python,
};
use crate::events::Event;
/// Maximum size of a PDU
pub const MAX_PDU_SIZE_BYTES: usize = 65_535;
@@ -48,27 +54,33 @@ pub enum RoomVersion {
Custom(String),
}
impl RoomVersion {
pub fn as_str(&self) -> &str {
match self {
RoomVersion::V1 => "1",
RoomVersion::V2 => "2",
RoomVersion::V3 => "3",
RoomVersion::V4 => "4",
RoomVersion::V5 => "5",
RoomVersion::V6 => "6",
RoomVersion::V7 => "7",
RoomVersion::V8 => "8",
RoomVersion::V9 => "9",
RoomVersion::V10 => "10",
RoomVersion::V11 => "11",
RoomVersion::V12 => "12",
RoomVersion::OrgMatrixMsc1767_10 => "org.matrix.msc1767.10",
RoomVersion::OrgMatrixMsc3757_10 => "org.matrix.msc3757.10",
RoomVersion::OrgMatrixMsc3757_11 => "org.matrix.msc3757.11",
RoomVersion::OrgMatrixHydra11 => "org.matrix.hydra.11",
RoomVersion::Custom(s) => s.as_str(),
}
}
}
impl Display for RoomVersion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RoomVersion::V1 => write!(f, "1"),
RoomVersion::V2 => write!(f, "2"),
RoomVersion::V3 => write!(f, "3"),
RoomVersion::V4 => write!(f, "4"),
RoomVersion::V5 => write!(f, "5"),
RoomVersion::V6 => write!(f, "6"),
RoomVersion::V7 => write!(f, "7"),
RoomVersion::V8 => write!(f, "8"),
RoomVersion::V9 => write!(f, "9"),
RoomVersion::V10 => write!(f, "10"),
RoomVersion::V11 => write!(f, "11"),
RoomVersion::V12 => write!(f, "12"),
RoomVersion::OrgMatrixMsc1767_10 => write!(f, "org.matrix.msc1767.10"),
RoomVersion::OrgMatrixMsc3757_10 => write!(f, "org.matrix.msc3757.10"),
RoomVersion::OrgMatrixMsc3757_11 => write!(f, "org.matrix.msc3757.11"),
RoomVersion::OrgMatrixHydra11 => write!(f, "org.matrix.hydra.11"),
RoomVersion::Custom(s) => write!(f, "{s}"),
}
write!(f, "{}", self.as_str())
}
}
@@ -221,3 +233,29 @@ pub mod redaction_field {
/// Redacts event field: redacts
pub const REDACTS: &str = "redacts";
}
/// A reference to the `synapse.api.room_version.KNOWN_ROOM_VERSIONS`.
static KNOWN_ROOM_VERSIONS: OnceCell<Py<PyAny>> = OnceCell::new();
/// Access to the `synapse.api.room_version.KNOWN_ROOM_VERSIONS`.
fn known_room_version_py(py: Python<'_>) -> PyResult<&Bound<'_, PyAny>> {
Ok(KNOWN_ROOM_VERSIONS
.get_or_try_init(|| -> PyResult<Py<PyAny>> {
let module = py.import("synapse.api.room_version")?;
let room_versions_class = module.getattr("KNOWN_ROOM_VERSIONS")?;
Ok(room_versions_class.unbind().into())
})?
.bind(py))
}
pub fn get_room_version_py<'a>(
room_version: &RoomVersion,
py: Python<'a>,
) -> PyResult<Bound<'a, PyAny>> {
let room_version_module = known_room_version_py(py)?;
let room_version_str = room_version.as_str();
let room_version_py = room_version_module.get_item(room_version_str)?;
Ok(room_version_py)
}
+1 -1
View File
@@ -275,7 +275,7 @@ pub struct EventInternalMetadata {
#[pymethods]
impl EventInternalMetadata {
#[new]
fn new(dict: &Bound<'_, PyDict>) -> PyResult<Self> {
pub fn new(dict: &Bound<'_, PyDict>) -> PyResult<Self> {
let mut data = Vec::with_capacity(dict.len());
for (key, value) in dict.iter() {
+65 -11
View File
@@ -22,20 +22,26 @@
use std::{
collections::HashMap,
str::FromStr,
sync::{Arc, RwLock},
};
use pyo3::{
exceptions::{PyException, PyKeyError},
exceptions::{PyException, PyKeyError, PyValueError},
pyclass, pymethods,
types::{PyAnyMethods, PyIterator, PyMapping, PyMappingMethods, PyModule, PyModuleMethods},
wrap_pyfunction, Bound, IntoPyObject, PyAny, PyErr, PyResult, Python,
types::{
PyAnyMethods, PyDict, PyIterator, PyMapping, PyMappingMethods, PyModule, PyModuleMethods,
},
wrap_pyfunction, Bound, IntoPyObject, PyAny, PyResult, Python,
};
use pythonize::{depythonize, pythonize};
use serde::{Deserialize, Serialize};
use crate::{
events::{constants::RoomVersion, utils::calculate_event_id},
events::{
constants::{get_room_version_py, RoomVersion},
utils::calculate_event_id,
},
identifier::EventID,
};
@@ -382,30 +388,62 @@ struct EventCommonFields {
struct Event {
inner: EventFormatEnum,
event_id: EventID,
internal_metadata: internal_metadata::EventInternalMetadata,
room_version: RoomVersion,
rejected_reason: Option<Box<str>>,
}
#[pymethods]
impl Event {
#[new]
fn new<'a, 'py>(format: u8, event_dict: &'a Bound<'py, PyAny>) -> PyResult<Self> {
if format != 3 {
return Err(PyKeyError::new_err(format!(
"Unsupported event format version: {}",
format
)));
fn new<'a, 'py>(
event_dict: &'a Bound<'py, PyAny>,
room_version: &'a Bound<'py, PyAny>,
internal_metadata_dict: &'a Bound<'py, PyDict>,
rejected_reason: Option<String>,
) -> PyResult<Self> {
let room_version = {
let r = room_version.getattr("identifier")?;
let room_version_str = r.extract::<&str>()?;
RoomVersion::from_str(room_version_str)
.map_err(|e| PyValueError::new_err(format!("Unsupported room version: {}", e)))?
};
let rejected_reason = rejected_reason.map(String::into_boxed_str);
// Check we're the right room version
match room_version {
RoomVersion::V4
| RoomVersion::V5
| RoomVersion::V6
| RoomVersion::V7
| RoomVersion::V8
| RoomVersion::V9
| RoomVersion::V10
| RoomVersion::V11
| RoomVersion::OrgMatrixMsc1767_10
| RoomVersion::OrgMatrixMsc3757_10
| RoomVersion::OrgMatrixMsc3757_11 => {}
_ => return Err(PyValueError::new_err("Unsupported room version")),
}
let event_format_v3: EventFormatV3Container = depythonize(event_dict)?;
let internal_metadata =
internal_metadata::EventInternalMetadata::new(internal_metadata_dict)?;
let event_value = serde_json::to_value(&event_format_v3)
.map_err(|err| PyException::new_err(format!("Failed to serialize event: {}", err)))?;
let event_id = calculate_event_id(&event_value, &RoomVersion::V10).map_err(|err| {
let event_id = calculate_event_id(&event_value, &room_version).map_err(|err| {
PyException::new_err(format!("Failed to calculate event_id: {}", err))
})?;
Ok(Self {
inner: EventFormatEnum::V3(event_format_v3),
event_id,
room_version,
rejected_reason,
internal_metadata,
})
}
@@ -505,6 +543,22 @@ impl Event {
// ...
}
}
#[getter]
fn internal_metadata(&self) -> PyResult<internal_metadata::EventInternalMetadata> {
// TODO: Interior mutability
Ok(self.internal_metadata.clone())
}
#[getter]
fn rejected_reason(&self) -> Option<&str> {
self.rejected_reason.as_deref()
}
#[getter]
fn room_version<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
get_room_version_py(&self.room_version, py)
}
}
enum EventFormatEnum {