naia-client-socket 0.25.0

Abstraction to expose common API over a UDP socket on Linux, and a unreliable WebRTC datachannel on the browser
Documentation
use crate::{
    error::NaiaClientSocketError, packet_receiver::PacketReceiver, server_addr::ServerAddr,
};

use super::shared::{ERROR_QUEUE, MESSAGE_QUEUE, SERVER_ADDR};

/// Handles receiving messages from the Server through a given Client Socket
#[derive(Clone)]
pub struct PacketReceiverImpl {
    last_payload: Option<Box<[u8]>>,
}

impl PacketReceiverImpl {
    /// Create a new PacketReceiver, if supplied with the RtcDataChannel and a
    /// reference to a list of dropped messages
    pub fn new() -> Self {
        PacketReceiverImpl { last_payload: None }
    }
}

impl PacketReceiver for PacketReceiverImpl {
    fn receive(&mut self) -> Result<Option<&[u8]>, NaiaClientSocketError> {
        // Safety: MESSAGE_QUEUE, ERROR_QUEUE, and SERVER_ADDR are static muts written by the
        // JS bridge callbacks before receive() is ever called. wasm32 is single-threaded;
        // the JS bridge and Rust game loop are on the same thread and never run concurrently,
        // so accessing these statics without synchronization is safe on this target.
        unsafe {
            if let Some(msg_queue) = &mut MESSAGE_QUEUE {
                if let Some(message) = msg_queue.pop_front() {
                    self.last_payload = Some(message);
                    return Ok(Some(self.last_payload.as_ref().unwrap()));
                }
            }

            if let Some(error_queue) = &mut ERROR_QUEUE {
                if let Some(error) = error_queue.pop_front() {
                    return Err(NaiaClientSocketError::Message(error));
                }
            }
        };

        Ok(None)
    }

    /// Get the Server's Socket address
    fn server_addr(&self) -> ServerAddr {
        // Safety: SERVER_ADDR is set once at socket initialization; wasm32 is single-threaded.
        unsafe { SERVER_ADDR }
    }
}