Adding examples in documentation
All checks were successful
Rust Checks / checks (push) Successful in 8s
Rust Checks / checks (pull_request) Successful in 6s

This commit is contained in:
Tipragot 2024-02-07 09:04:51 +01:00
parent 672e8af818
commit 19aade3c13

View file

@ -2,9 +2,48 @@
use std::collections::LinkedList; use std::collections::LinkedList;
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::net::{TcpStream, ToSocketAddrs}; use std::net::{TcpListener, TcpStream, ToSocketAddrs};
/// A non-blocking tcp connection. /// A non-blocking tcp connection.
///
/// # Example
///
/// ```rust
/// use std::io;
///
/// use bevnet::{Connection, Listener};
///
/// # fn main() -> io::Result<()> {
/// let listener = Listener::bind("127.0.0.1:23732")?;
/// let mut connection = Connection::connect("127.0.0.1:23732")?;
///
/// // The accept operation is not blocking. So we need to loop here.
/// let mut server_connection;
/// loop {
/// if let Some(new_connection) = listener.accept()? {
/// server_connection = new_connection;
/// break;
/// }
/// }
///
/// // We don't need to loop here because the send operation just appends to the send buffer.
/// connection.send(b"Hello, world!")?;
///
/// // To be sure the message has been sent, we need to update the connection.
/// while !connection.update()? {
/// // Wait until the connection is updated.
/// }
///
/// // The receive operation is not blocking. So we need to loop here.
/// loop {
/// if let Some(message) = server_connection.receive()? {
/// assert_eq!(message, b"Hello, world!");
/// break;
/// }
/// }
/// # Ok(())
/// # }
/// ```
pub struct Connection { pub struct Connection {
/// The underlying [TcpStream] used for the connection. /// The underlying [TcpStream] used for the connection.
stream: TcpStream, stream: TcpStream,
@ -49,8 +88,11 @@ impl Connection {
/// Sends a message over the connection. /// Sends a message over the connection.
/// ///
/// Returns `true` if the message has been sent directly and `false`
/// if the message is still in the send queue.
///
/// This function is not blocking. /// This function is not blocking.
pub fn send(&mut self, message: &[u8]) -> io::Result<()> { pub fn send(&mut self, message: &[u8]) -> io::Result<bool> {
// Get the length of the message as a u16. // Get the length of the message as a u16.
let message_len: u16 = match message.len().try_into() { let message_len: u16 = match message.len().try_into() {
Ok(len) => len, Ok(len) => len,
@ -75,9 +117,11 @@ impl Connection {
/// Updates the connection. /// Updates the connection.
/// ///
/// This function sends any pending messages that have not been sent yet. /// This function sends any pending messages that have not been sent yet.
/// It returns `true` if there is no remaining data to send after updating
/// the connection and `false` otherwise.
/// ///
/// This function is not blocking. /// This function is not blocking.
pub fn update(&mut self) -> io::Result<()> { pub fn update(&mut self) -> io::Result<bool> {
// Looping over the send buffers. // Looping over the send buffers.
while let Some((offset, buffer)) = self.send_buffers.front_mut() { while let Some((offset, buffer)) = self.send_buffers.front_mut() {
// Writing the buffer to the stream. // Writing the buffer to the stream.
@ -95,7 +139,7 @@ impl Connection {
} }
// Returning success. // Returning success.
Ok(()) Ok(self.send_buffers.is_empty())
} }
/// Receives a byte block from the connection. /// Receives a byte block from the connection.
@ -177,3 +221,48 @@ impl Connection {
Ok(Some(&self.receive_buffer[..message_len as usize])) Ok(Some(&self.receive_buffer[..message_len as usize]))
} }
} }
/// A non-blocking tcp listener.
///
/// ```rust
/// use std::io;
///
/// use bevnet::{Connection, Listener};
///
/// # fn main() -> io::Result<()> {
/// let listener = Listener::bind("127.0.0.1:23732")?;
/// let mut connection = Connection::connect("127.0.0.1:23732")?;
///
/// // The accept operation is not blocking. So we need to loop here.
/// let mut server_connection;
/// loop {
/// if let Some(new_connection) = listener.accept()? {
/// server_connection = new_connection;
/// break;
/// }
/// }
/// # Ok(())
/// # }
/// ```
pub struct Listener(TcpListener);
impl Listener {
/// Creates a new listener.
pub fn bind(addr: impl ToSocketAddrs) -> io::Result<Listener> {
let listener = TcpListener::bind(addr)?;
listener.set_nonblocking(true)?;
Ok(Listener(listener))
}
/// Accepts a new [Connection].
///
/// This function is not blocking.
pub fn accept(&self) -> io::Result<Option<Connection>> {
match self.0.accept() {
Ok((stream, _)) => Connection::new(stream).map(Some),
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Ok(None),
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => Ok(None),
Err(e) => Err(e),
}
}
}