eidetica/sync/
peer_types.rs1use std::fmt;
7
8use serde::{Deserialize, Serialize};
9
10use crate::auth::crypto::PublicKey;
11
12#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
17#[serde(transparent)]
18pub struct PeerId(PublicKey);
19
20impl PeerId {
21 pub fn new(pk: PublicKey) -> Self {
23 Self(pk)
24 }
25
26 pub fn public_key(&self) -> &PublicKey {
28 &self.0
29 }
30}
31
32impl fmt::Display for PeerId {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 write!(f, "{}", self.0)
35 }
36}
37
38impl From<PublicKey> for PeerId {
39 fn from(pk: PublicKey) -> Self {
40 Self(pk)
41 }
42}
43
44impl From<&PublicKey> for PeerId {
45 fn from(pk: &PublicKey) -> Self {
46 Self(pk.clone())
47 }
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
52pub enum ConnectionState {
53 Disconnected,
55 Connecting,
57 Connected,
59 Failed(String),
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
65pub struct Address {
66 pub transport_type: String,
68 pub address: String,
70}
71
72impl Address {
73 pub fn new(transport_type: impl Into<String>, address: impl Into<String>) -> Self {
75 Self {
76 transport_type: transport_type.into(),
77 address: address.into(),
78 }
79 }
80
81 pub fn http(address: impl Into<String>) -> Self {
85 Self::new("http", address)
86 }
87
88 pub fn iroh(node_id: impl Into<String>) -> Self {
90 Self::new("iroh", node_id)
91 }
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
96pub struct PeerInfo {
97 pub id: PeerId,
99 pub display_name: Option<String>,
101 pub first_seen: String,
103 pub last_seen: String,
105 pub status: PeerStatus,
107 pub addresses: Vec<Address>,
109 pub connection_state: ConnectionState,
111 pub last_successful_sync: Option<String>,
113 pub connection_attempts: u32,
115 pub last_error: Option<String>,
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
121pub enum PeerStatus {
122 #[default]
124 Active,
125 Inactive,
127 Blocked,
129}
130
131impl PeerInfo {
132 pub fn new_at(id: impl Into<PeerId>, display_name: Option<&str>, timestamp: String) -> Self {
136 Self {
137 id: id.into(),
138 display_name: display_name.map(|s| s.to_string()),
139 first_seen: timestamp.clone(),
140 last_seen: timestamp,
141 status: PeerStatus::Active,
142 addresses: Vec::new(),
143 connection_state: ConnectionState::Disconnected,
144 last_successful_sync: None,
145 connection_attempts: 0,
146 last_error: None,
147 }
148 }
149
150 pub fn touch_at(&mut self, timestamp: String) {
154 self.last_seen = timestamp;
155 }
156
157 pub fn add_address(&mut self, address: Address) {
159 if !self.addresses.contains(&address) {
160 self.addresses.push(address);
161 }
162 }
163
164 pub fn remove_address(&mut self, address: &Address) -> bool {
166 let initial_len = self.addresses.len();
167 self.addresses.retain(|a| a != address);
168 self.addresses.len() != initial_len
169 }
170
171 pub fn get_addresses(&self, transport_type: impl AsRef<str>) -> Vec<&Address> {
173 self.addresses
174 .iter()
175 .filter(|a| a.transport_type == transport_type.as_ref())
176 .collect()
177 }
178
179 pub fn get_all_addresses(&self) -> &Vec<Address> {
181 &self.addresses
182 }
183
184 pub fn has_transport(&self, transport_type: impl AsRef<str>) -> bool {
186 self.addresses
187 .iter()
188 .any(|a| a.transport_type == transport_type.as_ref())
189 }
190}