♻️🍱💩👷 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.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.6"
|
||||
|
@ -238,6 +244,29 @@ dependencies = [
|
|||
"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]]
|
||||
name = "bumpalo"
|
||||
version = "3.19.0"
|
||||
|
@ -250,6 +279,15 @@ version = "1.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.1"
|
||||
|
@ -272,6 +310,12 @@ dependencies = [
|
|||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.2.0"
|
||||
|
@ -293,6 +337,16 @@ version = "0.8.20"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "ctrlc"
|
||||
version = "3.4.7"
|
||||
|
@ -324,6 +378,17 @@ dependencies = [
|
|||
"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]]
|
||||
name = "disqualified"
|
||||
version = "1.0.0"
|
||||
|
@ -395,6 +460,16 @@ dependencies = [
|
|||
"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]]
|
||||
name = "getrandom"
|
||||
version = "0.3.3"
|
||||
|
@ -657,6 +732,12 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.10"
|
||||
|
@ -693,6 +774,12 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.104"
|
||||
|
@ -756,6 +843,12 @@ version = "1.0.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
|
@ -786,6 +879,8 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"bevy_app",
|
||||
"bevy_ecs",
|
||||
"blake3",
|
||||
"digest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
@ -801,6 +896,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.14.2+wasi-0.2.4"
|
||||
|
|
|
@ -9,5 +9,8 @@ edition = "2024"
|
|||
[workspace.dependencies]
|
||||
bevy_app = "0.16.1"
|
||||
bevy_ecs = "0.16.1"
|
||||
bitcode = "0.6.6"
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
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]
|
||||
bevy_app.workspace = true
|
||||
bevy_ecs.workspace = true
|
||||
digest.workspace = true
|
||||
serde.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::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
|
||||
#[derive(Clone, Copy, Serialize, Deserialize)]
|
||||
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;
|
||||
|
||||
/// 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 serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::entity::EntityId;
|
||||
|
||||
pub mod store;
|
||||
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.
|
||||
pub struct Node {
|
||||
|
@ -31,6 +42,16 @@ impl Node {
|
|||
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)]
|
||||
|
@ -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.
|
||||
|
||||
#[derive(Debug, Deserialize, Component, Serialize)]
|
||||
#[derive(Copy, Clone, Debug, Deserialize, Component, Serialize)]
|
||||
pub struct ContentHash {
|
||||
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:
|
||||
// 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.
|
||||
|
||||
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 vanth;
|
||||
|
||||
|
|
|
@ -11,3 +11,20 @@ pub struct 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