diff --git a/.github/ISSUE_TEMPLATE/SCIP.md b/.github/ISSUE_TEMPLATE/SCIP.md index 1a277a95..eebafdbc 100644 --- a/.github/ISSUE_TEMPLATE/SCIP.md +++ b/.github/ISSUE_TEMPLATE/SCIP.md @@ -1,10 +1,10 @@ --- -name: Improvement Proposal -about: This template aides in the creation of ecosystem improvement proposals indicated by the prefix SCIP- +about: A template outlining the structure of a formal proposal for a project improvement. +assignees: + - 'FL03 (https://github.com/FL03)' +name: Project Improvement Proposals +labels: ['scip'] title: 'SCIP-' -labels: '' -assignees: '' - --- **Abstract** @@ -18,3 +18,5 @@ A clear and concise description of any alternative solutions or features you've **Discussion** Add any other context or screenshots about the feature request here. + +### Additional Resources \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f8752176..0456ea2f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,32 +3,28 @@ updates: - package-ecosystem: cargo directory: / schedule: - interval: daily + interval: weekly - package-ecosystem: github-actions directory: / schedule: - interval: daily + interval: weekly - package-ecosystem: cargo directory: /actors schedule: - interval: daily + interval: weekly - package-ecosystem: cargo directory: /core schedule: - interval: daily + interval: weekly - package-ecosystem: cargo directory: /derive schedule: - interval: daily + interval: weekly - package-ecosystem: cargo directory: /macros schedule: - interval: daily + interval: weekly - package-ecosystem: cargo directory: /scsys schedule: - interval: daily - - package-ecosystem: cargo - directory: /stores - schedule: - interval: daily + interval: weekly diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 3a17c007..f6e706d2 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -7,15 +7,10 @@ concurrency: on: pull_request: branches: [ main ] - push: - branches: [ main ] - tags: [ nightly*, v*.*.* ] release: types: [ created ] repository_dispatch: types: [ clippy ] - schedule: - - cron: 30 21 * * 0 # Every Sunday at 9:30PM UTC workflow_dispatch: permissions: diff --git a/.github/workflows/crates.yml b/.github/workflows/crates.yml index f9090de2..babb5dc8 100644 --- a/.github/workflows/crates.yml +++ b/.github/workflows/crates.yml @@ -9,31 +9,26 @@ env: on: release: - types: [created] + types: [ created ] repository_dispatch: - types: [publish] + types: [ crates-io ] workflow_dispatch: jobs: core: name: Publish (core) runs-on: ubuntu-latest - strategy: - matrix: - package: [ core ] - env: - PACKAGE_NAME: ${{ github.event.repository.name }}-${{ matrix.package }} steps: - uses: actions/checkout@v4 - - name: Publish (${{ env.PACKAGE_NAME }}) - run: cargo publish --all-features -v -p ${{ env.PACKAGE_NAME }} --token ${{ secrets.CARGO_REGISTRY_TOKEN }} + - name: publish + run: cargo publish --all-features -v -p ${{ github.event.repository.name }}-core --token ${{ secrets.CARGO_REGISTRY_TOKEN }} features: name: Publish (features) needs: core runs-on: ubuntu-latest strategy: matrix: - package: [ actors, derive, macros, stores ] + package: [ actors, derive, macros, ] env: PACKAGE_NAME: ${{ github.event.repository.name }}-${{ matrix.package }} steps: @@ -41,12 +36,10 @@ jobs: - name: Publish (${{ env.PACKAGE_NAME }}) run: cargo publish --all-features -v -p ${{ env.PACKAGE_NAME }} --token ${{ secrets.CARGO_REGISTRY_TOKEN }} sdk: - env: - PACKAGE_NAME: ${{ github.event.repository.name }} name: Publish (sdk) needs: features runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Publish (${{ env.PACKAGE_NAME }}) - run: cargo publish --all-features -v -p ${{ env.PACKAGE_NAME }} --token ${{ secrets.CARGO_REGISTRY_TOKEN }} + - name: publish + run: cargo publish --all-features -v -p ${{ github.event.repository.name }} --token ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index fcd74841..325eb456 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -8,15 +8,12 @@ env: CARGO_TERM_COLOR: always on: - push: + pull_request: branches: [ main ] - tags: [ nightly*, v*.*.* ] release: types: [ created ] repository_dispatch: types: [ rust ] - schedule: - - cron: 30 21 * * 0 # Every Sunday at 9:30pm UTC workflow_dispatch: jobs: @@ -45,29 +42,23 @@ jobs: target/release key: ${{ matrix.toolchain }}-${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} test: - name: Test + name: Test (workspace) needs: [ builder ] strategy: matrix: + flags: [ --no-default-features, --all-features ] toolchain: [ stable, nightly ] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: setup (langspace) - run: | - rustup update - rustup default ${{ matrix.toolchain }} - - name: Test - run: cargo test --all -F full --release -v + - run: rustup default ${{ matrix.toolchain }} && rustup update + - name: ${{ matrix.flags }} + run: cargo test ${{ matrix.flags }} -r -v --workspace bench: name: Benchmark needs: [ builder ] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: setup (langspace) - run: | - rustup update - rustup default nightly - - name: Bench - run: cargo bench --all -F full -v + - run: rustup default nightly && rustup update + - run: cargo bench --all-features -v --workspace diff --git a/.gitignore b/.gitignore index d56a6360..d77e5ac3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,61 +1,12 @@ -# Config -**/config.* -**/*.config.* -**/*.env -**/*.env.* -# Directories -**/__pycache__/ -**/__sapper__/ - -**/.DS_STORE/ -**/.artifacts/data/ -**/.cache/ -**/.docker/data/ -**/.idea/ -**/.pytest_cache/ -**/.svelte-kit/ -**/.vscode/ - -**/artifacts/ -**/build/ -**/debug/ -**/dist/ -**/env/ -**/node_modules/ +### Rust **/target/ -**/venv/ - -# File Extensions -**/*.bk -**/*.bk.* - -**/*.csv -**/*.csv.* - -**/*.db -**/*.db.* -**/*.db-*.* +**/Cargo.lock -**/*.lock -**/*.lock.* - -**/*-lock.* - -**/*.log -**/*.log.* - -**/*.whl -**/*.whl.* - -**/*.zip -**/*.zip.* +**/*.bk +**/*.bk-* -# Exceptions -!**/.circleci/config.* -!**/default.config.* -!**/*.env.example -!**/*.config.js -!**/*.config.cjs +*-log.* +**/log.* diff --git a/Cargo.toml b/Cargo.toml index e3110218..f0aa3afc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,40 +1,37 @@ [workspace.package] authors = ["FL03 (https://github.com/FL03)", "Scattered-Systems (https://github.com/scattered-systems)"] categories = [] -description = "scsys lays the foundation for the Scattered-Systems ecosystem, delivering critical primitives throughout" +description = "scsys is a collection of primitives and utilities for use throughout the ecosystem." edition = "2021" homepage = "https://github.com/scattered-systems/scsys/wiki" keywords = ["blockchain", "primitives", "scsys"] license = "Apache-2.0" readme = "README.md" repository = "https://github.com/scattered-systems/scsys" -version = "0.2.1" - -[workspace.dependencies] -paste = "1" -smart-default = "0.7" -strum = { features = ["derive"], version = "0.26" } +version = "0.2.2" [workspace] default-members = [ "scsys", ] -exclude = [ - "examples/*", -] +exclude = [] members = [ "actors", "core", "derive", "macros", - "scsys", - "stores", + "scsys", ] resolver = "2" +[workspace.dependencies] +paste = "1" +smart-default = "0.7" +strum = { default-features = false, features = ["derive"], version = "0.26" } + [profile.dev] codegen-units = 256 debug = true diff --git a/actors/Cargo.toml b/actors/Cargo.toml index b748f4df..8f92755f 100644 --- a/actors/Cargo.toml +++ b/actors/Cargo.toml @@ -1,5 +1,6 @@ [package] authors.workspace = true +build = "build.rs" categories.workspace = true description.workspace = true edition.workspace = true @@ -22,18 +23,16 @@ full = [ "tokio" ] -serde = [ - "dep:serde", - "serde-ext", - "scsys-core/serde", -] +# *** [FF] Dependencies *** -serde-ext = [ - "dep:serde_json", +alloc = [ + "scsys-core/alloc", + "serde?/alloc", ] -std = [ - "scsys-core/std", +serde = [ + "dep:serde", + "scsys-core/serde", ] tokio = [ @@ -45,12 +44,21 @@ tokio-ext = [ "tokio/sync", ] +# *** [FF] Environments *** + +std = [ + "futures/std", + "scsys-core/std", + "serde?/std", + "strum/std", +] + wasi = [ - "scsys-core/wasi" + "scsys-core/wasi", ] wasm = [ - "scsys-core/wasm" + "scsys-core/wasm", ] [lib] @@ -61,19 +69,30 @@ test = true [dependencies] async-trait = "0.1" -futures = "0.3" glob = "0.3" paste.workspace = true -serde = { optional = true, features = ["derive"], version = "1" } -serde_json = { optional = true, version = "1" } smart-default.workspace = true strum.workspace = true -tokio = { optional = true, version = "1" } + +[dependencies.futures] +default-features = false +version = "0.3" [dependencies.scsys-core] +default-features = false path = "../core" -version = "0.2.1" -# version = "0.2.1-nightly" +version = "0.2.2" +# version = "0.2.2-nightly" + +[dependencies.serde] +default-features = false +features = ["derive"] +optional = true +version = "1" + +[dependencies.tokio] +optional = true +version = "1" [dev-dependencies] diff --git a/actors/build.rs b/actors/build.rs new file mode 100644 index 00000000..940a4ce4 --- /dev/null +++ b/actors/build.rs @@ -0,0 +1,8 @@ +/* + Appellation: build + Contrib: FL03 +*/ + +fn main() { + println!("cargo::rustc-check-cfg=cfg(no_std)"); +} diff --git a/actors/src/actor.rs b/actors/src/actor.rs new file mode 100644 index 00000000..79a34936 --- /dev/null +++ b/actors/src/actor.rs @@ -0,0 +1,11 @@ +/* + Appellation: actor + Creator: FL03 +*/ + +pub mod engine; + +pub trait Actor { + type Ctx; + type Engine; +} diff --git a/actors/src/actor/engine.rs b/actors/src/actor/engine.rs new file mode 100644 index 00000000..d28fbb2e --- /dev/null +++ b/actors/src/actor/engine.rs @@ -0,0 +1,4 @@ +/* + Appellation: engine + Creator: FL03 +*/ diff --git a/actors/src/lib.rs b/actors/src/lib.rs index e80558fb..d8607992 100644 --- a/actors/src/lib.rs +++ b/actors/src/lib.rs @@ -4,15 +4,17 @@ */ //! # Actors //! -//! -#[cfg(not(feature = "std"))] +//! This library seeks to provide a suite of tools for creating and managing actors in Rust. +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "alloc")] extern crate alloc; extern crate scsys_core as scsys; -pub use self::{direction::*, traits::*}; +pub use self::{actor::*, traits::*}; -pub(crate) mod direction; +pub(crate) mod actor; #[macro_use] pub(crate) mod macros; @@ -24,7 +26,7 @@ pub mod traits; pub type Job = Box; pub mod prelude { - pub use crate::direction::*; + pub use crate::actor::*; pub use crate::messages::*; pub use crate::power::*; pub use crate::states::prelude::*; diff --git a/actors/src/messages/message.rs b/actors/src/messages/message.rs index 27401994..0aa7dd18 100644 --- a/actors/src/messages/message.rs +++ b/actors/src/messages/message.rs @@ -3,11 +3,9 @@ Contrib: FL03 */ use scsys::prelude::{AtomicId, Timestamp}; -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; -#[cfg_attr(feature = "serde", derive(Deserialize, Serialize,))] #[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct Message { id: AtomicId, data: Option, @@ -15,48 +13,74 @@ pub struct Message { } impl Message { - pub fn new(data: Option) -> Self { + pub fn new() -> Self { Self { id: AtomicId::new(), - data, + data: None, ts: Timestamp::now(), } } - pub fn content(&self) -> Option<&T> { + pub fn clear(&mut self) { + self.on_update(); + self.data = None; + } + + pub fn data(&self) -> Option<&T> { self.data.as_ref() } + pub fn data_mut(&mut self) -> Option<&mut T> { + self.data.as_mut() + } + pub fn id(&self) -> usize { *self.id } + pub fn set_data(&mut self, data: Option) { + self.on_update(); + self.data = data; + } + pub fn timestamp(&self) -> Timestamp { self.ts } + + pub fn with_data(mut self, data: T) -> Self { + self.on_update(); + self.data = Some(data); + self + } + + fn on_update(&mut self) { + self.ts = Timestamp::now(); + } } -impl std::fmt::Display for Message +impl core::fmt::Display for Message where - T: std::fmt::Display, + T: core::fmt::Display, { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - if let Some(data) = self.content() { - return write!(f, "Timestamp: {}\n{}", self.ts, data,); + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + if let Some(data) = self.data() { + return write!(f, "{}", data); } - write!(f, "Timestamp: {}", self.ts) + write!(f, "{}", self.timestamp()) } } impl From> for Message { fn from(data: Option) -> Self { - Self::new(data) + let mut msg = Message::new(); + msg.set_data(data); + msg } } impl From for Message { fn from(data: T) -> Self { - Self::new(Some(data)) + Self::new().with_data(data) } } diff --git a/actors/src/power/mod.rs b/actors/src/power/mod.rs index 3084c817..d397486d 100644 --- a/actors/src/power/mod.rs +++ b/actors/src/power/mod.rs @@ -9,13 +9,12 @@ pub use self::state::Power; pub(crate) mod state; -#[cfg(feature = "tokio-ext")] pub mod shutdown; #[cfg(test)] mod tests { use super::*; - use std::str::FromStr; + use core::str::FromStr; #[test] fn test_power() { diff --git a/actors/src/power/shutdown.rs b/actors/src/power/shutdown.rs index 2272add0..f54aba84 100644 --- a/actors/src/power/shutdown.rs +++ b/actors/src/power/shutdown.rs @@ -2,6 +2,8 @@ Appellation: shutdown Contrib: FL03 */ +#![cfg(feature = "tokio")] + use super::Power; use tokio::sync::broadcast; diff --git a/actors/src/states/mod.rs b/actors/src/states/mod.rs index b4243d6f..07177d3c 100644 --- a/actors/src/states/mod.rs +++ b/actors/src/states/mod.rs @@ -41,6 +41,7 @@ mod tests { } #[test] + #[cfg(feature = "std")] fn test_states_iter() { let a: Vec = BinaryState::iter().collect(); assert_eq!(a.len(), 2); diff --git a/actors/src/states/state.rs b/actors/src/states/state.rs index f2645999..05d50476 100644 --- a/actors/src/states/state.rs +++ b/actors/src/states/state.rs @@ -2,6 +2,7 @@ Appellation: state Contrib: FL03 */ +use core::borrow::{Borrow, BorrowMut}; use scsys::id::AtomicId; #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] @@ -43,8 +44,14 @@ impl StateBase { } } -impl core::borrow::Borrow for StateBase { +impl Borrow for StateBase { fn borrow(&self) -> &Q { &self.state } } + +impl BorrowMut for StateBase { + fn borrow_mut(&mut self) -> &mut Q { + &mut self.state + } +} diff --git a/actors/tests/default.rs b/actors/tests/default.rs index f7f43e25..d9f69d40 100644 --- a/actors/tests/default.rs +++ b/actors/tests/default.rs @@ -2,11 +2,10 @@ Appellation: default Contrib: FL03 */ -#![cfg(test)] fn addition(a: A, b: B) -> C where - A: std::ops::Add, + A: core::ops::Add, { a + b } diff --git a/actors/tests/states.rs b/actors/tests/states.rs new file mode 100644 index 00000000..e69de29b diff --git a/core/Cargo.toml b/core/Cargo.toml index a7c2570a..d3d9fee1 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,5 +1,6 @@ [package] authors.workspace = true +build = "build.rs" categories.workspace = true description.workspace = true edition.workspace = true @@ -23,6 +24,14 @@ full = [ "serde", ] + + +# *** [FF] Dependencies *** +alloc = [ + "rand?/alloc", + "serde?/alloc", +] + rand = [ "dep:rand", ] @@ -33,10 +42,16 @@ serde = [ ] serde-ext = [ - "dep:serde_json", + "rand?/serde1", ] -std = [] +# *** [FF] Environment(s) *** +std = [ + "rand?/std", + "rand?/std_rng", + "serde?/std", + "strum/std", +] wasi = [] @@ -52,14 +67,23 @@ test = true [dependencies] glob = "0.3" -rand = { optional = true, version = "0.8" } -serde = { optional = true, features = ["derive"], version = "1" } -serde_json = { optional = true, version = "1" } smart-default.workspace = true -strum = { features = ["derive"], version = "0.26" } +strum.workspace = true + +[dependencies.rand] +default-features = false +optional = true +version = "0.8" + +[dependencies.serde] +default-features = false +features = ["derive"] +optional = true +version = "1" [dev-dependencies] anyhow = "1" +serde_json = "1" [package.metadata.docs.rs] rustc-args = ["--cfg", "docsrs"] diff --git a/core/build.rs b/core/build.rs new file mode 100644 index 00000000..940a4ce4 --- /dev/null +++ b/core/build.rs @@ -0,0 +1,8 @@ +/* + Appellation: build + Contrib: FL03 +*/ + +fn main() { + println!("cargo::rustc-check-cfg=cfg(no_std)"); +} diff --git a/core/src/hkt/applicative.rs b/core/src/hkt/applicative.rs index 81909c69..7fe265c3 100644 --- a/core/src/hkt/applicative.rs +++ b/core/src/hkt/applicative.rs @@ -8,8 +8,7 @@ use super::functor::Functor; use super::HKT; -use std::rc::Rc; -use std::sync::Arc; +use super::containers::*; pub trait Applicative: Functor { fn pure_(value: U) -> Self::T @@ -21,33 +20,30 @@ pub trait Applicative: Functor { Self: HKT; } -impl Applicative for Arc { - fn pure_(value: U) -> Self::T { - Arc::new(value) - } +macro_rules! applicative { + ($($t:ident),* $(,)?) => { + $( + applicative!(@impl $t); + )* + }; + (@impl $t:ident) => { + impl Applicative for $t { + fn pure_(value: U) -> Self::T { + $t::new(value) + } - fn seq(&self, fs: >::T) -> Arc - where - F: Fn(&T) -> U, - { - let v = fs(self); - Arc::new(v) - } -} - -impl Applicative for Box { - fn pure_(value: U) -> Self::T { - Box::new(value) - } - - fn seq(&self, fs: >::T) -> Box - where - F: Fn(&T) -> U, - { - let v = fs(self); - Box::new(v) - } + fn seq(&self, fs: >::T) -> $t + where + F: Fn(&>::C) -> U, + { + let v = fs(self); + $t::new(v) + } + } + }; } +#[cfg(any(feature = "std", all(feature = "alloc", no_std)))] +applicative!(Arc, Box, Rc); impl Applicative for Option { fn pure_(value: U) -> Self::T { @@ -68,20 +64,6 @@ impl Applicative for Option { } } -impl Applicative for Rc { - fn pure_(value: U) -> Self::T { - Rc::new(value) - } - - fn seq(&self, fs: >::T) -> Rc - where - F: Fn(&T) -> U, - { - let v = fs(self); - Rc::new(v) - } -} - impl Applicative for Vec { fn pure_(value: U) -> Self::T { vec![value] diff --git a/core/src/hkt/functor.rs b/core/src/hkt/functor.rs index 0f865492..721ea691 100644 --- a/core/src/hkt/functor.rs +++ b/core/src/hkt/functor.rs @@ -6,9 +6,8 @@ //! //! A functor is a type that when mapped over, preserves the structure of the type while applying a function to the values within the type. //! Functors are useful for modeling the functional effects on values of parameterized data types. +use super::containers::*; use super::HKT; -use std::rc::Rc; -use std::sync::Arc; pub trait Functor: HKT { fn fmap(&self, f: F) -> Self::T @@ -16,23 +15,26 @@ pub trait Functor: HKT { F: Fn(&Self::C) -> U; } -impl Functor for Arc { - fn fmap(&self, f: F) -> Arc - where - F: Fn(&T) -> U, - { - Arc::new(f(self)) - } +macro_rules! functor { + ($($t:ident),* $(,)?) => { + $( + functor!(@impl $t); + )* + }; + (@impl $t:ident) => { + impl Functor for $t { + fn fmap(&self, f: F) -> $t + where + F: Fn(&T) -> U, + { + $t::new(f(self)) + } + } + }; } -impl Functor for Box { - fn fmap(&self, f: F) -> Box - where - F: Fn(&T) -> U, - { - Box::new(f(self)) - } -} +#[cfg(any(feature = "std", all(feature = "alloc", no_std)))] +functor!(Arc, Box, Rc); impl Functor for Option { fn fmap(&self, f: F) -> Option @@ -46,15 +48,6 @@ impl Functor for Option { } } -impl Functor for Rc { - fn fmap(&self, f: F) -> Rc - where - F: Fn(&T) -> U, - { - Rc::new(f(self)) - } -} - impl Functor for Vec { fn fmap(&self, f: F) -> Vec where diff --git a/core/src/hkt/mod.rs b/core/src/hkt/mod.rs index a955c2ce..30185cbb 100644 --- a/core/src/hkt/mod.rs +++ b/core/src/hkt/mod.rs @@ -5,33 +5,56 @@ //! # Higher Kinded Types //! //! +pub use self::prelude::*; pub mod applicative; pub mod functor; pub mod monad; -use std::rc::Rc; -use std::sync::Arc; +pub(crate) mod containers { + pub(crate) use core::option::Option; + + #[cfg(all(feature = "alloc", no_std))] + pub(crate) use alloc::{boxed::Box, rc::Rc, sync::Arc, vec::Vec}; + + #[cfg(feature = "std")] + pub(crate) use std::{boxed::Box, rc::Rc, sync::Arc, vec::Vec}; +} pub trait HKT { type C; // Current Type type T; // Type C swapped with U } +#[macro_export] macro_rules! hkt { - ($t:ident) => { - impl HKT for $t { + ($($($p:ident)::*),*) => { + $( + hkt!(@impl $($p)::*); + )* + }; + (@impl $($p:ident)::*) => { + impl HKT for $($p)::* { type C = T; - type T = $t; + type T = $($p)::*; } }; } -hkt!(Arc); -hkt!(Box); -hkt!(Option); -hkt!(Rc); -hkt!(Vec); +hkt!( + containers::Arc, + containers::Box, + containers::Option, + containers::Rc, + containers::Vec +); + +pub(crate) mod prelude { + pub use super::applicative::Applicative; + pub use super::functor::Functor; + pub use super::monad::Monad; + pub use super::HKT; +} #[cfg(test)] mod tests { diff --git a/core/src/hkt/monad.rs b/core/src/hkt/monad.rs index 74c091dc..95fe7523 100644 --- a/core/src/hkt/monad.rs +++ b/core/src/hkt/monad.rs @@ -2,11 +2,10 @@ Appellation: monad Contrib: FL03 */ -use super::applicative::Applicative; +use super::Applicative; use super::HKT; -use std::rc::Rc; -use std::sync::Arc; +use super::containers::*; pub trait Monad: Applicative { fn return_(x: U) -> Self::T diff --git a/core/src/id/mod.rs b/core/src/id/mod.rs index f6584444..b9d8adda 100644 --- a/core/src/id/mod.rs +++ b/core/src/id/mod.rs @@ -11,10 +11,15 @@ mod kinds { pub mod atomic; pub mod indexed; + + pub(crate) mod prelude { + pub use super::atomic::AtomicId; + pub use super::indexed::IndexId; + } } pub(crate) mod prelude { - pub use super::kinds::*; + pub use super::kinds::prelude::*; pub use super::traits::*; } diff --git a/core/src/id/traits.rs b/core/src/id/traits.rs index 61d71010..d22f1732 100644 --- a/core/src/id/traits.rs +++ b/core/src/id/traits.rs @@ -15,9 +15,10 @@ pub trait Identifier: ToString { pub trait Id where K: Identifier, - Self: Borrow, { - fn get(&self) -> &K; + type Item: Borrow; + + fn get(&self) -> &Self::Item; } pub trait Identifiable @@ -65,8 +66,10 @@ where S: Borrow, K: Identifier, { - fn get(&self) -> &K { - self.borrow() + type Item = S; + + fn get(&self) -> &Self::Item { + &self } } diff --git a/core/src/lib.rs b/core/src/lib.rs index 2175cc98..f7c7a65b 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -7,39 +7,35 @@ //! #![cfg_attr(not(feature = "std"), no_std)] -#[cfg(not(feature = "std"))] +#[cfg(feature = "alloc")] extern crate alloc; #[doc(inline)] -pub use self::utils::*; +pub use self::{traits::prelude::*, types::prelude::*, utils::*}; +#[macro_use] +pub(crate) mod macros; #[macro_use] pub(crate) mod seal; - pub(crate) mod utils; pub mod errors; pub mod hkt; pub mod id; -#[doc(hidden)] -pub mod net; +pub mod stores; pub mod sync; pub mod time; pub mod traits; pub mod types; -/// -pub const DEFAULT_IGNORE_CHARS: &[char] = &['[', ']', ',', '.', ' ']; - pub mod prelude { - pub use crate::utils::*; - pub use crate::DEFAULT_IGNORE_CHARS; - pub use crate::errors::*; - pub use crate::hkt::*; + pub use crate::hkt::prelude::*; pub use crate::id::prelude::*; - pub use crate::net::prelude::*; + pub use crate::stores::prelude::*; + pub use crate::sync::prelude::*; pub use crate::time::*; pub use crate::traits::prelude::*; - pub use crate::types::*; + pub use crate::types::prelude::*; + pub use crate::utils::*; } diff --git a/core/src/macros.rs b/core/src/macros.rs new file mode 100644 index 00000000..f1e1266c --- /dev/null +++ b/core/src/macros.rs @@ -0,0 +1,18 @@ +/* + Appellation: macros + Contrib: FL03 +*/ + +#[allow(unused_macros)] +macro_rules! impl_fmt { + ($name:ty: $($t:ident($($rest:tt)*)),*) => { + $(impl_fmt!($name: $t($($rest)*));)* + }; + (@impl $name:ty: $t:ident($($rest:tt)*)) => { + impl core::fmt::$t for $name { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, $($rest)*) + } + } + }; +} diff --git a/core/src/net/mod.rs b/core/src/net/mod.rs deleted file mode 100644 index 2f481e59..00000000 --- a/core/src/net/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -/* - Appellation: net - Contrib: FL03 -*/ -pub use self::utils::*; - -pub(crate) mod utils { - use core::net::{self, SocketAddr}; - /// This function attempts to convert the given input into a [core::net::SocketAddr] - pub fn try_str_to_socketaddr(addr: impl ToString) -> Result { - addr.to_string().parse() - } -} - -pub(crate) mod prelude { - pub use super::utils::*; -} diff --git a/core/src/stores/kv.rs b/core/src/stores/kv.rs new file mode 100644 index 00000000..40b0c498 --- /dev/null +++ b/core/src/stores/kv.rs @@ -0,0 +1,89 @@ +/* + Appellation: store + Contrib: FL03 +*/ +#[cfg(no_std)] +use alloc::collections::{btree_map, BTreeMap}; +#[cfg(not(no_std))] +use std::collections::{btree_map, BTreeMap}; + +pub trait Entry<'a> { + type Key; + type Value; + + fn key(&self) -> &Self::Key; + + fn or_insert(self, default: Self::Value) -> &'a mut Self::Value; +} + +pub trait Store { + fn get(&self, key: &K) -> Option<&V>; + + fn get_mut(&mut self, key: &K) -> Option<&mut V>; + + fn insert(&mut self, key: K, value: V) -> Option; + + fn remove(&mut self, key: &K) -> Option; +} + +/* + ********* Implementations ********* +*/ +macro_rules! entry { + ($($prefix:ident)::* -> $call:ident($($arg:tt),*)) => { + $($prefix)::*::Entry::$call($($arg),*) + }; + +} + +macro_rules! impl_entry { + ($($prefix:ident)::* where $($preds:tt)* ) => { + + impl<'a, K, V> Entry<'a> for $($prefix)::*::Entry<'a, K, V> where $($preds)* { + type Key = K; + type Value = V; + + fn key(&self) -> &Self::Key { + entry!($($prefix)::* -> key(self)) + } + + fn or_insert(self, default: Self::Value) -> &'a mut Self::Value { + entry!($($prefix)::* -> or_insert(self, default)) + } + } + + }; + +} + +macro_rules! impl_store { + ($t:ty, where $($preds:tt)* ) => { + + impl Store for $t where $($preds)* { + fn get(&self, key: &K) -> Option<&V> { + <$t>::get(self, &key) + } + + fn get_mut(&mut self, key: &K) -> Option<&mut V> { + <$t>::get_mut(self, &key) + } + + fn insert(&mut self, key: K, value: V) -> Option { + <$t>::insert(self, key, value) + } + + fn remove(&mut self, key: &K) -> Option { + <$t>::remove(self, &key) + } + } + + }; +} + +impl_entry!(btree_map where K: Ord); +impl_store!(BTreeMap, where K: Ord); + +#[cfg(feature = "std")] +impl_entry!(std::collections::hash_map where K: Eq + core::hash::Hash); +#[cfg(feature = "std")] +impl_store!(std::collections::HashMap, where K: Eq + core::hash::Hash); diff --git a/core/src/stores/mod.rs b/core/src/stores/mod.rs new file mode 100644 index 00000000..56422bd4 --- /dev/null +++ b/core/src/stores/mod.rs @@ -0,0 +1,15 @@ +/* + Appellation: stores + Contrib: FL03 +*/ + +pub mod kv; + +pub trait OrInsert { + fn or_insert(&mut self, key: K, value: V) -> &mut V; +} + +pub(crate) mod prelude { + pub use super::kv::Store as KeyValue; + pub use super::OrInsert; +} diff --git a/core/src/sync/atomic/mod.rs b/core/src/sync/atomic/mod.rs index fb0117aa..0a475a27 100644 --- a/core/src/sync/atomic/mod.rs +++ b/core/src/sync/atomic/mod.rs @@ -6,5 +6,9 @@ pub use self::order::AtomicOrder; pub(crate) mod order; +pub(crate) mod prelude { + pub use super::order::AtomicOrder; +} + #[cfg(test)] mod tests {} diff --git a/core/src/sync/mod.rs b/core/src/sync/mod.rs index ad281a82..6a7205bd 100644 --- a/core/src/sync/mod.rs +++ b/core/src/sync/mod.rs @@ -8,5 +8,9 @@ pub mod atomic; +pub(crate) mod prelude { + pub use super::atomic::prelude::*; +} + #[cfg(test)] mod tests {} diff --git a/core/src/time/epoch.rs b/core/src/time/epoch.rs index 12e0e684..80c1e447 100644 --- a/core/src/time/epoch.rs +++ b/core/src/time/epoch.rs @@ -4,7 +4,7 @@ */ #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize,))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct Epoch { size: u128, timestamp: i64, diff --git a/core/src/time/mod.rs b/core/src/time/mod.rs index 8cfd12f5..64a21449 100644 --- a/core/src/time/mod.rs +++ b/core/src/time/mod.rs @@ -19,6 +19,8 @@ pub trait Temporal { pub(crate) mod utils { /// [systime] is a utilitarian function that returns the current system time in milliseconds. + #[cfg(feature = "std")] + #[inline] pub fn systime() -> u128 { std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) diff --git a/core/src/time/timestamp.rs b/core/src/time/timestamp.rs index 31ea349f..a1235b03 100644 --- a/core/src/time/timestamp.rs +++ b/core/src/time/timestamp.rs @@ -2,23 +2,27 @@ Appellation: timestamp Contrib: FL03 */ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; -use std::ops::Deref; +use core::borrow::Borrow; +use core::ops::Deref; /// Timestamp implements a host of useful utilities for stamping data #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -#[cfg_attr(feature = "serde", derive(Deserialize, Serialize,))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[repr(transparent)] pub struct Timestamp(u128); impl Timestamp { + pub fn new(timestamp: u128) -> Self { + Self(timestamp) + } + /// Create a new timestamp + #[cfg(feature = "std")] pub fn now() -> Self { Self(crate::time::systime()) } - pub const fn timestamp(&self) -> u128 { + pub const fn get(&self) -> u128 { self.0 } } @@ -29,6 +33,12 @@ impl AsRef for Timestamp { } } +impl Borrow for Timestamp { + fn borrow(&self) -> &u128 { + &self.0 + } +} + impl Default for Timestamp { fn default() -> Self { Self::now() @@ -43,12 +53,6 @@ impl Deref for Timestamp { } } -impl std::fmt::Display for Timestamp { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - impl From for Timestamp { fn from(timestamp: u128) -> Self { Self(timestamp) @@ -61,6 +65,28 @@ impl From for u128 { } } +macro_rules! fmt_timestamp { + ($($t:ident($($rest:tt)*)),*) => { + $( + impl core::fmt::$t for Timestamp { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, $($rest)*, self.0) + } + } + )* + }; +} + +fmt_timestamp! { + Binary("{:b}"), + Display("{}"), + LowerExp("{:e}"), + LowerHex("{:x}"), + Octal("{:o}"), + UpperExp("{:E}"), + UpperHex("{:X}") +} + #[cfg(test)] mod tests { use super::*; diff --git a/core/src/traits/appellation.rs b/core/src/traits/appellation.rs index 33b7240b..7d306417 100644 --- a/core/src/traits/appellation.rs +++ b/core/src/traits/appellation.rs @@ -4,13 +4,10 @@ */ use crate::prelude::{Classifier, Identifier}; -/// An appellation is defined to be a name or title given to a person or thing; often being used in the context of wine. -/// Here, the `Appellation` is a unique object identifier that is composed of three independent parts: -/// - Classifier -/// - Identifier -/// - Name -/// -/// While the name is typically referenced by external users, the classifier and id are used to navigate through computational space. +/// An appellation is considered to be a name or title that is used to identify an object. +/// For our purposes, an `Appellation` is a type that is used to identify an object in a computational space. +/// The appellation outlines a notation that combines an idenfifier, classifier, and name into a single unique +/// identifier for an object. pub trait Appellation { type Class: Classifier; type Id: Identifier; @@ -24,13 +21,6 @@ pub trait Appellation { fn slug(&self) -> String { self.name().to_lowercase().replace(" ", "-") } - - fn type_id(&self) -> core::any::TypeId - where - Self: Sized + 'static, - { - core::any::TypeId::of::() - } } pub trait FromAppellation diff --git a/core/src/traits/mod.rs b/core/src/traits/mod.rs index 87d9feab..a0a7ce7d 100644 --- a/core/src/traits/mod.rs +++ b/core/src/traits/mod.rs @@ -2,35 +2,24 @@ Appellation: specs Contrib: FL03 */ -pub use self::{appellation::*, classify::*, ext::*}; +pub use self::{appellation::*, classify::*, ext::prelude::*}; pub mod appellation; pub mod classify; pub mod ext { - pub use self::{slice::*, string::StringExt}; + pub use self::prelude::*; - pub mod slice; - pub mod string; -} + pub(crate) mod slice; + pub(crate) mod string; -/// Interface for data-structures that can be compared for equality -pub trait Contain -where - T: PartialEq, -{ - /// [Contain::contains] returns true if the given element is in the [Contain] instance - fn contains(&self, elem: &T) -> bool; - /// [Contain::contains_all] returns true if all elements in the given iterator are in the [Contain] instance - fn contains_all(&self, iter: impl IntoIterator) -> bool { - iter.into_iter().all(|i| self.contains(&i)) - } - /// [Contain::contains_some] returns true if any element in the given iterator is in the [Contain] instance - fn contains_some(&self, iter: impl IntoIterator) -> bool { - iter.into_iter().any(|i| self.contains(&i)) + pub(crate) mod prelude { + pub use super::slice::*; + pub use super::string::*; } } +/// [IntoInner] is typically used for basic structures that wrap a single value. pub trait IntoInner { type Inner; @@ -49,6 +38,6 @@ pub trait Name { pub(crate) mod prelude { pub use super::appellation::*; pub use super::classify::*; - pub use super::ext::*; - pub use super::{Contain, Name}; + pub use super::ext::prelude::*; + pub use super::{IntoInner, Name}; } diff --git a/actors/src/direction.rs b/core/src/types/direction.rs similarity index 100% rename from actors/src/direction.rs rename to core/src/types/direction.rs diff --git a/core/src/types/mod.rs b/core/src/types/mod.rs index 12941c57..2b2de35c 100644 --- a/core/src/types/mod.rs +++ b/core/src/types/mod.rs @@ -2,16 +2,14 @@ Appellation: types Contrib: FL03 */ -//! # types -//! -//! - -pub use self::utils::*; #[cfg(feature = "std")] -pub use std_types::*; +pub use self::std_types::*; +pub use self::{direction::Direction, utils::*}; + +pub mod direction; -pub type AnyAsync = Box; +pub type BoxAny = Box; /// A type alias for [core::result::Result] that employs the [crate::errors::Error] type pub type Result = core::result::Result; @@ -56,6 +54,14 @@ pub(crate) mod utils { } } +pub(crate) mod prelude { + pub use super::direction::Direction; + #[cfg(feature = "std")] + pub use super::std_types::*; + pub use super::utils::*; + pub use super::{BoxAny, Result}; +} + #[cfg(test)] mod tests { use super::*; diff --git a/core/src/utils.rs b/core/src/utils.rs index c7f3781a..e940e9fd 100644 --- a/core/src/utils.rs +++ b/core/src/utils.rs @@ -3,26 +3,8 @@ Contrib: FL03 */ #[cfg(feature = "std")] -pub use self::fs::*; - -use core::fmt; -use core::str::FromStr; - -/// A simple extraction utility for getting values from a string and converting them into a [Vec] -pub fn extractor(bp: char, data: &S, exclude: Option<&[char]>) -> Vec -where - S: ToString, - T: FromStr + ToString, - ::Err: fmt::Debug, -{ - let data = data.to_string(); - let skip = exclude.unwrap_or(crate::DEFAULT_IGNORE_CHARS); - let trimmed: &str = data.trim_matches(skip); - trimmed - .split(bp) - .map(|i| i.trim_matches(skip).parse::().unwrap()) - .collect() -} +pub use self::std_utils::*; + /// Remove the first and last charecters of a string pub fn fnl_remove(data: impl ToString) -> String { let data = data.to_string(); @@ -32,16 +14,6 @@ pub fn fnl_remove(data: impl ToString) -> String { chars.as_str().to_string() } -/// Fetch the project root unless specified otherwise with a CARGO_MANIFEST_DIR env variable -#[cfg(feature = "std")] -pub fn project_root() -> std::path::PathBuf { - std::path::Path::new(&env!("CARGO_MANIFEST_DIR")) - .ancestors() - .nth(1) - .unwrap() - .to_path_buf() -} - pub fn snakecase(name: impl ToString) -> String { let data = name.to_string(); @@ -87,25 +59,38 @@ pub fn snakecase(name: impl ToString) -> String { } #[cfg(feature = "std")] -mod fs { - use std::fs::File; - use std::io::{self, BufRead, BufReader}; - /// A generic function wrapper extending glob::glob - pub fn collect_files_as(f: &dyn Fn(std::path::PathBuf) -> T, pat: &str) -> Vec { - let mut files = Vec::::new(); - for path in glob::glob(pat).expect("Failed to read glob pattern...") { - if let Ok(r) = path { - files.push(f(r)) +mod std_utils { + pub use self::fs::*; + + /// Fetch the project root unless specified otherwise with a CARGO_MANIFEST_DIR env variable + pub fn project_root() -> std::path::PathBuf { + std::path::Path::new(&env!("CARGO_MANIFEST_DIR")) + .ancestors() + .nth(1) + .unwrap() + .to_path_buf() + } + + mod fs { + use std::fs::File; + use std::io::{self, BufRead, BufReader}; + /// A generic function wrapper extending glob::glob + pub fn collect_files_as(f: &dyn Fn(std::path::PathBuf) -> T, pat: &str) -> Vec { + let mut files = Vec::::new(); + for path in glob::glob(pat).expect("Failed to read glob pattern...") { + if let Ok(r) = path { + files.push(f(r)) + } + continue; } - continue; + files } - files - } - /// This function converts the file found at path (fp) into a [Vec] - pub fn file_to_vec(fp: String) -> Result, io::Error> { - let file_in = File::open(fp)?; - let file_reader = BufReader::new(file_in); - Ok(file_reader.lines().filter_map(Result::ok).collect()) + /// This function converts the file found at path (fp) into a [Vec] + pub fn file_to_vec(fp: String) -> Result, io::Error> { + let file_in = File::open(fp)?; + let file_reader = BufReader::new(file_in); + Ok(file_reader.lines().filter_map(Result::ok).collect()) + } } } diff --git a/core/tests/default.rs b/core/tests/default.rs index f7f43e25..6353d6be 100644 --- a/core/tests/default.rs +++ b/core/tests/default.rs @@ -2,11 +2,10 @@ Appellation: default Contrib: FL03 */ -#![cfg(test)] fn addition(a: A, b: B) -> C where - A: std::ops::Add, + A: core::ops::Add, { a + b } @@ -14,5 +13,5 @@ where #[test] fn compiles() { assert_eq!(addition(1, 2), 3); - assert_ne!(addition(1_f64, 0_f64), 3_f64); + assert_ne!(addition(1f64, 0f64), 3f64); } diff --git a/core/tests/errors.rs b/core/tests/errors.rs new file mode 100644 index 00000000..b3b6cfaf --- /dev/null +++ b/core/tests/errors.rs @@ -0,0 +1,23 @@ +/* + Appellation: errors + Contrib: FL03 +*/ +extern crate scsys_core as scsys; + +use scsys::errors::{Error, ErrorKind}; + +#[test] +fn test_error() { + let msg = "test"; + let err = Error::new(ErrorKind::custom("custom"), msg.to_string()); + assert_eq!(err.kind(), &ErrorKind::custom("custom")); +} + +#[test] +#[cfg(feature = "serde")] +fn test_error_serde() { + let err = Error::new(ErrorKind::custom("custom"), "test".to_string()); + let json = serde_json::to_value(&err).unwrap(); + let err2: Error = serde_json::from_value(json).unwrap(); + assert_eq!(err, err2); +} diff --git a/core/tests/time.rs b/core/tests/time.rs deleted file mode 100644 index d8c310c2..00000000 --- a/core/tests/time.rs +++ /dev/null @@ -1,5 +0,0 @@ -/* - Appellation: default - Contrib: FL03 -*/ -#![cfg(test)] diff --git a/derive/Cargo.toml b/derive/Cargo.toml index 725cc665..c715da4e 100644 --- a/derive/Cargo.toml +++ b/derive/Cargo.toml @@ -22,6 +22,10 @@ proc-macro2 = "1" quote = "1" syn = { features = ["full"], version = "2" } +[dev-dependencies] +serde = "1" +serde_json = "1" + [package.metadata.docs.rs] all-features = true rustc-args = ["--cfg", "docsrs"] diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 052867b0..af193daa 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -1,12 +1,7 @@ /* Appellation: scsys-derive Contrib: FL03 - */ -//! # scsys-derive -//! -//! Useful derive macros for the scsys ecosystem - extern crate proc_macro; extern crate quote; extern crate syn; @@ -21,30 +16,32 @@ pub(crate) mod utils; use proc_macro::TokenStream; use syn::{parse_macro_input, Data, DeriveInput}; -#[proc_macro_derive(SerdeDisplay)] -pub fn serde_display(input: TokenStream) -> TokenStream { +#[proc_macro_derive(Display, attributes(display))] +pub fn display(input: TokenStream) -> TokenStream { // Parse the inputs into the proper struct let ast = parse_macro_input!(input as DeriveInput); // Build the impl - let gen = display::handle_serde_display(&ast.ident, &ast.generics); + let gen = display::impl_display(&ast); gen.into() } -#[proc_macro_derive(Display, attributes(display))] -pub fn any_display(input: TokenStream) -> TokenStream { - // Parse the inputs into the proper struct - let ast = parse_macro_input!(input as DeriveInput); +/// This macro generates a parameter struct and an enum of parameter keys. +#[proc_macro_derive(Params, attributes(param))] +pub fn params(input: TokenStream) -> TokenStream { + // Parse the input tokens into a syntax tree + let input = parse_macro_input!(input as DeriveInput); - // Build the impl - let gen = display::impl_display(&ast); + let gen = params::impl_params(&input); + // Return the generated code as a TokenStream gen.into() } -#[proc_macro_derive(VariantConstructors)] -pub fn derive_functional_constructors(input: TokenStream) -> TokenStream { +/// This macro automatically generates functional constructors for all enclosed variants. +#[proc_macro_derive(VariantConstructors, attributes(variant))] +pub fn variant_constructors(input: TokenStream) -> TokenStream { let ast: DeriveInput = syn::parse(input).unwrap(); match ast.data { @@ -54,13 +51,17 @@ pub fn derive_functional_constructors(input: TokenStream) -> TokenStream { .into() } -/// This macro generates a parameter struct and an enum of parameter keys. -#[proc_macro_derive(Keyed, attributes(key))] +/* + ******** DEPRECATED ******** +*/ + +#[proc_macro_derive(Keyed, attributes(param))] +#[deprecated(since = "0.2.2", note = "Use `Params` instead")] pub fn keyed(input: TokenStream) -> TokenStream { // Parse the input tokens into a syntax tree let input = parse_macro_input!(input as DeriveInput); - let gen = params::impl_keyed(&input); + let gen = params::impl_params(&input); // Return the generated code as a TokenStream gen.into() diff --git a/derive/src/params.rs b/derive/src/params.rs index df4d88cb..10f63fcf 100644 --- a/derive/src/params.rs +++ b/derive/src/params.rs @@ -9,7 +9,7 @@ use proc_macro2::TokenStream; use quote::{format_ident, quote}; use syn::{Data, DataStruct, DeriveInput}; -pub fn impl_keyed(input: &DeriveInput) -> TokenStream { +pub fn impl_params(input: &DeriveInput) -> TokenStream { // Get the name of the struct let struct_name = &input.ident; let store_name = format_ident!("{}Key", struct_name); diff --git a/scsys/tests/derive.rs b/derive/tests/display.rs similarity index 74% rename from scsys/tests/derive.rs rename to derive/tests/display.rs index 8d1e0796..85b0f209 100644 --- a/scsys/tests/derive.rs +++ b/derive/tests/display.rs @@ -1,27 +1,18 @@ /* - Appellation: derive + Appellation: default Contrib: FL03 */ #![cfg(test)] -use scsys::prelude::{SerdeDisplay, Timestamp, VariantConstructors}; +use scsys_derive::{Display, VariantConstructors}; use serde::{Deserialize, Serialize}; #[derive( - Clone, - Debug, - Default, - Deserialize, - Eq, - Hash, - Ord, - PartialEq, - PartialOrd, - SerdeDisplay, - Serialize, + Clone, Debug, Default, Deserialize, Display, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, )] +#[display] pub struct TestStruct { - timestamp: Timestamp, + pub id: usize, } #[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd, VariantConstructors)] diff --git a/macros/src/lib.rs b/macros/src/lib.rs index ff6fa93d..a71ce375 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -5,3 +5,13 @@ //! # scsys-macros //! //! +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[doc(hidden)] +#[proc_macro] +pub fn display(input: TokenStream) -> TokenStream { + println!("display: {:?}", input); + input +} diff --git a/scsys/Cargo.toml b/scsys/Cargo.toml index 62a9706e..1d03a37e 100644 --- a/scsys/Cargo.toml +++ b/scsys/Cargo.toml @@ -13,69 +13,72 @@ version.workspace = true [features] default = [ - "actors", - "stores", "std", ] full = [ "default", + "actors", "derive", "rand", "serde", "tokio", ] +# *** [FF] Crates *** + actors = [ - "dep:scsys-actors" + "dep:scsys-actors", ] derive = [ "dep:scsys-derive", - "macros" + "macros", ] macros = [ - "dep:scsys-macros" + "dep:scsys-macros", ] +# *** [FF] Dependencies *** +alloc = [ + "scsys-actors?/alloc", + "scsys-core/alloc", +] rand = [ "scsys-core/rand", ] serde = [ - "scsys-actors/serde", + "scsys-actors?/serde", "scsys-core/serde", - "scsys-stores/serde", ] -std = [ - "scsys-actors/std", - "scsys-core/std", - "scsys-stores/std", -] - -stores = [ - "dep:scsys-stores" +tokio = [ + "scsys-actors?/tokio", ] +# *** [FF] Environments *** -tokio = [ - "scsys-actors/tokio", +std = [ + "scsys-actors?/std", + "scsys-core/std", ] wasi = [ - "scsys-actors/wasi", - "scsys-core/wasi" + "scsys-actors?/wasi", + "scsys-core/wasi", ] wasm = [ - "scsys-actors/wasm", + "scsys-actors?/wasm", "scsys-core/wasm", ] + [lib] bench = true crate-type = ["cdylib", "rlib"] +doctest = true test = true [[example]] @@ -90,20 +93,26 @@ required-features = ["actors"] name = "params" required-features = ["derive"] +[build-dependencies] -[[test]] -name = "derive" -required-features = ["serde", "derive"] +[dependencies.scsys-actors] +optional = true +path = "../actors" +version = "0.2.2" +[dependencies.scsys-core] +path = "../core" +version = "0.2.2" -[build-dependencies] +[dependencies.scsys-derive] +optional = true +path = "../derive" +version = "0.2.2" -[dependencies] -scsys-actors = { optional = true, path = "../actors", version = "0.2.1" } -scsys-core = { path = "../core", version = "0.2.1" } -scsys-derive = { optional = true, path = "../derive", version = "0.2.1" } -scsys-macros = { optional = true, path = "../macros", version = "0.2.1" } -scsys-stores = { optional = true, path = "../stores", version = "0.2.1" } +[dependencies.scsys-macros] +optional = true +path = "../macros" +version = "0.2.2" [dev-dependencies] serde = { features = ["derive"], version = "1" } @@ -112,6 +121,11 @@ serde_json = "1" [package.metadata.docs.rs] all-features = true rustc-args = ["--cfg", "docsrs"] +version = "v{{version}}" + +[package.metadata.release] +no-dev-version = true +tag-name = "{{version}}" [target.wasm32-unknown-unknown] diff --git a/scsys/benches/default.rs b/scsys/benches/default.rs index fae8377c..e405867e 100644 --- a/scsys/benches/default.rs +++ b/scsys/benches/default.rs @@ -2,7 +2,7 @@ Appellation: default Contrib: FL03 */ -#![cfg(bench)] +#![feature(test)] extern crate test; use test::Bencher; @@ -26,7 +26,7 @@ fn iterative_fibonacci(b: &mut Bencher) { pub mod fib { // recursive fibonacci - fn fibonacci(n: usize) -> u32 { + pub fn fibonacci(n: usize) -> u32 { if n < 2 { 1 } else { @@ -64,12 +64,11 @@ pub mod fib { type Item = u32; fn next(&mut self) -> Option { - use std::mem::replace; + use core::mem::replace; + let next = self.curr + self.next; + let curr = replace(&mut self.next, next); - let new_next = self.curr + self.next; - let new_curr = replace(&mut self.next, new_next); - - Some(replace(&mut self.curr, new_curr)) + Some(replace(&mut self.curr, curr)) } } } diff --git a/scsys/examples/derive.rs b/scsys/examples/derive.rs index 9660ff01..90a86288 100644 --- a/scsys/examples/derive.rs +++ b/scsys/examples/derive.rs @@ -4,9 +4,10 @@ */ extern crate scsys; -use scsys::{Keyed, VariantConstructors}; +use scsys::prelude::Result; +use scsys::{Params, VariantConstructors}; -fn main() -> Result<(), Box> { +fn main() -> Result<()> { let params = LinearParams { weight: 1.0 }; println!("{:?}", ¶ms); let wk = LinearParamsKey::Weight; @@ -17,9 +18,9 @@ fn main() -> Result<(), Box> { Ok(()) } -#[derive(Clone, Copy, Debug, Default, Eq, Hash, Keyed, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, Params, PartialEq, PartialOrd)] pub struct LinearParams { - #[key] + #[param] pub weight: T, } diff --git a/scsys/examples/messages.rs b/scsys/examples/messages.rs index 6f7cd075..bef63bdb 100644 --- a/scsys/examples/messages.rs +++ b/scsys/examples/messages.rs @@ -2,8 +2,7 @@ Appellation: messages Creator: FL03 */ -use scsys::core::id::AtomicId; -use scsys::prelude::Message; +use scsys::prelude::{AtomicId, Message}; fn main() { let id = AtomicId::new(); diff --git a/scsys/examples/params.rs b/scsys/examples/params.rs index eed91989..65013536 100644 --- a/scsys/examples/params.rs +++ b/scsys/examples/params.rs @@ -4,9 +4,9 @@ */ extern crate scsys; -use scsys::Keyed; +use scsys::Params; -fn main() -> Result<(), Box> { +fn main() -> scsys::prelude::Result<()> { let _params = LinearParams { weight: 1.0 }; let wk = LinearParamsKey::Weight; println!("{:?}", &wk); @@ -15,8 +15,8 @@ fn main() -> Result<(), Box> { Ok(()) } -#[derive(Keyed)] +#[derive(Params)] pub struct LinearParams { - #[key] + #[param] pub weight: T, } diff --git a/scsys/src/lib.rs b/scsys/src/lib.rs index 77e2c686..df9cfcdd 100644 --- a/scsys/src/lib.rs +++ b/scsys/src/lib.rs @@ -4,31 +4,28 @@ */ //! # scsys //! -//! +//! Welcome to `scsys`, home to various primitives and utilities used throughout the [scsys](https://scattered-systems.com) ecosystem. +//! The sdk is heavily feature gated, reducing its footprint and allowing for a more modular approach to development. #[doc(inline)] -pub use scsys_core as core; +pub use scsys_core::*; #[cfg(feature = "actors")] #[doc(inline)] pub use scsys_actors as actors; #[cfg(feature = "derive")] +#[doc(inline)] pub use scsys_derive::*; #[cfg(feature = "macros")] -pub use scsys_macros::*; -#[cfg(feature = "stores")] #[doc(inline)] -pub use scsys_stores as stores; +pub use scsys_macros::*; +// #66 - Cleanup the prelude module(s) pub mod prelude { - #[doc(inline)] - pub use super::core::prelude::*; - #[cfg(feature = "actors")] #[doc(inline)] - pub use super::actors::prelude::*; - #[cfg(feature = "stores")] + pub use scsys_actors::prelude::*; #[doc(inline)] - pub use crate::stores::prelude::*; + pub use scsys_core::prelude::*; #[cfg(feature = "derive")] pub use scsys_derive::*; #[cfg(feature = "macros")] diff --git a/scsys/tests/default.rs b/scsys/tests/default.rs index f7f43e25..6353d6be 100644 --- a/scsys/tests/default.rs +++ b/scsys/tests/default.rs @@ -2,11 +2,10 @@ Appellation: default Contrib: FL03 */ -#![cfg(test)] fn addition(a: A, b: B) -> C where - A: std::ops::Add, + A: core::ops::Add, { a + b } @@ -14,5 +13,5 @@ where #[test] fn compiles() { assert_eq!(addition(1, 2), 3); - assert_ne!(addition(1_f64, 0_f64), 3_f64); + assert_ne!(addition(1f64, 0f64), 3f64); } diff --git a/stores/Cargo.toml b/stores/Cargo.toml deleted file mode 100644 index 78be3e71..00000000 --- a/stores/Cargo.toml +++ /dev/null @@ -1,56 +0,0 @@ -[package] -authors.workspace = true -categories.workspace = true -description.workspace = true -edition.workspace = true -homepage.workspace = true -keywords.workspace = true -license.workspace = true -name = "scsys-stores" -readme.workspace = true -repository.workspace = true -version.workspace = true - -[features] -default = [ - "std", -] - -full = [ - "default", - "serde", -] - -serde = [ - "dep:serde", - "serde-ext" -] - -serde-ext = [ - "dep:serde_json" -] - -std = [] - -[lib] -bench = false -crate-type = ["cdylib", "rlib"] -test = true - -[build-dependencies] - -[dependencies] -serde = { optional = true, features = ["derive"], version = "1" } -serde_json = { optional = true, version = "1" } -smart-default.workspace = true -strum.workspace = true - -[dev-dependencies] - -[package.metadata.docs.rs] -all-features = true -rustc-args = ["--cfg", "docsrs"] - -[target.wasm32-unknown-unknown] - -[target.wasm32-wasi] \ No newline at end of file diff --git a/stores/src/actions/crud/mod.rs b/stores/src/actions/crud/mod.rs deleted file mode 100644 index d06f011c..00000000 --- a/stores/src/actions/crud/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* - Appellation: crud - Contrib: FL03 -*/ -pub use self::mode::*; - -pub(crate) mod mode; - -#[cfg(test)] -mod tests {} diff --git a/stores/src/actions/crud/mode.rs b/stores/src/actions/crud/mode.rs deleted file mode 100644 index 535b5d9c..00000000 --- a/stores/src/actions/crud/mode.rs +++ /dev/null @@ -1,58 +0,0 @@ -/* - Appellation: mode - Contrib: FL03 -*/ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; -use strum::{Display, EnumCount, EnumIs, EnumIter, EnumString, VariantNames}; - -/// The mode of a CRUD operation. -/// -#[derive( - Clone, - Copy, - Debug, - Default, - Display, - EnumCount, - EnumIs, - EnumIter, - EnumString, - Eq, - Hash, - Ord, - PartialEq, - PartialOrd, - VariantNames, -)] -#[cfg_attr( - feature = "serde", - derive(Deserialize, Serialize), - serde(rename_all = "lowercase", untagged) -)] -#[strum(serialize_all = "lowercase")] -pub enum CRUD { - #[default] - Create, - Read, - Update, - Delete, -} - -impl CRUD { - pub fn create() -> Self { - Self::Create - } - - pub fn read() -> Self { - Self::Read - } - - pub fn update() -> Self { - Self::Update - } - - pub fn delete() -> Self { - Self::Delete - } -} diff --git a/stores/src/actions/mod.rs b/stores/src/actions/mod.rs deleted file mode 100644 index e6fa8567..00000000 --- a/stores/src/actions/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -/* - Appellation: actions - Contrib: FL03 -*/ - -pub mod crud; - -pub(crate) mod prelude { - pub use super::crud::CRUD; -} - -#[cfg(test)] -mod tests {} diff --git a/stores/src/caches/mod.rs b/stores/src/caches/mod.rs deleted file mode 100644 index 15d34c1f..00000000 --- a/stores/src/caches/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -/* - Appellation: caches - Contrib: FL03 -*/ -//! Caches -//! -//! - -pub trait CacheBackend {} - -#[cfg(test)] -mod tests {} diff --git a/stores/src/kv/mod.rs b/stores/src/kv/mod.rs deleted file mode 100644 index 41ea1bb7..00000000 --- a/stores/src/kv/mod.rs +++ /dev/null @@ -1,66 +0,0 @@ -/* - Appellation: kv - Contrib: FL03 -*/ -//! Key-Value Store - -pub trait KeyValue { - fn get(&self, key: &K) -> Option<&V>; - - fn insert(&mut self, key: K, value: V) -> Option; - - fn remove(&mut self, key: &K) -> Option; -} - -pub trait OrInsert { - fn or_insert(&mut self, key: K, value: V) -> &mut V; -} - -macro_rules! impl_kv { - ($t:ty, where $($preds:tt)* ) => { - - impl KeyValue for $t where $($preds)* { - fn get(&self, key: &K) -> Option<&V> { - <$t>::get(self, &key) - } - - fn insert(&mut self, key: K, value: V) -> Option { - <$t>::insert(self, key, value) - } - - fn remove(&mut self, key: &K) -> Option { - <$t>::remove(self, &key) - } - } - }; -} - -use std::collections::{BTreeMap, HashMap}; - -impl_kv!(BTreeMap, where K: std::cmp::Ord); -impl_kv!(HashMap, where K: std::cmp::Eq + std::hash::Hash); - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_kv() { - let mut map = HashMap::new(); - map.insert(1, "one"); - map.insert(2, "two"); - map.insert(3, "three"); - - assert_eq!(map.get(&1), Some(&"one")); - assert_eq!(map.get(&2), Some(&"two")); - assert_eq!(map.get(&3), Some(&"three")); - - assert_eq!(map.remove(&1), Some("one")); - assert_eq!(map.remove(&2), Some("two")); - assert_eq!(map.remove(&3), Some("three")); - - assert_eq!(map.get(&1), None); - assert_eq!(map.get(&2), None); - assert_eq!(map.get(&3), None); - } -} diff --git a/stores/src/lib.rs b/stores/src/lib.rs deleted file mode 100644 index e3060fea..00000000 --- a/stores/src/lib.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* - Appellation: scsys-stores - Creator: FL03 -*/ -//! # Stores -//! -//! - -pub mod actions; -pub mod caches; -pub mod kv; -pub mod queues; -pub mod registries; -pub mod repos; -pub mod store; - -pub mod prelude { - pub use crate::actions::prelude::*; - - pub use crate::store::*; -} diff --git a/stores/src/queues/mod.rs b/stores/src/queues/mod.rs deleted file mode 100644 index e3a8e83f..00000000 --- a/stores/src/queues/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -/* - Appellation: queues - Contrib: FL03 -*/ -//! Queues -//! -//! -pub use self::queue::Queue; - -pub(crate) mod queue; - -#[cfg(test)] -mod tests {} diff --git a/stores/src/queues/queue.rs b/stores/src/queues/queue.rs deleted file mode 100644 index 7ce38e1d..00000000 --- a/stores/src/queues/queue.rs +++ /dev/null @@ -1,6 +0,0 @@ -/* - Appellation: queue - Contrib: FL03 -*/ - -pub struct Queue; diff --git a/stores/src/registries/mod.rs b/stores/src/registries/mod.rs deleted file mode 100644 index 7db14253..00000000 --- a/stores/src/registries/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -/* - Appellation: registries - Contrib: FL03 -*/ -//! Registries -//! -//! -pub use self::registry::*; - -pub(crate) mod registry; - -pub trait Register {} - -#[cfg(test)] -mod tests {} diff --git a/stores/src/registries/registry.rs b/stores/src/registries/registry.rs deleted file mode 100644 index 178a2962..00000000 --- a/stores/src/registries/registry.rs +++ /dev/null @@ -1,6 +0,0 @@ -/* - Appellation: registry - Contrib: FL03 -*/ - -pub struct Registry {} diff --git a/stores/src/repos/mod.rs b/stores/src/repos/mod.rs deleted file mode 100644 index 5e5db385..00000000 --- a/stores/src/repos/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -/* - Appellation: repos - Contrib: FL03 -*/ -//! Repos -//! -//! - -pub trait Repo {} - -#[cfg(test)] -mod tests {} diff --git a/stores/src/store.rs b/stores/src/store.rs deleted file mode 100644 index cc21fd9b..00000000 --- a/stores/src/store.rs +++ /dev/null @@ -1,6 +0,0 @@ -/* - Appellation: store - Contrib: FL03 -*/ - -pub trait Store {} diff --git a/stores/tests/default.rs b/stores/tests/default.rs deleted file mode 100644 index f7f43e25..00000000 --- a/stores/tests/default.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* - Appellation: default - Contrib: FL03 -*/ -#![cfg(test)] - -fn addition(a: A, b: B) -> C -where - A: std::ops::Add, -{ - a + b -} - -#[test] -fn compiles() { - assert_eq!(addition(1, 2), 3); - assert_ne!(addition(1_f64, 0_f64), 3_f64); -}