Skip to main content

m4a_matrix_core/
resolve.rs

1use 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
16/// The full recursive set of auth events of `ids` (the ids themselves included).
17pub 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
21/// [`auth_chain`] over any event source.
22pub 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
37/// Resolves forked room states (state resolution v2) over a set of known events.
38pub 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
42/// [`resolve_state`] over any event source (a store lookup).
43pub 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}