Crates.io | lagbuffer |
lib.rs | lagbuffer |
version | 0.2.0 |
source | src |
created_at | 2024-10-01 21:24:13.146958 |
updated_at | 2024-10-02 19:43:34.292605 |
description | **LagBuffer** is a Rust crate designed to handle out-of-order events and reconcile state efficiently. It is particularly useful in scenarios such as game development or networked applications, where events may arrive out of sequence due to network latency or other factors. |
homepage | |
repository | https://github.com/hardliner66/LagBuffer |
max_upload_size | |
id | 1393432 |
size | 29,671 |
LagBuffer is a Rust crate designed to handle out-of-order events and reconcile state efficiently. It is particularly useful in scenarios such as game development or networked applications, where events may arrive out of sequence due to network latency or other factors.
Add the following to your Cargo.toml:
[dependencies]
lagbuffer = "0.1.0"
Below is an example demonstrating how to use the LagBuffer
crate. In this example, we define custom State
and Event
implementations to be used with the LagBuffer
.
use lagbuffer::{LagBuffer, State, Event};
#[derive(Clone, Debug)]
struct MyState {
data: Vec<i32>,
}
impl MyState {
fn new() -> Self {
Self { data: Vec::new() }
}
}
impl State<usize> for MyState {
type Event = MyEvent;
fn apply(&mut self, event: &Self::Event) {
match event.action {
Action::Insert => self.data.push(event.value),
Action::Replace => {
if let Some(pos) = self.data.iter().position(|&x| x == event.target) {
self.data[pos] = event.value;
}
}
}
}
}
#[derive(Clone, Debug)]
enum Action {
Insert,
Replace,
}
#[derive(Clone, Debug)]
struct MyEvent {
id: usize,
value: i32,
target: i32,
action: Action,
}
impl Event<usize> for MyEvent {
fn get_order_key(&self) -> usize {
self.id
}
}
fn main() {
let initial_state = MyState::new();
const BUFFER_SIZE: usize = 4;
let mut buffer = LagBuffer::<MyState, BUFFER_SIZE>::new(initial_state);
// Apply events
buffer.update(MyEvent {
id: 1,
value: 10,
target: 0,
action: Action::Insert,
});
buffer.update(MyEvent {
id: 3,
value: 30,
target: 0,
action: Action::Insert,
});
buffer.update(MyEvent {
id: 2,
value: 20,
target: 0,
action: Action::Insert,
}); // Out-of-order event
// Access the current state
println!("Current data: {:?}", buffer.state().data);
}
Current data: [10, 20, 30]
Define Your State: Implement the State trait for your custom state (MyState). The apply method defines how events modify the state.
Define Your Events: Implement the Event trait for your event type (MyEvent). The get_order_key method returns an order key used to determine the event sequence.
Create a LagBuffer: Instantiate a LagBuffer with your state and specify the buffer size (BUFFER_SIZE).
Update with Events: Use the update method to process events, whether they arrive in order or out of order.
Access the State: Use the state method to get a reference to the current state after all events have been applied.
OrderKey
is used to determine the sequence of events. It must implement the Ord
trait.SIZE
) based on your application's requirements. A larger buffer can handle more out-of-order events but uses more memory.The LagBuffer
maintains two buffers to store events and reconstructs the state from a base state and the events. When an event is received:
If it's in order (its OrderKey
is greater than to the last event's key in the active buffer):
SIZE
, the event is also added to the secondary buffer.If it's out of order:
SIZE
and the secondary buffer is not empty, the event is also inserted into the secondary buffer at the correct position.When the active buffer's length exceeds SIZE
, a buffer swap occurs: