| Crates.io | lagbuffer |
| lib.rs | lagbuffer |
| version | 0.2.0 |
| created_at | 2024-10-01 21:24:13.146958+00 |
| updated_at | 2024-10-02 19:43:34.292605+00 |
| 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: