use crate::error::RadError;
use crate::auth::{AuthType, AuthState};
use crate::Processor;
use regex::Regex;
use std::io::BufRead;
use lazy_static::lazy_static;
lazy_static!{
pub static ref TRIM: Regex = Regex::new(r"^[ \t\r\n]+|[ \t\r\n]+$").unwrap();
}
#[cfg(feature = "color")]
use colored::*;
pub(crate) struct Utils;
impl Utils {
pub(crate) fn local_name(level: usize, name : &str) -> String {
format!("{}.{}", level, name)
}
pub(crate) fn trim(args: &str) -> String {
let result = TRIM.replace_all(args, "");
result.to_string()
}
pub fn full_lines(mut input: impl BufRead) -> impl Iterator<Item = std::io::Result<String>> {
std::iter::from_fn(move || {
let mut vec = String::new();
match input.read_line(&mut vec) {
Ok(0) => None,
Ok(_) => Some(Ok(vec)),
Err(e) => Some(Err(e)),
}
})
}
pub(crate) fn is_blank_char(ch: char) -> bool {
ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'
}
pub(crate) fn is_arg_true(arg: &str) -> Result<bool, RadError> {
let arg = Utils::trim(arg);
if let Ok(value) = arg.parse::<usize>() {
if value == 0 {
return Ok(false);
} else {
return Ok(true);
}
} else {
if arg.to_lowercase() == "true" {
return Ok(true);
} else if arg.to_lowercase() == "false" {
return Ok(false);
}
}
return Err(RadError::InvalidArgument("Neither true nor false".to_owned()));
}
pub(crate) fn utf8_substring(source: &str, min: Option<usize>, max: Option<usize>) -> String {
let mut result = String::new();
if let Some(min) = min {
if let Some(max) = max { for (idx,ch) in source.chars().enumerate() {
if idx >= min && idx <= max {
result.push(ch);
}
}
} else { for (idx,ch) in source.chars().enumerate() {
if idx >= min {
result.push(ch);
}
}
}
} else { if let Some(max) = max { for (idx,ch) in source.chars().enumerate() {
if idx <= max {
result.push(ch);
}
}
} else { return source.to_owned();
}
}
return result;
}
pub fn green(string : &str) -> Box<dyn std::fmt::Display> {
if cfg!(feature = "color") {
#[cfg(feature = "color")]
return Box::new(string.green().to_owned());
}
Box::new(string.to_owned())
}
pub fn red(string : &str) -> Box<dyn std::fmt::Display> {
if cfg!(feature = "color") {
#[cfg(feature = "color")]
return Box::new(string.red().to_owned());
}
Box::new(string.to_owned())
}
pub fn yellow(string : &str) -> Box<dyn std::fmt::Display> {
if cfg!(feature = "color") {
#[cfg(feature = "color")]
return Box::new(string.yellow().to_owned());
}
Box::new(string.to_owned())
}
#[allow(dead_code)]
pub(crate) fn count_sentences(s: &str) -> usize {
s.as_bytes().iter().filter(|&&c| c == b'\n').count() + 1
}
#[cfg(feature = "debug")]
pub fn clear_terminal() -> Result<(), RadError> {
use crossterm::{ExecutableCommand, terminal::ClearType};
std::io::stdout()
.execute(crossterm::terminal::Clear(ClearType::All))?
.execute(crossterm::cursor::MoveTo(0,0))?;
Ok(())
}
pub fn is_real_path(path: &std::path::Path) -> Result<(), RadError> {
if !path.exists() {
return Err(RadError::InvalidFile(path.display().to_string()));
}
Ok(())
}
pub fn pop_newline(s: &mut String) {
if s.ends_with('\n') {
s.pop();
if s.ends_with('\r') {
s.pop();
}
}
}
pub(crate) fn is_granted(name:&str, auth_type: AuthType, processor: &mut Processor) -> Result<bool, RadError> {
match processor.get_auth_state(&auth_type) {
AuthState::Restricted => {
Err(RadError::PermissionDenied(name.to_owned(), auth_type))
}
AuthState::Warn => {
processor.log_warning(&format!("\"{}\" was called with \"{:?}\" permission", name, auth_type))?;
Ok(true)
}
AuthState::Open => Ok(true),
}
}
}