finished zero-copy migration!
now the entire networking and persistence stack is zero-copy with single-allocation, single-copy reads. Closes #128 Signed-off-by: Sienna Meridian Satterwhite <sienna@r3t.io>
This commit is contained in:
@@ -485,7 +485,7 @@ pub fn save_session(conn: &mut Connection, session: &crate::networking::Session)
|
||||
session.last_active,
|
||||
session.entity_count as i64,
|
||||
session.state.to_string(),
|
||||
session.secret,
|
||||
session.secret.as_ref().map(|b| b.as_ref()),
|
||||
],
|
||||
)?;
|
||||
Ok(())
|
||||
@@ -517,7 +517,8 @@ pub fn load_session(
|
||||
last_active: row.get(3)?,
|
||||
entity_count: row.get::<_, i64>(4)? as usize,
|
||||
state,
|
||||
secret: row.get(6)?,
|
||||
secret: row.get::<_, Option<std::borrow::Cow<'_, [u8]>>>(6)?
|
||||
.map(|cow| bytes::Bytes::copy_from_slice(&cow)),
|
||||
})
|
||||
},
|
||||
)
|
||||
@@ -548,7 +549,8 @@ pub fn get_last_active_session(conn: &Connection) -> Result<Option<crate::networ
|
||||
last_active: row.get(3)?,
|
||||
entity_count: row.get::<_, i64>(4)? as usize,
|
||||
state,
|
||||
secret: row.get(6)?,
|
||||
secret: row.get::<_, Option<std::borrow::Cow<'_, [u8]>>>(6)?
|
||||
.map(|cow| bytes::Bytes::copy_from_slice(&cow)),
|
||||
})
|
||||
},
|
||||
)
|
||||
@@ -643,10 +645,10 @@ pub fn load_entity_components(
|
||||
|
||||
let components: Vec<LoadedComponent> = stmt
|
||||
.query_map([entity_id.as_bytes()], |row| {
|
||||
let data_vec: Vec<u8> = row.get(1)?;
|
||||
let data_cow: std::borrow::Cow<'_, [u8]> = row.get(1)?;
|
||||
Ok(LoadedComponent {
|
||||
component_type: row.get(0)?,
|
||||
data: bytes::Bytes::from(data_vec),
|
||||
data: bytes::Bytes::copy_from_slice(&data_cow),
|
||||
})
|
||||
})?
|
||||
.collect::<std::result::Result<Vec<_>, _>>()?;
|
||||
@@ -669,7 +671,7 @@ pub fn load_entity_by_network_id(
|
||||
WHERE id = ?1",
|
||||
[network_id.as_bytes()],
|
||||
|row| {
|
||||
let id_bytes: Vec<u8> = row.get(0)?;
|
||||
let id_bytes: std::borrow::Cow<'_, [u8]> = row.get(0)?;
|
||||
let mut id_array = [0u8; 16];
|
||||
id_array.copy_from_slice(&id_bytes);
|
||||
let id = uuid::Uuid::from_bytes(id_array);
|
||||
@@ -714,7 +716,7 @@ pub fn load_all_entities(conn: &Connection) -> Result<Vec<LoadedEntity>> {
|
||||
)?;
|
||||
|
||||
let entity_rows = stmt.query_map([], |row| {
|
||||
let id_bytes: Vec<u8> = row.get(0)?;
|
||||
let id_bytes: std::borrow::Cow<'_, [u8]> = row.get(0)?;
|
||||
let mut id_array = [0u8; 16];
|
||||
id_array.copy_from_slice(&id_bytes);
|
||||
let id = uuid::Uuid::from_bytes(id_array);
|
||||
@@ -761,7 +763,7 @@ pub fn load_entities_by_type(conn: &Connection, entity_type: &str) -> Result<Vec
|
||||
)?;
|
||||
|
||||
let entity_rows = stmt.query_map([entity_type], |row| {
|
||||
let id_bytes: Vec<u8> = row.get(0)?;
|
||||
let id_bytes: std::borrow::Cow<'_, [u8]> = row.get(0)?;
|
||||
let mut id_array = [0u8; 16];
|
||||
id_array.copy_from_slice(&id_bytes);
|
||||
let id = uuid::Uuid::from_bytes(id_array);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//! Zero-copy component type registry using rkyv and inventory
|
||||
//! Type registry using rkyv and inventory
|
||||
//!
|
||||
//! This module provides a runtime type registry that collects all synced components
|
||||
//! via the `inventory` crate and assigns them numeric discriminants for efficient
|
||||
//! serialization.
|
||||
//! This module provides a runtime type registry that collects all synced
|
||||
//! components via the `inventory` crate and assigns them numeric discriminants
|
||||
//! for efficient serialization.
|
||||
|
||||
use std::{
|
||||
any::TypeId,
|
||||
@@ -26,10 +26,13 @@ pub struct ComponentMeta {
|
||||
/// Deserialization function that returns a boxed component
|
||||
pub deserialize_fn: fn(&[u8]) -> Result<Box<dyn std::any::Any>>,
|
||||
|
||||
/// Serialization function that reads from an entity (returns None if entity doesn't have this component)
|
||||
pub serialize_fn: fn(&bevy::ecs::world::World, bevy::ecs::entity::Entity) -> Option<bytes::Bytes>,
|
||||
/// Serialization function that reads from an entity (returns None if entity
|
||||
/// doesn't have this component)
|
||||
pub serialize_fn:
|
||||
fn(&bevy::ecs::world::World, bevy::ecs::entity::Entity) -> Option<bytes::Bytes>,
|
||||
|
||||
/// Insert function that takes a boxed component and inserts it into an entity
|
||||
/// Insert function that takes a boxed component and inserts it into an
|
||||
/// entity
|
||||
pub insert_fn: fn(&mut bevy::ecs::world::EntityWorldMut, Box<dyn std::any::Any>),
|
||||
}
|
||||
|
||||
@@ -47,10 +50,14 @@ pub struct ComponentTypeRegistry {
|
||||
discriminant_to_deserializer: HashMap<u16, fn(&[u8]) -> Result<Box<dyn std::any::Any>>>,
|
||||
|
||||
/// Discriminant to serialization function
|
||||
discriminant_to_serializer: HashMap<u16, fn(&bevy::ecs::world::World, bevy::ecs::entity::Entity) -> Option<bytes::Bytes>>,
|
||||
discriminant_to_serializer: HashMap<
|
||||
u16,
|
||||
fn(&bevy::ecs::world::World, bevy::ecs::entity::Entity) -> Option<bytes::Bytes>,
|
||||
>,
|
||||
|
||||
/// Discriminant to insert function
|
||||
discriminant_to_inserter: HashMap<u16, fn(&mut bevy::ecs::world::EntityWorldMut, Box<dyn std::any::Any>)>,
|
||||
discriminant_to_inserter:
|
||||
HashMap<u16, fn(&mut bevy::ecs::world::EntityWorldMut, Box<dyn std::any::Any>)>,
|
||||
|
||||
/// Discriminant to type name (for debugging)
|
||||
discriminant_to_name: HashMap<u16, &'static str>,
|
||||
@@ -138,7 +145,10 @@ impl ComponentTypeRegistry {
|
||||
}
|
||||
|
||||
/// Get the insert function for a discriminant
|
||||
pub fn get_insert_fn(&self, discriminant: u16) -> Option<fn(&mut bevy::ecs::world::EntityWorldMut, Box<dyn std::any::Any>)> {
|
||||
pub fn get_insert_fn(
|
||||
&self,
|
||||
discriminant: u16,
|
||||
) -> Option<fn(&mut bevy::ecs::world::EntityWorldMut, Box<dyn std::any::Any>)> {
|
||||
self.discriminant_to_inserter.get(&discriminant).copied()
|
||||
}
|
||||
|
||||
@@ -148,8 +158,13 @@ impl ComponentTypeRegistry {
|
||||
}
|
||||
|
||||
/// Get the deserialize function for a discriminant
|
||||
pub fn get_deserialize_fn(&self, discriminant: u16) -> Option<fn(&[u8]) -> Result<Box<dyn std::any::Any>>> {
|
||||
self.discriminant_to_deserializer.get(&discriminant).copied()
|
||||
pub fn get_deserialize_fn(
|
||||
&self,
|
||||
discriminant: u16,
|
||||
) -> Option<fn(&[u8]) -> Result<Box<dyn std::any::Any>>> {
|
||||
self.discriminant_to_deserializer
|
||||
.get(&discriminant)
|
||||
.copied()
|
||||
}
|
||||
|
||||
/// Get type path for a discriminant
|
||||
@@ -158,7 +173,10 @@ impl ComponentTypeRegistry {
|
||||
}
|
||||
|
||||
/// Get the deserialize function by type path
|
||||
pub fn get_deserialize_fn_by_path(&self, type_path: &str) -> Option<fn(&[u8]) -> Result<Box<dyn std::any::Any>>> {
|
||||
pub fn get_deserialize_fn_by_path(
|
||||
&self,
|
||||
type_path: &str,
|
||||
) -> Option<fn(&[u8]) -> Result<Box<dyn std::any::Any>>> {
|
||||
// Linear search through discriminant_to_path to find matching type_path
|
||||
for (discriminant, path) in &self.discriminant_to_path {
|
||||
if *path == type_path {
|
||||
@@ -169,7 +187,10 @@ impl ComponentTypeRegistry {
|
||||
}
|
||||
|
||||
/// Get the insert function by type path
|
||||
pub fn get_insert_fn_by_path(&self, type_path: &str) -> Option<fn(&mut bevy::ecs::world::EntityWorldMut, Box<dyn std::any::Any>)> {
|
||||
pub fn get_insert_fn_by_path(
|
||||
&self,
|
||||
type_path: &str,
|
||||
) -> Option<fn(&mut bevy::ecs::world::EntityWorldMut, Box<dyn std::any::Any>)> {
|
||||
// Linear search through discriminant_to_path to find matching type_path
|
||||
for (discriminant, path) in &self.discriminant_to_path {
|
||||
if *path == type_path {
|
||||
@@ -191,7 +212,8 @@ impl ComponentTypeRegistry {
|
||||
|
||||
/// Serialize all registered components from an entity
|
||||
///
|
||||
/// Returns Vec<(discriminant, type_path, serialized_bytes)> for all components that exist on the entity.
|
||||
/// Returns Vec<(discriminant, type_path, serialized_bytes)> for all
|
||||
/// components that exist on the entity.
|
||||
pub fn serialize_entity_components(
|
||||
&self,
|
||||
world: &bevy::ecs::world::World,
|
||||
|
||||
Reference in New Issue
Block a user