Started creating FSM builder
This commit is contained in:
199
src/configotron/fsm.rs
Normal file
199
src/configotron/fsm.rs
Normal file
@@ -0,0 +1,199 @@
|
||||
use std::{cell::RefCell, rc::{Weak, Rc}};
|
||||
|
||||
pub struct FSM {
|
||||
states: Vec<Rc<RefCell<FSMState>>>
|
||||
}
|
||||
|
||||
impl FSM {
|
||||
pub fn new(state: Vec<Rc<RefCell<FSMState>>>) -> 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<FSMTranistion>
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FSMTranistion {
|
||||
array: [Weak<RefCell<FSMState>>; 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<RefCell<FSMState>>, default: Weak<RefCell<FSMState>>) -> Self {
|
||||
let mut array: [Weak<RefCell<FSMState>>; 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<RefCell<FSMState>>) -> Self {
|
||||
let mut array: [Weak<RefCell<FSMState>>; 128] = std::array::from_fn(|_| Weak::clone(&default));
|
||||
FSMTranistion { array }
|
||||
}
|
||||
|
||||
pub fn apply(&mut self, mask: TransitionMask, state: Weak<RefCell<FSMState>>) {
|
||||
|
||||
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<MaskPresets> for TransitionMask {
|
||||
fn from(value: MaskPresets) -> Self {
|
||||
let mut n: u128 = 0;
|
||||
|
||||
let mut set_range = |r: RangeInclusive<i32>| {
|
||||
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]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod conf;
|
||||
pub mod doc;
|
||||
pub mod doc;
|
||||
pub mod fsm;
|
||||
Reference in New Issue
Block a user