✨♻️ bevy_vanth, vanth, vanth_derive, flake: Add Bevy integration crate and refactor entity/networking
- Created new crate `bevy_vanth` with basic plugin structure for Bevy integration. - Refactored `Id` generation in `vanth` to use `OsRng` and removed redundant `to_u128_pair`/`from_u128_pair` methods. - Moved networking functionality into new `net` module with `Node`, `Packet`, and `Message` types. - Updated `vanth_derive` to use `proc-macro-crate` for reliable crate path resolution. - Added `rand` dependency to replace custom ID generation logic. - Updated `Cargo.toml`/`Cargo.lock` with new dependencies: `bevy_app`, `nix`, `cfg_aliases`, `proc-macro-crate`. - Modified `README.md` with improved project description. - Added commented clippy check in `flake.nix`.
This commit is contained in:
parent
5262a266c0
commit
3b193c5aa3
13 changed files with 298 additions and 127 deletions
8
crates/bevy_vanth/Cargo.toml
Normal file
8
crates/bevy_vanth/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "bevy_vanth"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
bevy_ecs.workspace = true
|
||||
bevy_app.workspace = true
|
20
crates/bevy_vanth/src/lib.rs
Normal file
20
crates/bevy_vanth/src/lib.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
use bevy_app::Plugin;
|
||||
use bevy_ecs::component::Component;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct VanthRoot {}
|
||||
|
||||
pub struct VanthPlugin {}
|
||||
|
||||
impl Plugin for VanthPlugin {
|
||||
fn build(&self, app: &mut bevy_app::App) {
|
||||
// TODO: Allow specifying custom schedules.
|
||||
app.add_systems(bevy_app::FixedPreUpdate, run_vanth).finish();
|
||||
}
|
||||
}
|
||||
|
||||
impl VanthPlugin {}
|
||||
|
||||
fn run_vanth() {
|
||||
|
||||
}
|
|
@ -16,6 +16,7 @@ blake3.workspace = true
|
|||
vanth_derive = { path = "../vanth_derive" }
|
||||
rusqlite.workspace = true
|
||||
tracing.workspace = true
|
||||
rand = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = { workspace = true }
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use vanth::{hash, Vanth};
|
||||
// use serde::{Deserialize, Serialize};
|
||||
// use vanth::{hash, Vanth};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, Vanth)]
|
||||
struct Foo {
|
||||
value: i32,
|
||||
}
|
||||
// #[derive(Clone, Debug, Deserialize, Serialize, Vanth)]
|
||||
// struct Foo {
|
||||
// value: i32,
|
||||
// }
|
||||
|
||||
fn main() {
|
||||
let x = "hello";
|
||||
println!("Hash: {:?}", hash(&x).hex());
|
||||
// let x = "hello";
|
||||
// println!("Hash: {:?}", hash(&x).hex());
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use crate::hash;
|
||||
use crate::hashing_serializer::{self, HashingSerializer};
|
||||
use rand::rngs::OsRng;
|
||||
use rand::TryRngCore;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{self, Debug, Display};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::hash;
|
||||
use crate::hashing_serializer::{self, HashingSerializer};
|
||||
|
||||
#[derive(Clone, Copy, Deserialize)]
|
||||
pub struct EntityId([u8; 32]);
|
||||
|
||||
|
@ -16,7 +17,7 @@ impl From<String> for EntityId {
|
|||
}
|
||||
|
||||
/// A generic identifier type that can be used for different entity types
|
||||
#[derive(Clone, Copy, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
pub struct Id<T: ?Sized> {
|
||||
/// The raw identifier value
|
||||
pub value: [u8; 32],
|
||||
|
@ -37,14 +38,7 @@ impl<T: ?Sized> Id<T> {
|
|||
/// Generate a random ID
|
||||
pub fn random() -> Self {
|
||||
let mut value = [0u8; 32];
|
||||
// Simple random generation for demonstration
|
||||
for i in 0..32 {
|
||||
value[i] = (std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos() as u8)
|
||||
.wrapping_add(i as u8);
|
||||
}
|
||||
OsRng.try_fill_bytes(&mut value).unwrap();
|
||||
Self::new(value)
|
||||
}
|
||||
|
||||
|
@ -67,42 +61,6 @@ impl<T: ?Sized> Id<T> {
|
|||
}
|
||||
Self::new(bytes)
|
||||
}
|
||||
|
||||
/// Convert the ID to a pair of u128 values for handling larger values
|
||||
/// Returns (high_bits, low_bits)
|
||||
pub fn to_u128_pair(&self) -> (u128, u128) {
|
||||
let mut high = 0u128;
|
||||
let mut low = 0u128;
|
||||
|
||||
// First 16 bytes go to low
|
||||
for i in 0..16 {
|
||||
low |= (self.value[i] as u128) << (i * 8);
|
||||
}
|
||||
|
||||
// Next 16 bytes go to high
|
||||
for i in 0..16 {
|
||||
high |= (self.value[i + 16] as u128) << (i * 8);
|
||||
}
|
||||
|
||||
(high, low)
|
||||
}
|
||||
|
||||
/// Create an ID from a pair of u128 values
|
||||
pub fn from_u128_pair(high: u128, low: u128) -> Self {
|
||||
let mut bytes = [0u8; 32];
|
||||
|
||||
// Low bits fill first 16 bytes
|
||||
for i in 0..16 {
|
||||
bytes[i] = ((low >> (i * 8)) & 0xFF) as u8;
|
||||
}
|
||||
|
||||
// High bits fill next 16 bytes
|
||||
for i in 0..16 {
|
||||
bytes[i + 16] = ((high >> (i * 8)) & 0xFF) as u8;
|
||||
}
|
||||
|
||||
Self::new(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> PartialEq for Id<T> {
|
||||
|
@ -119,20 +77,6 @@ impl<T: ?Sized> Hash for Id<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Debug for Id<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let (high, low) = self.to_u128_pair();
|
||||
write!(f, "Id<{}>({:016x}{:016x})", std::any::type_name::<T>(), high, low)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Display for Id<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let (high, low) = self.to_u128_pair();
|
||||
write!(f, "{:016x}{:016x}", high, low)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ContentHash {
|
||||
value: [u8; 32],
|
||||
}
|
||||
|
|
|
@ -7,10 +7,12 @@ use crate::entity::EntityId;
|
|||
|
||||
pub mod entity;
|
||||
pub mod hashing_serializer;
|
||||
pub mod net;
|
||||
pub mod nix;
|
||||
pub mod store;
|
||||
|
||||
pub use hashing_serializer::hash;
|
||||
pub use net::Node;
|
||||
pub use vanth_derive::Vanth;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
@ -19,41 +21,6 @@ pub enum Error {
|
|||
Other(String),
|
||||
}
|
||||
|
||||
|
||||
/// A view of all of the [`Node`]s in a cluster.
|
||||
pub struct Network {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/// A Vanth server.
|
||||
pub struct Node {
|
||||
// TODO
|
||||
}
|
||||
|
||||
impl Node {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
pub fn entity_count(&self) -> usize {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn run() {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn save(entity_id: impl Into<EntityId>) -> Result<()> {
|
||||
// TODO
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn load(entity_id: impl Into<EntityId>) -> Result<Option<EntityContents>> {
|
||||
// // TODO
|
||||
// Ok(None)
|
||||
// }
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct HashedValue {
|
||||
content_hash: ContentHash,
|
||||
|
@ -75,9 +42,15 @@ pub struct Value {
|
|||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)]
|
||||
pub struct EventTy(Ty);
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)]
|
||||
pub struct TaskTy(Ty);
|
||||
|
||||
/// A wrapper for the fully-qualified name of a Rust type. This should be univerisally unique for a given type within a
|
||||
/// given project.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, Eq, Hash)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)]
|
||||
pub struct Ty {
|
||||
pub path: Vec<String>,
|
||||
}
|
||||
|
@ -88,12 +61,6 @@ impl ToString for Ty {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Ty {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.path == other.path
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<str>> PartialEq<T> for Ty {
|
||||
fn eq(&self, other: &T) -> bool {
|
||||
self.to_string() == *other.as_ref()
|
||||
|
@ -182,5 +149,49 @@ pub struct Handle<T> {
|
|||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
pub trait Task {
|
||||
type Output: Vanth + Serialize + DeserializeOwned;
|
||||
|
||||
// TODO: Make async?
|
||||
fn execute(self) -> Self::Output;
|
||||
}
|
||||
|
||||
/// A representation of the approximate computational cost of completing a task.
|
||||
pub struct Cost {
|
||||
value: f64,
|
||||
}
|
||||
|
||||
/// A world which Vanth entities live in. Lifetimes `'v` of [`Vanth<'v>`] types are tied to the lifetime of the `Root`.
|
||||
pub struct Root {}
|
||||
pub struct Root {
|
||||
current_epoch: u64,
|
||||
}
|
||||
|
||||
pub trait Module {
|
||||
fn register(world_context: &mut ModuleRegistration);
|
||||
}
|
||||
|
||||
pub struct ModuleRegistration {
|
||||
events: Vec<EventTy>,
|
||||
}
|
||||
|
||||
impl ModuleRegistration {}
|
||||
|
||||
pub trait ModuleTools: Module {
|
||||
type Tool: Tool;
|
||||
|
||||
fn tools(&self) -> impl Iterator<Item = Self::Tool>;
|
||||
}
|
||||
|
||||
pub trait Tool: Send + Sync {
|
||||
type Input;
|
||||
type Output;
|
||||
type Error: std::error::Error;
|
||||
|
||||
fn name<'a>() -> &'a str;
|
||||
fn description<'a>() -> &'a str;
|
||||
|
||||
fn call(
|
||||
&self,
|
||||
input: Self::Input,
|
||||
) -> impl Future<Output = std::result::Result<Self::Output, Self::Error>> + Send;
|
||||
}
|
||||
|
|
63
crates/vanth/src/net.rs
Normal file
63
crates/vanth/src/net.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Error, Result};
|
||||
use crate::{
|
||||
Vanth,
|
||||
entity::{EntityId, Id},
|
||||
};
|
||||
|
||||
pub struct Packet {
|
||||
pub source_node: Id<Node>,
|
||||
pub signature: Vec<u8>,
|
||||
pub message: Message,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, Vanth)]
|
||||
pub struct Message {
|
||||
pub events: Vec<Event>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, Vanth)]
|
||||
pub enum Event {}
|
||||
|
||||
/// A view of all of the [`Node`]s in a cluster.
|
||||
pub struct Network {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/// A Vanth server.
|
||||
pub struct Node {
|
||||
id: Id<Node>,
|
||||
}
|
||||
|
||||
impl Node {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
id: Id::random(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_id(id: Id<Node>) -> Self {
|
||||
Self {
|
||||
id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn entity_count(&self) -> usize {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn run() {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn save(entity_id: impl Into<EntityId>) -> Result<()> {
|
||||
// TODO
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn load(entity_id: impl Into<EntityId>) -> Result<Option<EntityContents>> {
|
||||
// // TODO
|
||||
// Ok(None)
|
||||
// }
|
||||
}
|
|
@ -9,4 +9,5 @@ proc-macro = true
|
|||
[dependencies]
|
||||
quote.workspace = true
|
||||
syn.workspace = true
|
||||
proc-macro2.workspace = true
|
||||
proc-macro2.workspace = true
|
||||
proc-macro-crate.workspace = true
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use proc_macro::TokenStream;
|
||||
use proc_macro_crate::{crate_name, FoundCrate};
|
||||
use proc_macro2::Span;
|
||||
use quote::quote;
|
||||
use syn::parse_quote;
|
||||
use syn::{DeriveInput, GenericParam, Generics, parse_macro_input};
|
||||
|
@ -11,6 +13,15 @@ pub fn vanth_derive(input: TokenStream) -> TokenStream {
|
|||
|
||||
let mut generics = input.generics.clone();
|
||||
|
||||
let vanth_path = match crate_name("vanth") {
|
||||
Ok(FoundCrate::Itself) => quote!(crate),
|
||||
Ok(FoundCrate::Name(name)) => {
|
||||
let ident = syn::Ident::new(&name, Span::call_site());
|
||||
quote!(#ident)
|
||||
}
|
||||
Err(_) => quote!(vanth),
|
||||
};
|
||||
|
||||
let type_params: Vec<syn::Ident> = generics
|
||||
.params
|
||||
.iter()
|
||||
|
@ -25,7 +36,7 @@ pub fn vanth_derive(input: TokenStream) -> TokenStream {
|
|||
|
||||
let mut where_clause = generics.where_clause.clone().unwrap_or_else(|| parse_quote!(where));
|
||||
for tp in &type_params {
|
||||
where_clause.predicates.push(parse_quote!(#tp : vanth::Vanth));
|
||||
where_clause.predicates.push(parse_quote!(#tp : #vanth_path::Vanth));
|
||||
}
|
||||
|
||||
let (impl_generics, ty_generics, _) = generics.split_for_impl();
|
||||
|
@ -34,19 +45,19 @@ pub fn vanth_derive(input: TokenStream) -> TokenStream {
|
|||
quote! { String::new() }
|
||||
} else {
|
||||
quote! {
|
||||
format!("<{}>", [#(#type_params::ty().path.join("::")),*].join(","))
|
||||
format!("<{}>", [#( <#type_params as #vanth_path::Vanth>::ty().path.join("::") ),*].join(","))
|
||||
}
|
||||
};
|
||||
|
||||
let expanded = quote! {
|
||||
impl #impl_generics vanth::Vanth for #name #ty_generics #where_clause {
|
||||
fn ty() -> vanth::Ty {
|
||||
impl #impl_generics #vanth_path::Vanth for #name #ty_generics #where_clause {
|
||||
fn ty() -> #vanth_path::Ty {
|
||||
let module_path = module_path!();
|
||||
let mut path: Vec<String> = module_path.split("::").map(|s| s.to_string()).collect();
|
||||
let base_name = stringify!(#name);
|
||||
let generics_str = #generics_code;
|
||||
path.push(format!("{}{}", base_name, generics_str));
|
||||
vanth::Ty { path }
|
||||
#vanth_path::Ty { path }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue