tawasuyu

tawasuyu/hifas

Motor en Rust para decidir, con demostración y no a ojo, cuándo un conjunto de réplicas local-first puede operar sin coordinación y cuándo no — y, cuando la respuesta es "sí, dentro de límites", proveer el mecanismo que lo garantiza.

Rust 24Markdown 14TOML 1358 Definiciones

⎇ 74acdb9dbca5fc2399bce6f3d65a3bf865c01c22 src/nerve.rs Rust · 67 líneas · 2.2 KB Historia Quién tocó qué crudo

M4: adaptador soberano con API congelada y contrato honesto 703ae7023 · Sergio ·

1//! `nerve` — el grafo de qué réplicas comparten datos con cuáles (§6.2).
2//!
3//! Vértices = réplicas, aristas = pares que comparten un dato.
4
5use petgraph::graph::{NodeIndex, UnGraph};
6
7/// Identificador de una réplica (vértice del nervio).
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub struct ReplicaId(pub usize);
10
11/// Qué coordenadas del estado se comparten en una arista.
12///
13/// M0: forma únicamente; el detalle de la proyección se fija en `sheaf` (T1/T2).
14#[derive(Debug, Clone, Default, PartialEq)]
15pub struct SharedLink {
16    /// Índices de las coordenadas compartidas en esta arista.
17    pub shared_coords: Vec<usize>,
18}
19
20/// El nervio: grafo no dirigido de réplicas y sus enlaces compartidos.
21#[derive(Debug, Default, Clone)]
22pub struct Nerve {
23    /// Grafo no dirigido: vértices = réplicas, aristas = pares que comparten datos.
24    pub graph: UnGraph<ReplicaId, SharedLink>,
25}
26
27impl Nerve {
28    /// Nervio vacío.
29    pub fn new() -> Self {
30        Self {
31            graph: UnGraph::new_undirected(),
32        }
33    }
34
35    /// Construye el nervio de `num_vertices` réplicas y una lista de aristas.
36    /// Los índices de nodo coinciden con los `ReplicaId` (0..num_vertices).
37    pub fn from_edges(num_vertices: usize, edges: &[(usize, usize)]) -> Self {
38        let mut graph = UnGraph::new_undirected();
39        let nodes: Vec<NodeIndex> = (0..num_vertices).map(|i| graph.add_node(ReplicaId(i))).collect();
40        for &(a, b) in edges {
41            graph.add_edge(nodes[a], nodes[b], SharedLink::default());
42        }
43        Self { graph }
44    }
45
46    /// Número de réplicas (vértices).
47    pub fn num_replicas(&self) -> usize {
48        self.graph.node_count()
49    }
50
51    /// Las aristas como pares `(u, v)` de índices de réplica.
52    pub fn edges(&self) -> Vec<(usize, usize)> {
53        self.graph
54            .edge_indices()
55            .filter_map(|e| self.graph.edge_endpoints(e))
56            .map(|(a, b)| (a.index(), b.index()))
57            .collect()
58    }
59
60    /// Vecinas de la réplica `v` en el nervio.
61    pub fn neighbors(&self, v: usize) -> Vec<usize> {
62        self.graph
63            .neighbors(NodeIndex::new(v))
64            .map(|n| n.index())
65            .collect()
66    }
67}