Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,13 @@ pub fn get_name(p: Peer, buf: &mut [u8; 16]) -> &str {
}

/// Get the peer's system settings.
///
/// **IMPORTANT:** This is the only function that accepts as input not only [`Peer`]
/// but also [`Me`], which might lead to a state drift if used incorrectly.
/// See [the docs](https://docs.fireflyzero.com/dev/net/) for more info.
#[must_use]
pub fn get_settings(p: Peer) -> Settings {
let raw = unsafe { bindings::get_settings(u32::from(p.0)) };
pub fn get_settings<P: AnyPeer>(p: P) -> Settings {
let raw = unsafe { bindings::get_settings(u32::from(p.into_u8())) };
let code = [(raw >> 8) as u8, raw as u8];
let language = Language::from_code(code).unwrap_or_default();
let flags = raw >> 16;
Expand Down
88 changes: 65 additions & 23 deletions src/net.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
// The peer ID.
/// A peer obtained either from [`Peers`] ([`get_peers`]) or from [`get_me`].
pub trait AnyPeer {
/// Restore the peer from a primitive type (u8).
///
/// ## Safety
///
/// See [`AnyPeer::into_u8`].
#[must_use]
unsafe fn from_u8(p: u8) -> Self;

/// Dump the peer as a primitive type (u8).
///
/// ## Safety
///
/// For most applications, [`Peers`], [`Peer`], and [`Me`] types should
/// be considered opaque and agnostic of their internal representation.
/// However, some code interpreters written for Firefly in Rust (firefly-lua)
/// might need the ability to save values on the virtual stack as primitive types,
/// and this is where this function comes in handy.
#[must_use]
unsafe fn into_u8(self) -> u8;
}

/// The peer ID.
///
/// Constructed from [`Peers`] (which is constructed by [`get_peers`]).
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct Peer(pub(crate) u8);

/// Represents a specific device (or combination of such).
/// Represents a specific device (or a combination of all devices).
///
/// Used for reading and writing state of a device: input, stash, scores, etc.
impl Peer {
Expand All @@ -16,37 +41,54 @@ impl Default for Peer {
}
}

impl Peer {
/// Dump [`Peer`] as a primitive type (u8).
///
/// ## Safety
///
/// See [`Peer::to_u8`].
#[must_use]
pub unsafe fn from_u8(p: u8) -> Self {
impl AnyPeer for Peer {
unsafe fn from_u8(p: u8) -> Self {
Self(p)
}

/// Restore [`Peer`] from a primitive type (u8).
///
/// ## Safety
///
/// For most applications, [`Peers`] and [`Peer`] types should be considered
/// opaque and agnostic of their internal representation.
/// However, some code interpreters written for Firefly in Rust
/// might need the ability to save values on virtual stack as primitive types,
/// and this is where this function comes in handy.
#[must_use]
pub unsafe fn into_u8(self) -> u8 {
unsafe fn into_u8(self) -> u8 {
self.0
}
}

/// The peer representing the current device.
///
/// Can be compared to [`Peer`] or used to [`get_settings`][crate::get_settings].
///
/// **IMPORTANT:** Using this type may cause state drift between device in multiplayer.
/// See [the docs](https://docs.fireflyzero.com/dev/net/) for more info.
#[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
}
}

/// The list of peers online.
///
/// Includes all connected peers as well as the local device.
///
/// The order is deterministic between calls and between runs.
///
/// Constructed by [`get_peers`].
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct Peers(pub(crate) u32);

Expand Down Expand Up @@ -163,9 +205,9 @@ type Stash = [u8];

/// Get the peer corresponding to the local device.
#[must_use]
pub fn get_me() -> Peer {
pub fn get_me() -> Me {
let me = unsafe { bindings::get_me() };
Peer(me as u8)
Me(me as u8)
}

/// Get the list of peers online.
Expand Down