use std::{fmt::Display, sync::Mutex}; use crate::readline::linebuf::Line; pub static REGISTERS: Mutex = Mutex::new(Registers::new()); #[cfg(test)] pub static SAVED_REGISTERS: Mutex> = Mutex::new(None); #[cfg(test)] pub fn save_registers() { let mut saved = SAVED_REGISTERS.lock().unwrap(); *saved = Some(REGISTERS.lock().unwrap().clone()); } #[cfg(test)] pub fn restore_registers() { let mut saved = SAVED_REGISTERS.lock().unwrap(); if let Some(ref registers) = *saved { *REGISTERS.lock().unwrap() = registers.clone(); } *saved = None; } pub fn read_register(ch: Option) -> Option { let lock = REGISTERS.lock().unwrap(); lock.get_reg(ch).map(|r| r.content().clone()) } pub fn write_register(ch: Option, buf: RegisterContent) { let mut lock = REGISTERS.lock().unwrap(); if let Some(r) = lock.get_reg_mut(ch) { r.write(buf) } } pub fn append_register(ch: Option, buf: RegisterContent) { let mut lock = REGISTERS.lock().unwrap(); if let Some(r) = lock.get_reg_mut(ch) { r.append(buf) } } #[derive(Default, Clone, Debug)] pub enum RegisterContent { Span(Vec), Line(Vec), Block(Vec), #[default] Empty, } impl Display for RegisterContent { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Block(s) | Self::Line(s) | Self::Span(s) => { write!(f, "{}", s.iter().map(|l| l.to_string()).collect::>().join("\n")) } Self::Empty => write!(f, ""), } } } impl RegisterContent { pub fn clear(&mut self) { *self = Self::Empty } pub fn len(&self) -> usize { match self { Self::Span(s) | Self::Line(s) | Self::Block(s) => s.len(), Self::Empty => 0, } } pub fn is_empty(&self) -> bool { match self { Self::Span(s) => s.is_empty(), Self::Line(s) => s.is_empty(), Self::Block(s) => s.is_empty(), Self::Empty => true, } } pub fn is_block(&self) -> bool { matches!(self, Self::Block(_)) } pub fn is_line(&self) -> bool { matches!(self, Self::Line(_)) } pub fn is_span(&self) -> bool { matches!(self, Self::Span(_)) } pub fn char_count(&self) -> usize { self.to_string().chars().count() } } #[derive(Default, Clone, Debug)] pub struct Registers { default: Register, a: Register, b: Register, c: Register, d: Register, e: Register, f: Register, g: Register, h: Register, i: Register, j: Register, k: Register, l: Register, m: Register, n: Register, o: Register, p: Register, q: Register, r: Register, s: Register, t: Register, u: Register, v: Register, w: Register, x: Register, y: Register, z: Register, } impl Registers { pub const fn new() -> Self { Self { default: Register::new(), a: Register::new(), b: Register::new(), c: Register::new(), d: Register::new(), e: Register::new(), f: Register::new(), g: Register::new(), h: Register::new(), i: Register::new(), j: Register::new(), k: Register::new(), l: Register::new(), m: Register::new(), n: Register::new(), o: Register::new(), p: Register::new(), q: Register::new(), r: Register::new(), s: Register::new(), t: Register::new(), u: Register::new(), v: Register::new(), w: Register::new(), x: Register::new(), y: Register::new(), z: Register::new(), } } pub fn get_reg(&self, ch: Option) -> Option<&Register> { let Some(ch) = ch else { return Some(&self.default); }; match ch { 'a' => Some(&self.a), 'b' => Some(&self.b), 'c' => Some(&self.c), 'd' => Some(&self.d), 'e' => Some(&self.e), 'f' => Some(&self.f), 'g' => Some(&self.g), 'h' => Some(&self.h), 'i' => Some(&self.i), 'j' => Some(&self.j), 'k' => Some(&self.k), 'l' => Some(&self.l), 'm' => Some(&self.m), 'n' => Some(&self.n), 'o' => Some(&self.o), 'p' => Some(&self.p), 'q' => Some(&self.q), 'r' => Some(&self.r), 's' => Some(&self.s), 't' => Some(&self.t), 'u' => Some(&self.u), 'v' => Some(&self.v), 'w' => Some(&self.w), 'x' => Some(&self.x), 'y' => Some(&self.y), 'z' => Some(&self.z), _ => None, } } pub fn get_reg_mut(&mut self, ch: Option) -> Option<&mut Register> { let Some(ch) = ch else { return Some(&mut self.default); }; match ch { 'a' => Some(&mut self.a), 'b' => Some(&mut self.b), 'c' => Some(&mut self.c), 'd' => Some(&mut self.d), 'e' => Some(&mut self.e), 'f' => Some(&mut self.f), 'g' => Some(&mut self.g), 'h' => Some(&mut self.h), 'i' => Some(&mut self.i), 'j' => Some(&mut self.j), 'k' => Some(&mut self.k), 'l' => Some(&mut self.l), 'm' => Some(&mut self.m), 'n' => Some(&mut self.n), 'o' => Some(&mut self.o), 'p' => Some(&mut self.p), 'q' => Some(&mut self.q), 'r' => Some(&mut self.r), 's' => Some(&mut self.s), 't' => Some(&mut self.t), 'u' => Some(&mut self.u), 'v' => Some(&mut self.v), 'w' => Some(&mut self.w), 'x' => Some(&mut self.x), 'y' => Some(&mut self.y), 'z' => Some(&mut self.z), _ => None, } } } #[derive(Clone, Default, Debug)] pub struct Register { content: RegisterContent, } impl Register { pub const fn new() -> Self { Self { content: RegisterContent::Empty, } } pub fn content(&self) -> &RegisterContent { &self.content } pub fn write(&mut self, buf: RegisterContent) { self.content = buf } pub fn append(&mut self, mut buf: RegisterContent) { match buf { RegisterContent::Empty => {} RegisterContent::Span(ref mut s) | RegisterContent::Block(ref mut s) | RegisterContent::Line(ref mut s) => match &mut self.content { RegisterContent::Empty => self.content = buf, RegisterContent::Span(existing) | RegisterContent::Line(existing) | RegisterContent::Block(existing) => existing.append(s), }, } } pub fn clear(&mut self) { self.content.clear() } pub fn is_line(&self) -> bool { self.content.is_line() } pub fn is_span(&self) -> bool { self.content.is_span() } }