use crate::auth::AuthFlags;
#[cfg(not(feature = "wasm"))]
use crate::common::FileTarget;
use crate::common::RadResult;
use crate::common::{
CommentType, ErrorBehaviour, FlowControl, Hygiene, ProcessInput, ProcessType, RelayTarget,
};
use crate::consts::LINE_ENDING;
use crate::RadError;
use regex::Regex;
use std::collections::{HashMap, HashSet};
#[cfg(not(feature = "wasm"))]
use std::path::Path;
use std::path::PathBuf;
pub(crate) struct ProcessorState {
pub auth_flags: AuthFlags,
pub current_input: ProcessInput,
pub input_stack: HashSet<PathBuf>,
pub newline: String,
pub paused: bool,
pub error_cache: Option<RadError>,
pub hygiene: Hygiene,
pub pipe_truncate: bool,
pub pipe_map: HashMap<String, String>,
pub relay: Vec<RelayTarget>,
pub sandbox: bool,
pub behaviour: ErrorBehaviour,
pub process_type: ProcessType,
pub comment_type: CommentType,
#[cfg(not(feature = "wasm"))]
pub temp_target: FileTarget,
pub comment_char: Option<char>,
pub macro_char: Option<char>,
pub flow_control: FlowControl,
pub deny_newline: bool, pub consume_newline: bool, pub escape_newline: bool, pub queued: Vec<String>,
pub regex_cache: RegexCache,
pub lexor_escape_blanks: bool,
}
impl ProcessorState {
pub fn new() -> Self {
Self {
current_input: ProcessInput::Stdin,
input_stack: HashSet::new(),
auth_flags: AuthFlags::new(),
newline: LINE_ENDING.to_owned(),
pipe_truncate: true,
pipe_map: HashMap::new(),
paused: false,
error_cache: None,
hygiene: Hygiene::None,
relay: vec![],
behaviour: ErrorBehaviour::Strict,
process_type: ProcessType::Expand,
comment_type: CommentType::None,
sandbox: false,
#[cfg(not(feature = "wasm"))]
temp_target: FileTarget::with_truncate(&std::env::temp_dir().join("rad.txt")).unwrap(),
comment_char: None,
macro_char: None,
flow_control: FlowControl::None,
deny_newline: false,
consume_newline: false,
escape_newline: false,
queued: vec![],
regex_cache: RegexCache::new(),
lexor_escape_blanks: false,
}
}
#[cfg(not(feature = "wasm"))]
pub(crate) fn set_temp_target(&mut self, path: &Path) -> RadResult<()> {
if path.exists() {
std::fs::remove_file(path)?;
}
let new_target = FileTarget::with_truncate(path)?;
self.temp_target = new_target;
Ok(())
}
pub fn add_pipe(&mut self, name: Option<&str>, value: String) {
if let Some(name) = name {
self.pipe_map.insert(name.to_owned(), value);
} else {
self.pipe_map.insert("-".to_owned(), value);
}
}
pub fn get_pipe(&mut self, key: &str) -> Option<String> {
if self.pipe_truncate {
self.pipe_map.remove(key)
} else {
self.pipe_map.get(key).map(|s| s.to_owned())
}
}
}
pub(crate) struct RegexCache {
cache: HashMap<String, Regex>,
register: HashMap<String, Regex>,
}
impl RegexCache {
pub fn new() -> Self {
Self {
cache: HashMap::new(),
register: HashMap::new(),
}
}
pub fn contains(&self, name: &str) -> bool {
self.cache.contains_key(name)
}
pub fn register(&mut self, name: &str, source: &str) -> RadResult<()> {
self.cache.insert(name.to_string(), Regex::new(source)?);
Ok(())
}
pub fn append(&mut self, src: &str) -> RadResult<&Regex> {
if self.cache.len() > 100 {
self.cache.clear();
}
self.cache.insert(src.to_string(), Regex::new(src)?);
Ok(self.get(src).unwrap())
}
pub fn get(&self, src: &str) -> Option<&Regex> {
if self.register.get(src).is_some() {
self.register.get(src)
} else {
self.cache.get(src)
}
}
}