pub trait AnyPeer {
#[must_use]
unsafe fn from_u8(p: u8) -> Self;
#[must_use]
unsafe fn into_u8(self) -> u8;
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct Peer(pub(crate) u8);
impl Peer {
pub const COMBINED: Self = Peer(0xFF);
}
impl Default for Peer {
fn default() -> Self {
Self::COMBINED
}
}
impl AnyPeer for Peer {
unsafe fn from_u8(p: u8) -> Self {
Self(p)
}
unsafe fn into_u8(self) -> u8 {
self.0
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct Me(pub(crate) u8);
impl AnyPeer for Me {
unsafe fn from_u8(p: u8) -> Self {
Self(p)
}
unsafe fn into_u8(self) -> u8 {
self.0
}
}
impl PartialEq<Peer> for Me {
fn eq(&self, other: &Peer) -> bool {
self.0 == other.0
}
}
impl PartialEq<Me> for Peer {
fn eq(&self, other: &Me) -> bool {
self.0 == other.0
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct Peers(pub(crate) u32);
impl Peers {
#[must_use]
pub unsafe fn from_u32(p: u32) -> Self {
Self(p)
}
#[must_use]
pub unsafe fn into_u32(self) -> u32 {
self.0
}
#[must_use]
pub fn iter(&self) -> PeersIter {
PeersIter {
peer: 0,
peers: self.0,
}
}
#[must_use]
pub fn contains(&self, p: &Peer) -> bool {
(self.0 >> p.0) & 1 != 0
}
#[must_use]
#[expect(clippy::len_without_is_empty)] pub fn len(&self) -> usize {
self.0.count_ones() as usize
}
#[cfg(feature = "alloc")]
#[must_use]
pub fn as_vec(&self) -> alloc::vec::Vec<Peer> {
self.iter().collect()
}
}
impl IntoIterator for Peers {
type Item = Peer;
type IntoIter = PeersIter;
fn into_iter(self) -> Self::IntoIter {
PeersIter {
peer: 0,
peers: self.0,
}
}
}
pub struct PeersIter {
peer: u8,
peers: u32,
}
impl Iterator for PeersIter {
type Item = Peer;
fn next(&mut self) -> Option<Self::Item> {
while self.peers != 0 {
let peer = self.peer;
let peers = self.peers;
self.peer += 1;
self.peers >>= 1;
if peers & 1 != 0 {
return Some(Peer(peer));
}
}
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.peers.count_ones() as usize;
(size, Some(size))
}
fn count(self) -> usize {
self.peers.count_ones() as usize
}
}
type Stash = [u8];
#[must_use]
pub fn get_me() -> Me {
let me = unsafe { bindings::get_me() };
Me(me as u8)
}
#[must_use]
pub fn get_peers() -> Peers {
let peers = unsafe { bindings::get_peers() };
Peers(peers)
}
pub fn save_stash(peer: Peer, stash: &Stash) {
let ptr = stash.as_ptr();
let peer = u32::from(peer.0);
unsafe {
bindings::save_stash(peer, ptr as u32, stash.len() as u32);
}
}
#[must_use]
pub fn load_stash(peer: Peer, stash: &mut Stash) -> Option<&mut Stash> {
let ptr = stash.as_ptr();
let peer = u32::from(peer.0);
let size = unsafe { bindings::load_stash(peer, ptr as u32, stash.len() as u32) };
if size == 0 {
return None;
}
let size = size as usize;
Some(&mut stash[..size])
}
#[must_use]
pub fn load_stash_buf<const N: usize>(peer: Peer) -> Option<[u8; N]> {
let stash = [0u8; N];
let ptr = stash.as_ptr();
let peer = u32::from(peer.0);
let size = unsafe { bindings::load_stash(peer, ptr as u32, stash.len() as u32) };
if size == 0 {
return None;
}
Some(stash)
}
mod bindings {
#[link(wasm_import_module = "net")]
unsafe extern "C" {
pub(crate) fn get_me() -> u32;
pub(crate) fn get_peers() -> u32;
pub(crate) fn save_stash(peer: u32, ptr: u32, len: u32);
pub(crate) fn load_stash(peer: u32, ptr: u32, len: u32) -> u32;
}
}