📝 cli, vanth, meta, flake: Simplify dependencies, add meta crate, and improve docs

- Removed dependencies `sqlx` and `bevy_app` to simplify the project.
- Added new crate `vanth_meta` for generating example SVGs.
- Updated CLI tests to use `assert_cmd` for better test assertions.
- Enhanced README with comprehensive library and CLI usage documentation.
- Modified `Store::write` in `vanth` crate to return the content hash.
- Set `checkPhase` to empty in Nix flake configuration.
This commit is contained in:
Markus Scully 2025-08-11 12:59:29 +03:00
parent 1001819e4c
commit ff57ee8deb
Signed by: mascully
GPG key ID: 93CA5814B698101C
13 changed files with 426 additions and 1158 deletions

View file

@ -2,6 +2,11 @@
name = "vanth_cli"
version.workspace = true
edition.workspace = true
default-run = "vanth"
[[bin]]
name = "vanth"
path = "src/main.rs"
[dependencies]
clap.workspace = true
@ -10,6 +15,7 @@ serde_json.workspace = true
vanth = { path = "../vanth" }
tracing.workspace = true
tracing-subscriber.workspace = true
assert_cmd.workspace = true
[dev-dependencies]
tempfile = { workspace = true }

View file

@ -3,6 +3,7 @@ use clap::Parser;
mod cli;
pub use cli::*;
use tracing::trace;
fn main() {
tracing_subscriber::fmt()

View file

@ -1,6 +1,6 @@
use assert_cmd::Command;
use std::io::Write;
use std::path::Path;
use std::process::Command;
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
@ -8,33 +8,14 @@ use tempfile::tempdir;
use vanth::{ContentHash, Vanth, hash as vanth_hash};
fn run_vanth(args: &[&str], input: Option<&str>) -> (String, String, i32) {
let mut cmd = Command::new(env!("CARGO_BIN_EXE_vanth_cli"));
cmd.args(args);
if let Some(inp) = input {
let mut child = cmd
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap();
{
let stdin = child.stdin.as_mut().unwrap();
stdin.write_all(inp.as_bytes()).unwrap();
}
let output = child.wait_with_output().unwrap();
(
String::from_utf8(output.stdout).unwrap(),
String::from_utf8(output.stderr).unwrap(),
output.status.code().unwrap(),
)
} else {
let output = cmd.output().unwrap();
(
String::from_utf8(output.stdout).unwrap(),
String::from_utf8(output.stderr).unwrap(),
output.status.code().unwrap(),
)
}
let mut cmd = Command::cargo_bin("vanth").unwrap();
let output = cmd.args(args).write_stdin(input.unwrap_or("")).output().unwrap();
(
String::from_utf8(output.stdout).unwrap(),
String::from_utf8(output.stderr).unwrap(),
output.status.code().unwrap(),
)
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Vanth)]
@ -72,7 +53,7 @@ fn test_write_get() {
panic!("{}", stderr);
}
let hash = stdout.trim();
println!("x{}x", hash);
println!("{}", hash);
let (stdout, stderr, exit) = run_vanth(&["get", "--db", &db_path, "--ty", &Foo::ty().to_string(), &hash], None);
if exit != 0 {

6
crates/meta/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "vanth_meta"
version.workspace = true
edition.workspace = true
[dependencies]

181
crates/meta/src/main.rs Normal file
View file

@ -0,0 +1,181 @@
//!
use std::f32::consts::PI;
#[derive(Debug, Clone, Copy, PartialEq)]
struct Point {
x: f32,
y: f32,
}
impl Point {
fn add_axis_1(&self, amount: f32) -> Self {
let angle = 4.0 / 6.0 * PI;
(self.x + amount * angle.cos(), self.y + amount * angle.sin()).into()
}
fn add_axis_2(&self, amount: f32) -> Self {
let angle = 2.0 / 6.0 * PI;
(self.x + amount * angle.cos(), self.y + amount * angle.sin()).into()
}
fn to_string(&self) -> String {
format!("{},{}", self.x, self.y)
}
}
impl std::ops::Add for Point {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Point {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
}
impl std::ops::AddAssign for Point {
fn add_assign(&mut self, rhs: Self) {
self.x += rhs.x;
self.y += rhs.y;
}
}
impl std::ops::Sub for Point {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Point {
x: self.x - rhs.x,
y: self.y - rhs.y,
}
}
}
impl std::ops::Mul<f32> for Point {
type Output = Self;
fn mul(self, rhs: f32) -> Self::Output {
Point {
x: self.x * rhs,
y: self.y * rhs,
}
}
}
impl std::ops::Div<f32> for Point {
type Output = Self;
fn div(self, rhs: f32) -> Self::Output {
Point {
x: self.x / rhs,
y: self.y / rhs,
}
}
}
impl std::ops::Neg for Point {
type Output = Self;
fn neg(self) -> Self::Output {
Point { x: -self.x, y: -self.y }
}
}
impl From<(f32, f32)> for Point {
fn from((x, y): (f32, f32)) -> Self {
Point { x, y }
}
}
impl From<Point> for (f32, f32) {
fn from(pt: Point) -> Self {
(pt.x, pt.y)
}
}
fn axonometric(x: f32, y: f32) -> Point {
let dx = (2.0 / 6.0 * PI).cos();
let dy = (2.0 / 6.0 * PI).sin();
(50.0 + x * dx + y * dy, 50.0 + x * -dy + y * dx).into()
}
fn main() {
let axis_1_dx = (2.0 / 6.0 * PI).cos();
let axis_1_dy = (2.0 / 6.0 * PI).sin();
let axis_2_dx = (4.0 / 6.0 * PI).cos();
let axis_2_dy = (4.0 / 6.0 * PI).sin();
// let mut point: Point = (20.0, 20.0).into();
// let mut poly_1 = vec![point];
// for &diff in &[
// (axis_1_dx * 10.0, axis_1_dy * 10.0),
// (10.0, 0.0),
// (axis_1_dx * -10.0, axis_1_dy * -10.0),
// ] {
// point += <_ as Into<Point>>::into(diff);
// poly_1.push(point);
// }
// let mut point: Point = (20.0 + axis_1_dx * 60.0, 20.0).into();
// let mut poly_2 = vec![point];
// for &diff in &[
// (axis_2_dx * 10.0, axis_2_dy * 10.0),
// (10.0, 0.0),
// (axis_2_dx * -10.0, axis_2_dy * -10.0),
// ] {
// point += <_ as Into<Point>>::into(diff);
// poly_2.push(point);
// }
// let mut point: Point = (23.0 + axis_1_dx * 3.0, 20.0 + axis_1_dy * 3.0).into();
// let mut poly_3 = vec![point];
// for &diff in &[
// (axis_1_dx * 30.0, axis_1_dy * 30.0),
// (axis_2_dx * -30.0, axis_2_dy * -30.0),
// (-10.0, 0.0),
// (axis_2_dx * 10.0, axis_2_dy * 10.0),
// (axis_1_dx * -10.0, axis_1_dy * -10.0),
// ] {
// point += <_ as Into<Point>>::into(diff);
// poly_3.push(point);
// }
// let mut poly_4 = vec![
// (20.0 + axis_1_dx * 25.0, 20.0 + axis_1_dy * 25.0).into(),
// (50.0 - axis_2_dx * 25.0, 20.0 + axis_1_dy * 25.0).into(),
// (20.0 + axis_1_dx * 25.0, 25.0 + axis_1_dy * 25.0).into(),
// ];
let poly_1 = vec![
axonometric(10.0, 10.0),
axonometric(10.0, 20.0),
axonometric(20.0, 20.0),
];
let poly_2 = vec![];
let poly_3 = vec![];
let poly_4 = vec![];
let mut svg = String::new();
svg.push_str(
r##"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 128 128">
<rect width="128" height="128" fill="#ffffff"/>
"##,
);
let blue = "#0b5cff";
let black = "#000000";
for (color, points) in &[(blue, poly_1), (blue, poly_2), (blue, poly_4), (black, poly_3)] {
svg.push_str(&format!(r##"<g fill="{}">"##, color));
svg.push_str(r##"<polygon points=""##);
svg.push_str(&points.iter().map(Point::to_string).collect::<Vec<_>>().join(" "));
svg.push_str(r##""/>"##);
svg.push_str(r##"</g>"##);
}
svg.push_str(r##"</svg>"##);
println!("{}", svg);
}

View file

@ -5,18 +5,22 @@ edition.workspace = true
[lib]
path = "src/lib.rs"
doctest = false
[dependencies]
bevy_app.workspace = true
bevy_ecs.workspace = true
digest.workspace = true
serde.workspace = true
serde_json.workspace = true
blake3.workspace = true
vanth_derive = { path = "../vanth_derive" }
sqlx.workspace = true
rusqlite.workspace = true
tracing.workspace = true
[dev-dependencies]
tempfile = { workspace = true }
[[example]]
name = "simple"
path = "examples/simple.rs"

View file

@ -0,0 +1,12 @@
use serde::{Deserialize, Serialize};
use vanth::{hash, Vanth};
#[derive(Clone, Debug, Deserialize, Serialize, Vanth)]
struct Foo {
value: i32,
}
fn main() {
let x = "hello";
println!("Hash: {:?}", hash(&x).hex());
}

View file

@ -1,7 +1,7 @@
#![doc = include_str!("../../../README.md")]
use std::marker::PhantomData;
/// Library crate for the `vanth` ECS-based database node.
use bevy_app::{App, Plugin};
use bevy_ecs::{prelude::*, query::QueryData};
use serde::{Deserialize, Serialize, de::DeserializeOwned};
@ -20,27 +20,23 @@ pub enum Error {
Other(String),
}
/// A server node wrapping a Bevy App without running it.
/// A Vanth server.
pub struct Node {
app: App,
}
impl Node {
/// Creates a new server node with an empty Bevy App.
pub fn new() -> Self {
let app = App::new();
Node { app }
Self { }
}
/// Returns the number of entities currently in the world.
pub fn entity_count(&self) -> usize {
todo!()
// Query for no components returns one item per entity.
// self.app.world().entities().len()
}
// TODO
pub fn run() {}
pub fn run() {
todo!()
}
pub fn save(entity_id: impl Into<EntityId>) -> Result<()> {
// TODO
@ -171,17 +167,6 @@ 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<>)>) {

View file

@ -115,10 +115,11 @@ impl Store {
Ok(results)
}
pub fn write<T: Vanth + Serialize>(&mut self, value: &T) -> Result<()> {
pub fn write<T: Vanth + Serialize>(&mut self, value: &T) -> Result<ContentHash> {
let content_hash = hash(&value);
let data = serde_json::to_vec(&value)?;
self.backend.write(T::ty(), content_hash, data)
self.backend.write(T::ty(), content_hash, data)?;
Ok(content_hash)
}
pub fn write_raw(&mut self, ty: Ty, content_hash: ContentHash, content: Vec<u8>) -> Result<()> {