♻️🍱💩👷 crates/vanth, project: Refactor entity system and setup; migrate to Nix flakes
- Add `.cargo/config.toml` with target directory and rustflags configuration. - Remove devenv files and set up Nix flake configuration with `flake.nix` and `flake.lock`. - Add dependencies on `blake3`, `digest`, and hashing-related crates for content hashing functionality. - Implement `EntityId` as hashed representation and `ContentHash` component using Blake3. - Add `hashing_serializer` module for serializing and hashing components. - Remove unused `parser` module and restructure lib.rs with new `Reference` type and storage interfaces. - Add test files for `store` and `reference` functionality with TODOs for implementation. - Introduce `VanthPlugin` skeleton and entity save/load interfaces with placeholder implementations. - Add `Reference` type with retrieval state machine and async handling stubs.
This commit is contained in:
parent
be75844fdd
commit
45a68865b6
19 changed files with 918 additions and 261 deletions
3
.cargo/config.toml
Normal file
3
.cargo/config.toml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[build]
|
||||||
|
target-dir = "target/cargo"
|
||||||
|
rustflags = ["-A", "unused", "-W", "unused_must_use"]
|
3
.envrc
3
.envrc
|
@ -1,3 +0,0 @@
|
||||||
source_url "https://raw.githubusercontent.com/cachix/devenv/95f329d49a8a5289d31e0982652f7058a189bfca/direnvrc" "sha256-d+8cBpDfDBj41inrADaJt+bDWhOktwslgoP5YiGJ1v0="
|
|
||||||
|
|
||||||
use devenv
|
|
1
.rules
1
.rules
|
@ -1 +0,0 @@
|
||||||
/home/asraelite/base/ai_rules/zed.md
|
|
101
Cargo.lock
generated
101
Cargo.lock
generated
|
@ -2,6 +2,12 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayref"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
|
@ -238,6 +244,29 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blake3"
|
||||||
|
version = "1.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0"
|
||||||
|
dependencies = [
|
||||||
|
"arrayref",
|
||||||
|
"arrayvec",
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"constant_time_eq",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.19.0"
|
version = "3.19.0"
|
||||||
|
@ -250,6 +279,15 @@ version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.2.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7"
|
||||||
|
dependencies = [
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -272,6 +310,12 @@ dependencies = [
|
||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "constant_time_eq"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "critical-section"
|
name = "critical-section"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
@ -293,6 +337,16 @@ version = "0.8.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctrlc"
|
name = "ctrlc"
|
||||||
version = "3.4.7"
|
version = "3.4.7"
|
||||||
|
@ -324,6 +378,17 @@ dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.10.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"crypto-common",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "disqualified"
|
name = "disqualified"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -395,6 +460,16 @@ dependencies = [
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.14.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -657,6 +732,12 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.10"
|
version = "0.4.10"
|
||||||
|
@ -693,6 +774,12 @@ version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "subtle"
|
||||||
|
version = "2.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.104"
|
version = "2.0.104"
|
||||||
|
@ -756,6 +843,12 @@ version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
|
checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.18.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
|
@ -786,6 +879,8 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy_app",
|
"bevy_app",
|
||||||
"bevy_ecs",
|
"bevy_ecs",
|
||||||
|
"blake3",
|
||||||
|
"digest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
@ -801,6 +896,12 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.14.2+wasi-0.2.4"
|
version = "0.14.2+wasi-0.2.4"
|
||||||
|
|
|
@ -9,5 +9,8 @@ edition = "2024"
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
bevy_app = "0.16.1"
|
bevy_app = "0.16.1"
|
||||||
bevy_ecs = "0.16.1"
|
bevy_ecs = "0.16.1"
|
||||||
|
bitcode = "0.6.6"
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
serde_json = "1.0.140"
|
serde_json = "1.0.140"
|
||||||
|
digest = "0.10.7"
|
||||||
|
blake3 = { version = "1.8.2", features = ["traits-preview"] }
|
||||||
|
|
|
@ -9,5 +9,7 @@ path = "src/lib.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy_app.workspace = true
|
bevy_app.workspace = true
|
||||||
bevy_ecs.workspace = true
|
bevy_ecs.workspace = true
|
||||||
|
digest.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
|
blake3.workspace = true
|
||||||
|
|
|
@ -3,6 +3,18 @@ use std::fmt::{self, Debug, Display};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use crate::hash;
|
||||||
|
use crate::hashing_serializer::{self, HashingSerializer};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Deserialize)]
|
||||||
|
pub struct EntityId([u8; 32]);
|
||||||
|
|
||||||
|
impl From<String> for EntityId {
|
||||||
|
fn from(value: String) -> Self {
|
||||||
|
Self(hash(&value).hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A generic identifier type that can be used for different entity types
|
/// A generic identifier type that can be used for different entity types
|
||||||
#[derive(Clone, Copy, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Serialize, Deserialize)]
|
||||||
pub struct Id<T: ?Sized> {
|
pub struct Id<T: ?Sized> {
|
||||||
|
|
390
crates/vanth/src/hashing_serializer.rs
Normal file
390
crates/vanth/src/hashing_serializer.rs
Normal file
|
@ -0,0 +1,390 @@
|
||||||
|
// Stolen and adapted from https://github.com/fjarri/hashing-serializer/blob/master/src/lib.rs
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use digest::Update;
|
||||||
|
use serde::{
|
||||||
|
ser::{
|
||||||
|
self, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
|
||||||
|
SerializeTupleStruct, SerializeTupleVariant,
|
||||||
|
},
|
||||||
|
Serialize, Serializer,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::ContentHash;
|
||||||
|
|
||||||
|
pub fn hash(value: &impl Serialize) -> ContentHash {
|
||||||
|
let mut digest = blake3::Hasher::new();
|
||||||
|
let mut serializer = HashingSerializer { digest: &mut digest };
|
||||||
|
// TODO: Don't unwrap.
|
||||||
|
serializer.serialize_value(value).unwrap();
|
||||||
|
ContentHash { hash: *serializer.digest.finalize().as_bytes() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A serializer that hashes the data instead of serializing it.
|
||||||
|
pub struct HashingSerializer<'a, T: Update> {
|
||||||
|
/// A reference to the digest that will accumulate the data.
|
||||||
|
pub digest: &'a mut T,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Possible errors during serialization.
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
|
pub enum Error {
|
||||||
|
/// The type's [`serde::Serialize`] impl tried to serialize a sequence of undefined length.
|
||||||
|
UndefinedSequenceLength,
|
||||||
|
|
||||||
|
/// Sequence length does not fit into `u128`.
|
||||||
|
///
|
||||||
|
/// Really, this shouldn't ever happen.
|
||||||
|
SequenceLengthTooLarge,
|
||||||
|
|
||||||
|
/// [`Serializer::collect_str`] got called, but heap memory allocation is not available.
|
||||||
|
///
|
||||||
|
/// Can only be returned if `alloc` feature not enabled.
|
||||||
|
CannotCollectStr,
|
||||||
|
|
||||||
|
/// Custom `serde` error, but memory allocation is not available.
|
||||||
|
/// Set a breakpoint where this is thrown for more information.
|
||||||
|
///
|
||||||
|
/// Can only be returned if `alloc` feature not enabled).
|
||||||
|
CustomErrorNoAlloc,
|
||||||
|
|
||||||
|
/// Custom `serde` error.
|
||||||
|
CustomError(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ser::Error for Error {
|
||||||
|
fn custom<T: fmt::Display>(msg: T) -> Self {
|
||||||
|
Self::CustomError(format!("{}", msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ser::StdError for Error {}
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{:?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts the `usize` sequence length to a fixed length type,
|
||||||
|
/// since we want the result to be portable.
|
||||||
|
fn try_into_sequence_length(len: usize) -> Result<u128, Error> {
|
||||||
|
u128::try_from(len)
|
||||||
|
.ok()
|
||||||
|
.ok_or(Error::SequenceLengthTooLarge)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement `serialize_$ty` for int types
|
||||||
|
macro_rules! impl_trivial_serialize {
|
||||||
|
($method_name:ident , $t:ty) => {
|
||||||
|
fn $method_name(self, v: $t) -> Result<Self::Ok, Self::Error> {
|
||||||
|
self.digest.update(&v.to_be_bytes());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_serialize_trait {
|
||||||
|
($method_name:ident , $t:ty) => {
|
||||||
|
fn $method_name(self, v: $t) -> Result<Self::Ok, Self::Error> {
|
||||||
|
self.digest.update(&v.to_be_bytes());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Update> Serializer for HashingSerializer<'a, T> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
type SerializeSeq = Self;
|
||||||
|
type SerializeTuple = Self;
|
||||||
|
type SerializeTupleStruct = Self;
|
||||||
|
type SerializeTupleVariant = Self;
|
||||||
|
type SerializeMap = Self;
|
||||||
|
type SerializeStruct = Self;
|
||||||
|
type SerializeStructVariant = Self;
|
||||||
|
|
||||||
|
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
|
||||||
|
self.digest.update(&(v as u8).to_be_bytes());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_trivial_serialize!(serialize_i8, i8);
|
||||||
|
impl_trivial_serialize!(serialize_i16, i16);
|
||||||
|
impl_trivial_serialize!(serialize_i32, i32);
|
||||||
|
impl_trivial_serialize!(serialize_i64, i64);
|
||||||
|
|
||||||
|
impl_trivial_serialize!(serialize_u8, u8);
|
||||||
|
impl_trivial_serialize!(serialize_u16, u16);
|
||||||
|
impl_trivial_serialize!(serialize_u32, u32);
|
||||||
|
impl_trivial_serialize!(serialize_u64, u64);
|
||||||
|
|
||||||
|
impl_trivial_serialize!(serialize_f32, f32);
|
||||||
|
impl_trivial_serialize!(serialize_f64, f64);
|
||||||
|
|
||||||
|
fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
|
||||||
|
// `char` is always at most 4 bytes, regardless of the platform,
|
||||||
|
// so this conversion is safe.
|
||||||
|
self.digest.update(&u64::from(v).to_be_bytes());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
|
||||||
|
self.digest.update(v.as_ref());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
|
||||||
|
self.digest.update(v);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
|
||||||
|
self.digest.update(&[0]);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_some<V: ?Sized + Serialize>(self, value: &V) -> Result<Self::Ok, Self::Error> {
|
||||||
|
self.digest.update(&[1]);
|
||||||
|
value.serialize(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_unit_variant(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
variant_index: u32,
|
||||||
|
_variant: &'static str,
|
||||||
|
) -> Result<Self::Ok, Self::Error> {
|
||||||
|
self.digest.update(&variant_index.to_be_bytes());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_newtype_struct<V: ?Sized + Serialize>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
value: &V,
|
||||||
|
) -> Result<Self::Ok, Self::Error> {
|
||||||
|
value.serialize(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_newtype_variant<V: ?Sized + Serialize>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
variant_index: u32,
|
||||||
|
_variant: &'static str,
|
||||||
|
value: &V,
|
||||||
|
) -> Result<Self::Ok, Self::Error> {
|
||||||
|
self.digest.update(&variant_index.to_be_bytes());
|
||||||
|
value.serialize(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
||||||
|
let len = len.ok_or(Error::UndefinedSequenceLength)?;
|
||||||
|
self.digest
|
||||||
|
.update(&try_into_sequence_length(len)?.to_be_bytes());
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
|
||||||
|
self.digest
|
||||||
|
.update(&try_into_sequence_length(len)?.to_be_bytes());
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_tuple_struct(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
len: usize,
|
||||||
|
) -> Result<Self::SerializeTupleStruct, Self::Error> {
|
||||||
|
self.digest
|
||||||
|
.update(&try_into_sequence_length(len)?.to_be_bytes());
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_tuple_variant(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
variant_index: u32,
|
||||||
|
_variant: &'static str,
|
||||||
|
len: usize,
|
||||||
|
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||||
|
self.digest.update(&variant_index.to_be_bytes());
|
||||||
|
self.digest
|
||||||
|
.update(&try_into_sequence_length(len)?.to_be_bytes());
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||||
|
let len = len.ok_or(Error::UndefinedSequenceLength)?;
|
||||||
|
self.digest
|
||||||
|
.update(&try_into_sequence_length(len)?.to_be_bytes());
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_struct(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
len: usize,
|
||||||
|
) -> Result<Self::SerializeStruct, Self::Error> {
|
||||||
|
self.digest
|
||||||
|
.update(&try_into_sequence_length(len)?.to_be_bytes());
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_struct_variant(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
variant_index: u32,
|
||||||
|
_variant: &'static str,
|
||||||
|
len: usize,
|
||||||
|
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||||
|
self.digest.update(&variant_index.to_be_bytes());
|
||||||
|
self.digest
|
||||||
|
.update(&try_into_sequence_length(len)?.to_be_bytes());
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_str<V: fmt::Display + ?Sized>(self, _: &V) -> Result<Self::Ok, Self::Error> {
|
||||||
|
Err(Error::CannotCollectStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_human_readable(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Update> SerializeSeq for HashingSerializer<'a, T> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn serialize_element<V: ?Sized + Serialize>(&mut self, value: &V) -> Result<Self::Ok, Error> {
|
||||||
|
value.serialize(HashingSerializer {
|
||||||
|
digest: self.digest,
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end(self) -> Result<Self::Ok, Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Update> SerializeTuple for HashingSerializer<'a, T> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn serialize_element<V: ?Sized + Serialize>(&mut self, value: &V) -> Result<Self::Ok, Error> {
|
||||||
|
value.serialize(HashingSerializer {
|
||||||
|
digest: self.digest,
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end(self) -> Result<Self::Ok, Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Update> SerializeTupleStruct for HashingSerializer<'a, T> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn serialize_field<V: ?Sized + Serialize>(&mut self, value: &V) -> Result<Self::Ok, Error> {
|
||||||
|
value.serialize(HashingSerializer {
|
||||||
|
digest: self.digest,
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end(self) -> Result<Self::Ok, Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Update> SerializeTupleVariant for HashingSerializer<'a, T> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn serialize_field<V: ?Sized + Serialize>(&mut self, value: &V) -> Result<Self::Ok, Error> {
|
||||||
|
value.serialize(HashingSerializer {
|
||||||
|
digest: self.digest,
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end(self) -> Result<Self::Ok, Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Update> SerializeMap for HashingSerializer<'a, T> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn serialize_key<K: ?Sized + Serialize>(&mut self, key: &K) -> Result<Self::Ok, Error> {
|
||||||
|
key.serialize(HashingSerializer {
|
||||||
|
digest: self.digest,
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_value<V: ?Sized + Serialize>(&mut self, value: &V) -> Result<Self::Ok, Error> {
|
||||||
|
value.serialize(HashingSerializer {
|
||||||
|
digest: self.digest,
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end(self) -> Result<Self::Ok, Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Update> SerializeStruct for HashingSerializer<'a, T> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn serialize_field<V: ?Sized + Serialize>(
|
||||||
|
&mut self,
|
||||||
|
_key: &'static str,
|
||||||
|
value: &V,
|
||||||
|
) -> Result<Self::Ok, Error> {
|
||||||
|
value.serialize(HashingSerializer {
|
||||||
|
digest: self.digest,
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end(self) -> Result<Self::Ok, Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Update> SerializeStructVariant for HashingSerializer<'a, T> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn serialize_field<V: ?Sized + Serialize>(
|
||||||
|
&mut self,
|
||||||
|
_key: &'static str,
|
||||||
|
value: &V,
|
||||||
|
) -> Result<Self::Ok, Error> {
|
||||||
|
value.serialize(HashingSerializer {
|
||||||
|
digest: self.digest,
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end(self) -> Result<Self::Ok, Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,23 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
/// Library crate for the `vanth` ECS-based database node.
|
/// Library crate for the `vanth` ECS-based database node.
|
||||||
use bevy_app::App;
|
use bevy_app::{App, Plugin};
|
||||||
use bevy_ecs::{prelude::*, query::QueryData};
|
use bevy_ecs::{prelude::*, query::QueryData};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::entity::EntityId;
|
||||||
|
|
||||||
pub mod store;
|
pub mod store;
|
||||||
pub mod entity;
|
pub mod entity;
|
||||||
|
pub mod hashing_serializer;
|
||||||
|
|
||||||
|
pub use hashing_serializer::hash;
|
||||||
|
|
||||||
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
|
pub enum Error {
|
||||||
|
Other(String),
|
||||||
|
}
|
||||||
|
|
||||||
/// A server node wrapping a Bevy App without running it.
|
/// A server node wrapping a Bevy App without running it.
|
||||||
pub struct Node {
|
pub struct Node {
|
||||||
|
@ -31,6 +42,16 @@ impl Node {
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(Debug, Deserialize, Component, Serialize)]
|
#[derive(Debug, Deserialize, Component, Serialize)]
|
||||||
|
@ -50,13 +71,81 @@ pub trait VanthTuple {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct EntityContents {
|
||||||
|
components: Vec<ComponentContents>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct ComponentContents {
|
||||||
|
id: String,
|
||||||
|
content_hash: ContentHash,
|
||||||
|
data: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Component: Serialize {
|
||||||
|
fn id() -> String;
|
||||||
|
}
|
||||||
|
|
||||||
// use a macro to implement VanthTuiple here.
|
// use a macro to implement VanthTuiple here.
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Component, Serialize)]
|
#[derive(Copy, Clone, Debug, Deserialize, Component, Serialize)]
|
||||||
pub struct ContentHash {
|
pub struct ContentHash {
|
||||||
pub hash: [u8; 32],
|
pub hash: [u8; 32],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Component, Serialize)]
|
||||||
|
pub struct Reference<T: Clone + Serialize> {
|
||||||
|
value: ReferenceValue,
|
||||||
|
_marker: PhantomData<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive( Clone, Debug, Deserialize, Component, Serialize)]
|
||||||
|
pub enum ReferenceValue {
|
||||||
|
Absent,
|
||||||
|
Retrieving(ReferenceRetrievalTask),
|
||||||
|
Present(Vec<u8>)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T: Clone + Serialize> Reference<T> {
|
||||||
|
pub async fn take() -> T {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get() -> Handle<T> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Clone, Debug, Deserialize, Serialize)]
|
||||||
|
struct ReferenceRetrievalTask {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Future for ReferenceRetrievalTask {
|
||||||
|
type Output = Vec<u8>;
|
||||||
|
|
||||||
|
fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Handle<T> {
|
||||||
|
_marker: PhantomData<T>
|
||||||
|
}
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// A trait is derivable for ECS components
|
// A trait is derivable for ECS components
|
||||||
// The components must have a content hash, not the entity. For efficiency and ergonomics. This means that a hash of each relevant component must be stored in the Vanth component of the entity, in a `HashMap` or something. The ID of the component used by Vanth should be a method on the derived trait.
|
// The components must have a content hash, not the entity. For efficiency and ergonomics. This means that a hash of each relevant component must be stored in the Vanth component of the entity, in a `HashMap` or something. The ID of the component used by Vanth should be a method on the derived trait.
|
||||||
|
|
||||||
|
pub struct VanthPlugin;
|
||||||
|
|
||||||
|
impl Plugin for VanthPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn run_reference_tasks(tasks: Query<(&ReferenceGetTask<>)>) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
#![allow(unused)]
|
|
||||||
|
|
||||||
mod parser;
|
|
||||||
mod util;
|
mod util;
|
||||||
mod vanth;
|
mod vanth;
|
||||||
|
|
||||||
|
|
|
@ -11,3 +11,20 @@ pub struct Store {
|
||||||
impl Store {
|
impl Store {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Component, Serialize)]
|
||||||
|
pub struct Cache {
|
||||||
|
size_limit_bytes: u64,
|
||||||
|
backend: Backend,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub enum Backend {
|
||||||
|
Memory,
|
||||||
|
Sqlite(Sqlite)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct Sqlite {
|
||||||
|
path: PathBuf,
|
||||||
|
}
|
||||||
|
|
28
crates/vanth/tests/reference.rs
Normal file
28
crates/vanth/tests/reference.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use vanth::{Component, Node, Reference};
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn test_store() {
|
||||||
|
// #[derive(Clone, Deserialize, Serialize)]
|
||||||
|
// struct Foo {
|
||||||
|
// bar: Reference<Bar>,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[derive(Clone, Deserialize, Serialize)]
|
||||||
|
// struct Bar {
|
||||||
|
// foo: Reference<Foo>,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl Component for Foo {
|
||||||
|
// fn id() -> String {
|
||||||
|
// "foo".into()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let node = Node::in_memory();
|
||||||
|
|
||||||
|
// let entity_id = "entity_1";
|
||||||
|
// let entity_components = (Foo { a: 5, b: 6.0 },);
|
||||||
|
|
||||||
|
// node.save("entity_1", entity_components);
|
||||||
|
// }
|
24
crates/vanth/tests/store.rs
Normal file
24
crates/vanth/tests/store.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use vanth::{Component, Node};
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn test_store() {
|
||||||
|
// #[derive(Deserialize, Serialize)]
|
||||||
|
// struct Foo {
|
||||||
|
// a: u32,
|
||||||
|
// b: f32,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl Component for Foo {
|
||||||
|
// fn id() -> String {
|
||||||
|
// "foo".into()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let node = Node::in_memory();
|
||||||
|
|
||||||
|
// let entity_id = "entity_1";
|
||||||
|
// let entity_components = (Foo { a: 5, b: 6.0 },);
|
||||||
|
|
||||||
|
// node.save("entity_1", entity_components);
|
||||||
|
// }
|
178
devenv.lock
178
devenv.lock
|
@ -1,178 +0,0 @@
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"devenv": {
|
|
||||||
"locked": {
|
|
||||||
"dir": "src/modules",
|
|
||||||
"lastModified": 1731619804,
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "devenv",
|
|
||||||
"rev": "87edaaf1dddf17fe16eabab3c8edaf7cca2c3bc2",
|
|
||||||
"treeHash": "c0c2fd8edf08b32c9da79d4bb917690dc5b126d0",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"dir": "src/modules",
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "devenv",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fenix": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"rust-analyzer-src": "rust-analyzer-src"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1731565929,
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "fenix",
|
|
||||||
"rev": "4c6c7d5088f12f57afd4ba6449f9eb168ca05620",
|
|
||||||
"treeHash": "06a361535bdfec44eb64eb02dc5628ea71b2f488",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "fenix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-compat": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1696426674,
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
|
||||||
"treeHash": "2addb7b71a20a25ea74feeaf5c2f6a6b30898ecb",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"gitignore": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"pre-commit-hooks",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1709087332,
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "gitignore.nix",
|
|
||||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
|
||||||
"treeHash": "ca14199cabdfe1a06a7b1654c76ed49100a689f9",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "gitignore.nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1716977621,
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "devenv-nixpkgs",
|
|
||||||
"rev": "4267e705586473d3e5c8d50299e71503f16a6fb6",
|
|
||||||
"treeHash": "6d9f1f7ca0faf1bc2eeb397c78a49623260d3412",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "cachix",
|
|
||||||
"ref": "rolling",
|
|
||||||
"repo": "devenv-nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-stable": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1731386116,
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "689fed12a013f56d4c4d3f612489634267d86529",
|
|
||||||
"treeHash": "8786ed18f037bad8b80b7a75c0e7b21a6769ee87",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-24.05",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-unstable": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1731531548,
|
|
||||||
"owner": "nixos",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "24f0d4acd634792badd6470134c387a3b039dace",
|
|
||||||
"treeHash": "a35f71a0fa18e0a51dfeead7b9c971ed73043752",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nixos",
|
|
||||||
"ref": "nixpkgs-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pre-commit-hooks": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": "flake-compat",
|
|
||||||
"gitignore": "gitignore",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"nixpkgs-stable": "nixpkgs-stable"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1731363552,
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "pre-commit-hooks.nix",
|
|
||||||
"rev": "cd1af27aa85026ac759d5d3fccf650abe7e1bbf0",
|
|
||||||
"treeHash": "d246c8c2f312332367d56063d2b049419880acc7",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "pre-commit-hooks.nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"devenv": "devenv",
|
|
||||||
"fenix": "fenix",
|
|
||||||
"nixpkgs": "nixpkgs",
|
|
||||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
|
||||||
"pre-commit-hooks": "pre-commit-hooks"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rust-analyzer-src": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1731342671,
|
|
||||||
"owner": "rust-lang",
|
|
||||||
"repo": "rust-analyzer",
|
|
||||||
"rev": "fc98e0657abf3ce07eed513e38274c89bbb2f8ad",
|
|
||||||
"treeHash": "7c4a6b17fbe9e655cac7d03a3c034456b8f60a1f",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "rust-lang",
|
|
||||||
"ref": "nightly",
|
|
||||||
"repo": "rust-analyzer",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
60
devenv.nix
60
devenv.nix
|
@ -1,60 +0,0 @@
|
||||||
{
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
inputs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
|
|
||||||
let
|
|
||||||
pkgs-unstable = import inputs.nixpkgs-unstable {
|
|
||||||
system = pkgs.stdenv.system;
|
|
||||||
config.allowUnfree = true;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# https://devenv.sh/basics/
|
|
||||||
env.GREET = "devenv";
|
|
||||||
|
|
||||||
# https://devenv.sh/packages/
|
|
||||||
packages = [
|
|
||||||
pkgs-unstable.git
|
|
||||||
pkgs-unstable.rustup
|
|
||||||
pkgs-unstable.code-cursor
|
|
||||||
pkgs-unstable.curl
|
|
||||||
pkgs-unstable.jq
|
|
||||||
];
|
|
||||||
|
|
||||||
# https://devenv.sh/languages/
|
|
||||||
languages.rust = {
|
|
||||||
channel = "nightly";
|
|
||||||
components = [
|
|
||||||
"cargo"
|
|
||||||
"rust-src"
|
|
||||||
"rustc"
|
|
||||||
"clippy"
|
|
||||||
];
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
enterShell = ''
|
|
||||||
rustup component add clippy
|
|
||||||
'';
|
|
||||||
|
|
||||||
enterTest = ''
|
|
||||||
echo "Running tests"
|
|
||||||
git --version | grep --color=auto "${pkgs.git.version}"
|
|
||||||
cargo clippy -- -D warnings
|
|
||||||
'';
|
|
||||||
|
|
||||||
pre-commit.hooks = {
|
|
||||||
shellcheck.enable = true;
|
|
||||||
clippy = {
|
|
||||||
enable = true;
|
|
||||||
name = "clippy";
|
|
||||||
entry = "cargo clippy -- -D warnings";
|
|
||||||
files = "\\.rs$";
|
|
||||||
language = "system";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
14
devenv.yaml
14
devenv.yaml
|
@ -1,14 +0,0 @@
|
||||||
# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json
|
|
||||||
inputs:
|
|
||||||
fenix:
|
|
||||||
url: github:nix-community/fenix
|
|
||||||
inputs:
|
|
||||||
nixpkgs:
|
|
||||||
follows: nixpkgs
|
|
||||||
nixpkgs:
|
|
||||||
url: github:cachix/devenv-nixpkgs/rolling
|
|
||||||
nixpkgs-unstable:
|
|
||||||
url: github:nixos/nixpkgs/nixpkgs-unstable
|
|
||||||
|
|
||||||
allowUnfree: true
|
|
||||||
|
|
130
flake.lock
generated
Normal file
130
flake.lock
generated
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"crane": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1754112045,
|
||||||
|
"narHash": "sha256-ZgsUm1brDXTPSLK5kY5rkQkqqr2oM1Pd20oirH3Sgkk=",
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"rev": "b91f27c93d9d414a21092d85ed5ac9def8624b91",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fenix": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1754116698,
|
||||||
|
"narHash": "sha256-2cMDogXcqv975o191g0/6ZM0UolJ2X0ChuuLaNKbNAM=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"rev": "acdb7d8af407ea8aee21b028dc58b4bc51a7849a",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-parts": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1754091436,
|
||||||
|
"narHash": "sha256-XKqDMN1/Qj1DKivQvscI4vmHfDfvYR2pfuFOJiCeewM=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "67df8c627c2c39c41dbec76a1f201929929ab0bd",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1753939845,
|
||||||
|
"narHash": "sha256-K2ViRJfdVGE8tpJejs8Qpvvejks1+A4GQej/lBk5y7I=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "94def634a20494ee057c76998843c015909d6311",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs-lib": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1753579242,
|
||||||
|
"narHash": "sha256-zvaMGVn14/Zz8hnp4VWT9xVnhc8vuL3TStRqwk22biA=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs.lib",
|
||||||
|
"rev": "0f36c44e01a6129be94e3ade315a5883f0228a6e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs.lib",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1754060105,
|
||||||
|
"narHash": "sha256-di5L6e5Iiv+oegS07j9h23FdqEpXn0ZQqMlDOEMw1EY=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "e7eabdc701d7dbb810fd91a97ec358caa4c1fc50",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"crane": "crane",
|
||||||
|
"fenix": "fenix",
|
||||||
|
"flake-parts": "flake-parts",
|
||||||
|
"nixpkgs": "nixpkgs_2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-analyzer-src": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1753974682,
|
||||||
|
"narHash": "sha256-Ya4Ecj8JaKkapgYCCybzZBcypXpblhuG0hVDzdy2zyo=",
|
||||||
|
"owner": "rust-lang",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"rev": "68e7ec90bf29c9b17d0dcdb3358de5dee7f4afb5",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "rust-lang",
|
||||||
|
"ref": "nightly",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
117
flake.nix
Normal file
117
flake.nix
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
|
crane.url = "github:ipetkov/crane";
|
||||||
|
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||||
|
fenix.url = "github:nix-community/fenix";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs =
|
||||||
|
inputs@{ flake-parts, ... }:
|
||||||
|
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||||
|
systems = [
|
||||||
|
"aarch64-linux"
|
||||||
|
"aarch64-darwin"
|
||||||
|
"x86_64-darwin"
|
||||||
|
"x86_64-linux"
|
||||||
|
];
|
||||||
|
|
||||||
|
perSystem =
|
||||||
|
{ pkgs, system, ... }:
|
||||||
|
let
|
||||||
|
rustToolchain = inputs.fenix.packages.${system}.combine ([
|
||||||
|
(inputs.fenix.packages.${system}.complete.withComponents [
|
||||||
|
"cargo"
|
||||||
|
"clippy"
|
||||||
|
"rust-src"
|
||||||
|
"rustc"
|
||||||
|
"rustfmt"
|
||||||
|
])
|
||||||
|
inputs.fenix.packages.${system}.complete.rust-analyzer
|
||||||
|
inputs.fenix.packages.${system}.targets.wasm32-unknown-unknown.latest.rust-std
|
||||||
|
]);
|
||||||
|
craneLib = (inputs.crane.mkLib pkgs).overrideToolchain rustToolchain;
|
||||||
|
|
||||||
|
packages =
|
||||||
|
with pkgs;
|
||||||
|
[
|
||||||
|
dbus
|
||||||
|
libssh2
|
||||||
|
makeWrapper
|
||||||
|
openssl
|
||||||
|
openssl.dev
|
||||||
|
pkg-config
|
||||||
|
]
|
||||||
|
++ lib.optionals stdenv.isLinux [
|
||||||
|
systemd
|
||||||
|
patchelf
|
||||||
|
]
|
||||||
|
++ lib.optionals stdenv.isDarwin [
|
||||||
|
libiconv
|
||||||
|
darwin.apple_sdk.frameworks.Security
|
||||||
|
darwin.apple_sdk.frameworks.SystemConfiguration
|
||||||
|
darwin.apple_sdk.frameworks.AudioUnit
|
||||||
|
darwin.apple_sdk.frameworks.CoreAudio
|
||||||
|
];
|
||||||
|
|
||||||
|
commonArgs = {
|
||||||
|
src = ./.;
|
||||||
|
strictDeps = true;
|
||||||
|
nativeBuildInputs = packages;
|
||||||
|
buildInputs = packages;
|
||||||
|
|
||||||
|
CARGO_BUILD_INCREMENTAL = "false";
|
||||||
|
RUST_BACKTRACE = "1";
|
||||||
|
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath packages;
|
||||||
|
};
|
||||||
|
|
||||||
|
craneArgs = {
|
||||||
|
};
|
||||||
|
|
||||||
|
cargoArtifacts = craneLib.buildDepsOnly (
|
||||||
|
commonArgs
|
||||||
|
// craneArgs
|
||||||
|
// {
|
||||||
|
pname = "vanth-deps";
|
||||||
|
version = "0.1.0";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
vanth = craneLib.buildPackage (
|
||||||
|
commonArgs
|
||||||
|
// craneArgs
|
||||||
|
// {
|
||||||
|
inherit cargoArtifacts;
|
||||||
|
pname = "vanth";
|
||||||
|
version = "0.1.0";
|
||||||
|
cargoExtraArgs = "--package vanth_cli";
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
if [ ! -f "$out/bin/vanth" ]; then
|
||||||
|
echo "Error: vanth binary not found in $out/bin/"
|
||||||
|
ls -la $out/bin/
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
''
|
||||||
|
+ pkgs.lib.optionalString pkgs.stdenv.isLinux ''
|
||||||
|
patchelf $out/bin/vanth --set-rpath ${pkgs.lib.makeLibraryPath packages}
|
||||||
|
wrapProgram $out/bin/vanth --set LD_LIBRARY_PATH "${pkgs.lib.makeLibraryPath packages}"
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
packages = rec {
|
||||||
|
inherit vanth;
|
||||||
|
default = vanth;
|
||||||
|
};
|
||||||
|
|
||||||
|
devShells.default = craneLib.devShell {
|
||||||
|
inputsFrom = [ vanth ];
|
||||||
|
packages = packages;
|
||||||
|
RUST_SRC_PATH = "${rustToolchain}/lib/rustlib/src/rust/library";
|
||||||
|
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath packages;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue