m4a_matrix_core/
resolve.rs1use std::collections::HashMap;
2
3use ruma_common::{room_version_rules::{RoomVersionRules, StateResolutionVersion}, EventId, OwnedEventId};
4use ruma_state_res::{resolve, utils::event_id_set::EventIdSet, StateMap};
5
6use crate::Pdu;
7
8#[derive(Debug, thiserror::Error)]
9pub enum ResolveError {
10 #[error("room version has no state resolution v2")]
11 Version,
12 #[error("state resolution failed: {0}")]
13 Failed(String),
14}
15
16pub fn auth_chain(pdus: &HashMap<OwnedEventId, Pdu>, ids: impl IntoIterator<Item = OwnedEventId>) -> EventIdSet<OwnedEventId> {
18 auth_chain_with(&|id: &EventId| pdus.get(id).cloned(), ids)
19}
20
21pub fn auth_chain_with(fetch: &dyn Fn(&EventId) -> Option<Pdu>, ids: impl IntoIterator<Item = OwnedEventId>) -> EventIdSet<OwnedEventId> {
23 let mut seen = EventIdSet::new();
24 let mut todo: Vec<OwnedEventId> = ids.into_iter().collect();
25 while let Some(id) = todo.pop() {
26 if seen.contains(&id) {
27 continue;
28 }
29 if let Some(p) = fetch(&id) {
30 todo.extend(p.auth_events.iter().cloned());
31 }
32 seen.insert(id);
33 }
34 seen
35}
36
37pub fn resolve_state(rules: &RoomVersionRules, pdus: &HashMap<OwnedEventId, Pdu>, forks: &[StateMap<OwnedEventId>]) -> Result<StateMap<OwnedEventId>, ResolveError> {
39 resolve_state_with(rules, &|id: &EventId| pdus.get(id).cloned(), forks)
40}
41
42pub fn resolve_state_with(rules: &RoomVersionRules, fetch: &dyn Fn(&EventId) -> Option<Pdu>, forks: &[StateMap<OwnedEventId>]) -> Result<StateMap<OwnedEventId>, ResolveError> {
44 let StateResolutionVersion::V2(v2) = &rules.state_res else { return Err(ResolveError::Version) };
45 let chains: Vec<EventIdSet<OwnedEventId>> = forks.iter().map(|f| auth_chain_with(fetch, f.values().cloned())).collect();
46 resolve(
47 &rules.authorization,
48 v2,
49 forks.iter(),
50 chains,
51 |id: &EventId| fetch(id),
52 |_| None,
53 )
54 .map_err(|e| ResolveError::Failed(e.to_string()))
55}