totally sync variables
bendn 2023-07-13
commit ca52d26
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock47
-rw-r--r--Cargo.toml11
-rw-r--r--README.md1
-rw-r--r--src/lib.rs109
5 files changed, 169 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..ddcdbeb
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,47 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "itoa"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a"
+
+[[package]]
+name = "paste"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4b27ab7be369122c218afc2079489cdcb4b517c0a3fc386ff11e1fedfcc2b35"
+
+[[package]]
+name = "ryu"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9"
+
+[[package]]
+name = "serde"
+version = "1.0.171"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9"
+
+[[package]]
+name = "serde_json"
+version = "1.0.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f1e14e89be7aa4c4b78bdbdc9eb5bf8517829a600ae8eaa39a6e1d960b5185c"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "totally-sync-variable"
+version = "0.1.0"
+dependencies = [
+ "paste",
+ "serde",
+ "serde_json",
+]
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..bfae105
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "totally-sync-variable"
+version = "0.1.0"
+edition = "2021"
+authors = ["bendn <[email protected]>"]
+homepage = "https://github.com/bend-n/totally-sync-variable"
+
+[dependencies]
+paste = "1.0"
+serde = "1"
+serde_json = "1.0"
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..cff8a58
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# totally sync variable
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..51fdcef
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,109 @@
+//! # the totally sync variables.
+//! ## features
+//! - make any variable, pass it round!
+//! - scoping? who needs it!
+//! - only one mutable reference? pshaw!
+//! - any numer of mutable references are allowed.
+//
+//! ## data races?
+//! dont know what your talking about.
+//!
+//! its *fearless concurrency* remember? and theres no unsafe code!
+//!
+//! besides, miri says its fiine.
+#![deny(unsafe_code)]
+#![allow(dead_code)]
+use serde::{de::DeserializeOwned, Serialize};
+use std::fs;
+use std::io::{BufReader, BufWriter};
+use std::marker::PhantomData;
+use std::ops::*;
+use std::path::Path;
+
+/// a variable stored on the filesystem (very secure 🔐)
+#[doc(hidden)]
+pub struct Var<T>(&'static str, PhantomData<T>);
+
+impl<T> Var<T> {
+ /// create a var
+ pub fn new(name: &'static str) -> Self {
+ Self(name, PhantomData::default())
+ }
+}
+
+impl<T: Serialize> Var<T> {
+ /// interior mutability!
+ /// ```
+ /// # use totally_sync_variable::*;
+ /// let x = def!(x = 5u8);
+ /// x.set(&3u8);
+ /// ```
+ pub fn set(&self, v: &T) {
+ let f = BufWriter::new(
+ fs::File::create(Path::new("/tmp/").join(self.0)).expect("become linux!"),
+ );
+ serde_json::to_writer(f, v).unwrap();
+ }
+}
+
+impl<T: DeserializeOwned> Var<T> {
+ /// procure the stored variable
+ /// ```
+ /// # use totally_sync_variable::*;
+ /// let y = def!(y = 5u8);
+ /// assert_eq!(y.get(), 5u8);
+ /// ```
+ pub fn get(&self) -> T {
+ let f = BufReader::new(fs::File::open(Path::new("/tmp/").join(self.0)).expect("oh no"));
+ serde_json::from_reader(f).unwrap()
+ }
+}
+
+macro_rules! op {
+ ($op: ident, $char: tt) => {paste::paste! {
+ impl<T: [<$op>]<T, Output = T> + Clone + DeserializeOwned + Serialize> [<$op Assign>] for Var<T> {
+ fn [<$op:lower _assign>](&mut self, rhs: Self) {
+ self.set(&(self.get().clone() $char rhs.get().clone()));
+ }
+ }
+ }};
+}
+
+op!(Add, +);
+op!(Sub, -);
+op!(Mul, *);
+op!(Div, /);
+op!(BitAnd, &);
+op!(BitOr, |);
+op!(BitXor, ^);
+op!(Shl, <<);
+op!(Shr, >>);
+
+#[macro_export]
+/// lil macro to define variables.
+macro_rules! def {
+ ($name:ident = $value:expr) => {{
+ let v = $crate::Var::new(stringify!($name));
+ v.set(&$value);
+ v
+ }};
+}
+
+#[macro_export]
+/// macro to reference variables from anywhere.
+macro_rules! refer {
+ ($name:ident) => {
+ $crate::Var::new(stringify!($name)).get()
+ };
+}
+
+#[test]
+fn it_works() {
+ {
+ let mut x = def!(x = 4u8);
+ x += def!(tmp = 4u8);
+ assert_eq!(x.get(), 8);
+ }
+ let v: u8 = refer!(x);
+ assert_eq!(v, 8)
+}