diff --git a/Cargo.lock b/Cargo.lock index 1ae84e3..b2657c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,21 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[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 = "cfg-if" version = "1.0.0" @@ -18,19 +33,90 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" name = "configotron" version = "0.1.0" dependencies = [ + "graphviz-rust", "pad", "rand", "serde", "serde_yml", - "thiserror", + "thiserror 1.0.69", ] +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[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 = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dot-generator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aaac7ada45f71873ebce336491d1c1bc4a7c8042c7cea978168ad59e805b871" +dependencies = [ + "dot-structures", +] + +[[package]] +name = "dot-structures" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cfcded997a93eb31edd639361fa33fd229a8784e953b37d71035fe3890b7b" + [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "errno" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[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.2.16" @@ -39,7 +125,35 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "graphviz-rust" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f971272959ba59e353181bbc69f29032ffc323a164e4975ff9bed15b1b3aaf56" +dependencies = [ + "dot-generator", + "dot-structures", + "into-attr", + "into-attr-derive", + "pest", + "pest_derive", + "rand", + "tempfile", ] [[package]] @@ -58,6 +172,28 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "into-attr" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18b48c537e49a709e678caec3753a7dba6854661a1eaa27675024283b3f8b376" +dependencies = [ + "dot-structures", +] + +[[package]] +name = "into-attr-derive" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecac7c1ae6cd2c6a3a64d1061a8bdc7f52ff62c26a831a2301e54c1b5d70d5b1" +dependencies = [ + "dot-generator", + "dot-structures", + "into-attr", + "quote", + "syn 1.0.109", +] + [[package]] name = "itoa" version = "1.0.15" @@ -80,12 +216,24 @@ dependencies = [ "version_check", ] +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + [[package]] name = "pad" version = "0.1.6" @@ -95,6 +243,51 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "pest" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6" +dependencies = [ + "memchr", + "thiserror 2.0.12", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "pest_meta" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -122,6 +315,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "rand" version = "0.8.5" @@ -149,7 +348,20 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.16", +] + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", ] [[package]] @@ -175,7 +387,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -193,6 +405,28 @@ dependencies = [ "version_check", ] +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.101" @@ -204,13 +438,35 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +dependencies = [ + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix", + "windows-sys", +] + [[package]] name = "thiserror" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", ] [[package]] @@ -221,9 +477,32 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + [[package]] name = "unicode-ident" version = "1.0.18" @@ -248,6 +527,97 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + [[package]] name = "zerocopy" version = "0.8.25" @@ -265,5 +635,5 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] diff --git a/Cargo.toml b/Cargo.toml index 90f11f5..dd57dab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,4 @@ serde = { version = "1.0", features = ["derive"] } serde_yml = "0.0.12" thiserror = "1" rand = "0.8" +graphviz-rust = "0.9.4" diff --git a/docs/configotron-whiteboard.xopp b/docs/configotron-whiteboard.xopp new file mode 100644 index 0000000..676f255 Binary files /dev/null and b/docs/configotron-whiteboard.xopp differ diff --git a/src/configotron/fsm.rs b/src/configotron/fsm.rs new file mode 100644 index 0000000..4b4faba --- /dev/null +++ b/src/configotron/fsm.rs @@ -0,0 +1,199 @@ +use std::{cell::RefCell, rc::{Weak, Rc}}; + +pub struct FSM { + states: Vec>> +} + +impl FSM { + pub fn new(state: Vec>>) -> Self { + FSM {states: state} + } +} + +#[derive(Debug, Clone, Copy)] +pub enum FSMStateAction { + NONE, TERMINAL +} + +#[derive(Debug, Clone)] +pub struct FSMState { + name: String, + action: FSMStateAction, + transition: Option +} + +#[derive(Debug, Clone)] +pub struct FSMTranistion { + array: [Weak>; 128], +} + + +impl FSMState { + pub fn new(name: String, action: FSMStateAction) -> Self { + FSMState { name: name, action: action, transition: None } + } + + pub fn set_transitions(&mut self, t: FSMTranistion) { + self.transition = Some(t); + } +} + +impl FSMTranistion { + + pub fn new_from_mask(mask: TransitionMask, pos: Weak>, default: Weak>) -> Self { + let mut array: [Weak>; 128] = std::array::from_fn(|_| Weak::clone(&default)); + for i in 0..128 { + if mask.get_bit(i) { + array[i] = Weak::clone(&pos ); + } + } + + FSMTranistion { array } + } + + pub fn new(mask: TransitionMask, default: Weak>) -> Self { + let mut array: [Weak>; 128] = std::array::from_fn(|_| Weak::clone(&default)); + FSMTranistion { array } + } + + pub fn apply(&mut self, mask: TransitionMask, state: Weak>) { + + for i in 0..128 { + if mask.get_bit(i) { + self.array[i] = Weak::clone(&state ); + } + } + } +} + +use transition_masking::{TransitionMask}; + +mod transition_masking { + use std::ops::RangeInclusive; + + pub enum MaskPresets { + Char(char), + AnyCase, LowerCase, UpperCase, + AllHumanReadable, + Numbers, SpecialChars, + WhiteSpace, LineTermination, + NoChar + } + + + pub struct TransitionMask { + mask: u128 + } + + impl From for TransitionMask { + fn from(value: MaskPresets) -> Self { + let mut n: u128 = 0; + + let mut set_range = |r: RangeInclusive| { + r.for_each(|i| { n |= 1 << i }); + }; + + match value { + MaskPresets::NoChar => {} + MaskPresets::AnyCase => { + set_range(0x41..=0x5a); // UpperCase + set_range(0x61..=0x7a); // LowerCase + }, + MaskPresets::LowerCase => { + set_range(0x61..=0x7a); // LowerCase + }, + MaskPresets::UpperCase => { + set_range(0x41..=0x5a); // UpperCase + }, + MaskPresets::AllHumanReadable => { + set_range(0x20..=0x7e); // All Ascii Chars + Space + Tab + n |= 1 << 0x9; // Tab + }, + MaskPresets::Numbers => { + set_range(0x30..=0x39); // Numbers + }, + MaskPresets::SpecialChars => { + set_range(0x21..=0x2F); // ! to / + set_range(0x3A..=0x40); // : to @ + set_range(0x5B..=0x0D); // [ to ` + set_range(0x7B..=0x7E); // { to ~ + }, + MaskPresets::WhiteSpace => { + n |= 1 << 0x9; // Tab + n |= 1 << 0x20; // Spaces + + }, + MaskPresets::LineTermination => { + n |= 1 << 0x0a; // Line Feed + n |= 1 << 0x0d; // Carriage Return + } + MaskPresets::Char(c) => { + if c.is_ascii() { + n |= 1 << (c as u32) + } + }, + } + + TransitionMask { mask: n } + } + } + + impl TransitionMask { + pub fn new() -> Self { + TransitionMask { mask: 0 } + } + + pub fn or(&self, other: Self) -> TransitionMask { + TransitionMask { mask: other.mask | self.mask } + } + + pub fn and(&self, other: Self) -> TransitionMask { + TransitionMask { mask: other.mask & self.mask } + } + + pub fn inv(&self) -> TransitionMask { + TransitionMask { mask: !self.mask } + } + + pub fn get_bit(&self, i: usize) -> bool { + (self.mask & (1 << i)) > 0 + } + } +} + +#[cfg(test)] +mod test { + use super::{transition_masking::*, *}; + + #[test] + fn simple_fsm_building() { + let z0 = Rc::new(RefCell::new(FSMState::new("z0".to_string(), FSMStateAction::NONE))); + let z1 = Rc::new(RefCell::new(FSMState::new("z1".to_string(), FSMStateAction::NONE))); + let z2 = Rc::new(RefCell::new(FSMState::new("z2".to_string(), FSMStateAction::TERMINAL))); + let z3 = Rc::new(RefCell::new(FSMState::new("z3".to_string(), FSMStateAction::NONE))); + + let mut z0_transisions = FSMTranistion::new_from_mask( + TransitionMask::from(MaskPresets::Char('a')), Rc::downgrade(&z1), Rc::downgrade(&z3)); + z0_transisions.apply(TransitionMask::from(MaskPresets::Char('b')), Rc::downgrade(&z2)); + + let mut z1_transisions = FSMTranistion::new_from_mask( + TransitionMask::from(MaskPresets::Char('a')), Rc::downgrade(&z1), Rc::downgrade(&z3)); + z1_transisions.apply(TransitionMask::from(MaskPresets::Char('b')), Rc::downgrade(&z2)); + + let z2_transisions = FSMTranistion::new_from_mask( + TransitionMask::from(MaskPresets::Char('a')), Rc::downgrade(&z2), Rc::downgrade(&z3)); + + let z3_transisions = FSMTranistion::new( + TransitionMask::from(MaskPresets::Char('a')), Rc::downgrade(&z3)); + + z0.borrow_mut().set_transitions(z0_transisions); + z1.borrow_mut().set_transitions(z1_transisions); + z2.borrow_mut().set_transitions(z2_transisions); + z3.borrow_mut().set_transitions(z3_transisions); + + + let fsm = FSM::new(vec![z0, z1, z2, z3]); + + } + +} \ No newline at end of file diff --git a/src/configotron/mod.rs b/src/configotron/mod.rs index 43ce38d..0b6606e 100644 --- a/src/configotron/mod.rs +++ b/src/configotron/mod.rs @@ -1,2 +1,3 @@ pub mod conf; -pub mod doc; \ No newline at end of file +pub mod doc; +pub mod fsm; \ No newline at end of file