#![feature(let_chains)]
#![feature(ascii_char)]
pub mod p;
pub mod x;
pub mod macros {
pub use crate::{err_fmt, fatal, puts, eputs};
}
use lazy_static::lazy_static;
use std::{collections::HashMap, io};
#[macro_export]
macro_rules! err_fmt {
($($t:tt)*) => {{
Err(format!($($t)*))
}};
}
#[macro_export]
macro_rules! fatal {
($($t:tt)*) => {{
eprintln!($($t)*);
std::process::exit(-1);
}};
}
#[macro_export]
macro_rules! puts {
($($t:tt)*) => {{
use std::io::Write;
print!($($t)*);
match std::io::stdout().flush() {
Ok(x) => x,
Err(e) => fatal!("failed to flush stdout: {e}"),
}
}};
}
#[macro_export]
macro_rules! eputs {
($($t:tt)*) => {{
use std::io::{Write, stderr};
eprint!($($t)*);
match stderr().flush() {
Ok(x) => x,
Err(e) => fatal!("failed to flush stderr: {e}")
}
}};
}
pub fn btoi(x: bool) -> i64 {
if x {
1
} else {
0
}
}
pub fn take<T>(v: &mut Vec<T>, n: i64) -> Vec<T> {
let mut r = Vec::new();
for _ in 0..n {
if v.len() > 0 {
r.push(v.remove(0));
} else {
break;
}
}
r
}
pub fn take_end<T>(v: &mut Vec<T>, n: i64) -> Vec<T> {
let mut r = Vec::new();
for _ in 0..n {
match v.pop() {
Some(x) => r.push(x),
None => break,
}
}
r
}
pub fn drop<T>(v: Vec<T>, n: i64) -> Vec<T> {
v.into_iter().skip(n as usize).collect()
}
pub fn drop_end<T: Clone>(v: &mut Vec<T>, n: i64) -> Vec<T> {
for _ in 0..n {
match v.pop() {
Some(_) => {}
None => break,
}
}
v.clone()
}
pub fn input(p: &str) -> String {
puts!("{p}");
let mut b = String::new();
let stdin = io::stdin();
match stdin.read_line(&mut b) {
Ok(x) => x,
Err(e) => fatal!("failed to read line from stdin: {e}"),
};
b.trim().to_string()
}
lazy_static! {
static ref ESCS: HashMap<char, char> = HashMap::from([
('n', '\n'),
('t', '\t'),
('0', '\0'),
('b', '\x08'),
('a', '\x07'),
('v', '\x0b'),
('f', '\x0c'),
('r', '\x0d'),
('"', '"'),
('\\', '\\'),
]);
}
pub fn esc<T>(x: T) -> String
where
String: From<T>,
{
String::from(x)
.chars()
.map(|x| {
for (c, e) in ESCS.iter() {
if x == *e {
return format!("\\{c}");
}
}
x.to_string()
})
.collect::<Vec<_>>()
.join("")
}
pub fn un_esc<T: Clone>(x: T) -> Result<String, String>
where
String: From<T>,
{
let mut s = String::new();
let mut i = 0;
let x = String::from(x).chars().collect::<Vec<_>>();
while i < x.len() {
s.push(if x[i] == '\\' {
if i + 1 < x.len() {
let t = x[i + 1];
i += 1;
match ESCS.get(&t) {
Some(x) => *x,
None => return err_fmt!("invalid escape \\{t}"),
}
} else {
return err_fmt!(
"escape at end of string: {}",
x.into_iter().collect::<String>()
);
}
} else {
x[i]
});
i += 1;
}
Ok(s)
}
#[test]
fn esc_unesc() {
for (x, y) in ESCS.iter() {
println!("\\{x}");
assert_eq!(esc(un_esc(match *y {
'\\' => continue,
x => x
}).unwrap()), format!("\\{x}"));
assert_eq!(un_esc(format!("\\{x}")), Ok(y.to_string()));
}
}