use super::{ClientInputEntry, ClientInputIndex, ClientInputStore, ClientShare, ClientShareIndex};
use std::time::SystemTime;
use stoffelnet::network_utils::ClientId;
impl ClientInputStore {
pub fn new() -> Self {
Self::default()
}
pub fn store_client_shares(&self, client_id: ClientId, shares: Vec<ClientShare>) {
let entry = ClientInputEntry {
client_id,
shares,
timestamp: SystemTime::now(),
};
let mut entries = self.entries.write();
entries.insert(client_id, entry);
drop(entries);
self.add_known_client(client_id);
}
pub fn replace_client_shares<I>(&self, inputs: I) -> usize
where
I: IntoIterator<Item = (ClientId, Vec<ClientShare>)>,
{
let mut total_shares = 0;
let timestamp = SystemTime::now();
let mut input_clients = Vec::new();
let mut entries = self.entries.write();
entries.clear();
for (client_id, shares) in inputs {
total_shares += shares.len();
input_clients.push(client_id);
entries.insert(
client_id,
ClientInputEntry {
client_id,
shares,
timestamp,
},
);
}
drop(entries);
self.add_known_clients(input_clients);
total_shares
}
pub fn snapshot_client_shares(&self) -> Vec<(ClientId, Vec<ClientShare>)> {
let entries = self.entries.read();
entries
.iter()
.map(|(&client_id, entry)| (client_id, entry.shares.clone()))
.collect()
}
pub fn snapshot_client_roster(&self) -> Vec<ClientId> {
self.client_ids()
}
pub fn store_client_input_bytes(&self, client_id: ClientId, share_bytes: Vec<Vec<u8>>) {
self.store_client_shares(
client_id,
share_bytes
.into_iter()
.map(ClientShare::untyped_bytes)
.collect(),
);
}
pub fn get_client_input_shares(&self, client_id: ClientId) -> Option<Vec<ClientShare>> {
let entries = self.entries.read();
entries.get(&client_id).map(|entry| entry.shares.clone())
}
pub fn get_client_share_data(
&self,
client_id: ClientId,
index: ClientShareIndex,
) -> Option<ClientShare> {
let entries = self.entries.read();
entries
.get(&client_id)
.and_then(|entry| entry.shares.get(index.index()).cloned())
}
pub fn get_client_input_bytes(&self, client_id: ClientId) -> Option<Vec<Vec<u8>>> {
let entries = self.entries.read();
entries.get(&client_id).map(|entry| {
entry
.shares
.iter()
.map(|share| share.bytes().to_vec())
.collect()
})
}
pub fn get_client_share_bytes(
&self,
client_id: ClientId,
index: ClientShareIndex,
) -> Option<Vec<u8>> {
self.get_client_share_data(client_id, index)
.map(|share| share.bytes().to_vec())
}
pub fn has_client_input(&self, client_id: ClientId) -> bool {
let entries = self.entries.read();
entries.contains_key(&client_id)
}
pub fn get_client_input_count(&self, client_id: ClientId) -> usize {
let entries = self.entries.read();
entries
.get(&client_id)
.map(|entry| entry.shares.len())
.unwrap_or(0)
}
pub fn list_clients(&self) -> Vec<ClientId> {
let entries = self.entries.read();
entries.keys().copied().collect()
}
pub fn remove_client_input(&self, client_id: ClientId) -> Option<ClientInputEntry> {
let mut entries = self.entries.write();
entries.remove(&client_id)
}
pub fn clear(&self) {
let mut entries = self.entries.write();
entries.clear();
drop(entries);
self.client_roster.write().clear();
}
pub fn len(&self) -> usize {
let roster = self.client_roster.read();
if roster.is_empty() {
self.entries.read().len()
} else {
roster.len()
}
}
pub fn input_client_count(&self) -> usize {
self.entries.read().len()
}
pub fn output_client_count(&self) -> usize {
self.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn client_id_at(&self, index: ClientInputIndex) -> Option<ClientId> {
let roster = self.client_roster.read();
if roster.is_empty() {
self.entries.read().keys().nth(index.index()).copied()
} else {
roster.get(index.index()).copied()
}
}
pub fn client_ids(&self) -> Vec<ClientId> {
let roster = self.client_roster.read();
if roster.is_empty() {
self.entries.read().keys().copied().collect()
} else {
roster.clone()
}
}
pub fn set_client_roster<I>(&self, clients: I)
where
I: IntoIterator<Item = ClientId>,
{
let mut clients = clients.into_iter().collect::<Vec<_>>();
clients.sort_unstable();
clients.dedup();
*self.client_roster.write() = clients;
}
pub fn add_known_client(&self, client_id: ClientId) {
let mut roster = self.client_roster.write();
match roster.binary_search(&client_id) {
Ok(_) => {}
Err(index) => roster.insert(index, client_id),
}
}
fn add_known_clients<I>(&self, clients: I)
where
I: IntoIterator<Item = ClientId>,
{
let mut roster = self.client_roster.read().clone();
roster.extend(clients);
self.set_client_roster(roster);
}
}