use crate::error::RadError;
use std::fs::File;
use std::fs::OpenOptions;
use std::path::{Path, PathBuf};
pub type RadResult<T> = Result<T, RadError>;
pub enum WriteOption<'a> {
File(FileTarget),
Variable(&'a mut String),
Return,
Terminal,
Discard,
}
impl<'a> WriteOption<'a> {
pub fn file(path: &Path, open_option: OpenOptions) -> RadResult<Self> {
let file = open_option.open(path).map_err(|_| {
RadError::InvalidFile(format!("Cannot set write option to {}", path.display()))
})?;
Ok(Self::File(FileTarget::from_file(path, file)?))
}
}
#[derive(Clone)]
pub struct LocalMacro {
pub level: usize,
pub name: String,
pub body: String,
}
impl LocalMacro {
pub fn new(level: usize, name: String, body: String) -> Self {
Self { level, name, body }
}
}
#[derive(Debug, Default)]
pub(crate) struct MacroFragment {
pub whole_string: String,
pub name: String,
pub args: String,
#[cfg(feature = "debug")]
pub processed_args: String,
pub pipe_output: bool,
pub pipe_input: bool,
pub yield_literal: bool,
pub negate_result: bool,
pub trim_input: bool,
pub trim_output: bool,
pub is_processed: bool,
}
impl MacroFragment {
pub fn new() -> Self {
MacroFragment {
whole_string: String::new(),
name: String::new(),
args: String::new(),
#[cfg(feature = "debug")]
processed_args: String::new(),
pipe_input: false,
pipe_output: false,
yield_literal: false,
negate_result: false,
trim_input: false,
trim_output: false,
is_processed: false,
}
}
pub(crate) fn clear(&mut self) {
self.whole_string.clear();
self.name.clear();
self.args.clear();
#[cfg(feature = "debug")]
self.processed_args.clear();
self.pipe_input = false;
self.pipe_output = false;
self.yield_literal = false;
self.trim_input = false;
self.negate_result = false;
self.trim_output = false;
}
pub(crate) fn is_empty(&self) -> bool {
self.whole_string.len() == 0
}
pub(crate) fn has_attribute(&self) -> bool {
self.pipe_input
|| self.pipe_output
|| self.yield_literal
|| self.trim_output
|| self.trim_input
|| self.negate_result
}
}
#[derive(PartialEq, Debug)]
pub enum CommentType {
None,
Start,
Any,
}
impl std::str::FromStr for CommentType {
type Err = RadError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let comment_type = match s.to_lowercase().as_str() {
"none" => Self::None,
"start" => Self::Start,
"any" => Self::Any,
_ => {
return Err(RadError::InvalidCommandOption(format!(
"Comment type : \"{}\" is not available.",
s
)));
}
};
Ok(comment_type)
}
}
#[derive(Debug)]
pub enum DiffOption {
None,
All,
Change,
}
impl std::str::FromStr for DiffOption {
type Err = RadError;
fn from_str(text: &str) -> Result<Self, Self::Err> {
let var = match text.to_lowercase().as_str() {
"none" => Self::None,
"all" => Self::All,
"change" => Self::Change,
_ => {
return Err(RadError::InvalidConversion(format!(
"Diffoption, \"{}\" is not a valid type",
text
)))
}
};
Ok(var)
}
}
#[derive(Debug, PartialEq)]
pub enum FlowControl {
None,
Escape,
Exit,
}
#[cfg(feature = "signature")]
pub enum SignatureType {
All,
Function,
Runtime,
}
#[cfg(feature = "signature")]
impl SignatureType {
pub fn from_str(text: &str) -> RadResult<Self> {
let variant = match text.to_lowercase().as_str() {
"all" => Self::All,
"function" => Self::Function,
"runtime" => Self::Runtime,
_ => {
return Err(RadError::InvalidConversion(format!(
"\"{}\" is not supported signature type",
text
)))
}
};
Ok(variant)
}
}
#[derive(Debug)]
pub enum RelayTarget {
None,
#[cfg(not(feature = "wasm"))]
File(FileTarget),
Macro(String),
#[cfg(not(feature = "wasm"))]
Temp,
}
#[derive(Clone, Debug, PartialEq)]
pub enum ProcessInput {
Stdin,
File(PathBuf),
}
impl std::fmt::Display for ProcessInput {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Stdin => write!(f, "Stdin"),
Self::File(file) => write!(f, "{}", file.display()),
}
}
}
#[derive(PartialEq, Clone, Copy)]
pub enum ErrorBehaviour {
Strict,
Lenient,
Purge,
Assert,
Interrupt,
}
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum ProcessType {
Expand,
Freeze,
Dry,
}
pub enum MacroType {
Function,
Deterred,
Runtime,
Any,
}
#[derive(Debug)]
pub struct FileTarget {
repr: PathBuf,
absolute_path: PathBuf,
file: File,
}
impl std::fmt::Display for FileTarget {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.repr.display())
}
}
impl FileTarget {
pub fn path(&self) -> &Path {
&self.absolute_path
}
pub fn name(&self) -> &Path {
&self.repr
}
pub fn inner(&mut self) -> &mut File {
&mut self.file
}
pub fn from_file(path: &Path, file: File) -> RadResult<Self> {
Ok(Self {
repr: path.to_owned(),
absolute_path: path.canonicalize()?,
file,
})
}
pub fn from_path(path: &Path) -> RadResult<Self> {
let repr_path = path.to_owned();
let file = std::fs::OpenOptions::new()
.create(true)
.write(true)
.append(true)
.open(&repr_path)
.map_err(|_| {
RadError::InvalidFile(format!("File \"{}\" cannot be opened", repr_path.display()))
})?;
Ok(Self {
repr: repr_path,
absolute_path: path.canonicalize()?,
file,
})
}
pub fn with_truncate(path: &Path) -> RadResult<Self> {
let repr_path = path.to_owned();
let file = std::fs::OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(&repr_path)
.map_err(|_| {
RadError::InvalidFile(format!("File \"{}\" cannot be opened", repr_path.display()))
})?;
Ok(Self {
repr: repr_path,
absolute_path: path.canonicalize()?,
file,
})
}
}
#[derive(PartialEq, Clone, Copy)]
pub enum Hygiene {
None,
Macro,
Input,
Aseptic,
}
#[derive(Eq, PartialEq)]
pub enum ContainerType {
Argument,
Expand,
None,
}