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 connection_attempts: u32,
113 pub last_error: Option<String>,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
119pub enum PeerStatus {
120 #[default]
122 Active,
123 Inactive,
125 Blocked,
127}
128
129impl PeerInfo {
130 pub fn new_at(id: impl Into<PeerId>, display_name: Option<&str>, timestamp: String) -> Self {
134 Self {
135 id: id.into(),
136 display_name: display_name.map(|s| s.to_string()),
137 first_seen: timestamp.clone(),
138 last_seen: timestamp,
139 status: PeerStatus::Active,
140 addresses: Vec::new(),
141 connection_state: ConnectionState::Disconnected,
142 connection_attempts: 0,
143 last_error: None,
144 }
145 }
146
147 pub fn touch_at(&mut self, timestamp: String) {
151 self.last_seen = timestamp;
152 }
153
154 pub fn add_address(&mut self, address: Address) {
156 if !self.addresses.contains(&address) {
157 self.addresses.push(address);
158 }
159 }
160
161 pub fn remove_address(&mut self, address: &Address) -> bool {
163 let initial_len = self.addresses.len();
164 self.addresses.retain(|a| a != address);
165 self.addresses.len() != initial_len
166 }
167
168 pub fn get_addresses(&self, transport_type: impl AsRef<str>) -> Vec<&Address> {
170 self.addresses
171 .iter()
172 .filter(|a| a.transport_type == transport_type.as_ref())
173 .collect()
174 }
175
176 pub fn get_all_addresses(&self) -> &Vec<Address> {
178 &self.addresses
179 }
180
181 pub fn has_transport(&self, transport_type: impl AsRef<str>) -> bool {
183 self.addresses
184 .iter()
185 .any(|a| a.transport_type == transport_type.as_ref())
186 }
187}