~skye/git/src/com.rs
view raw
/*
* common functions and utilities
*/
use colored::Colorize;
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use crate::{macros::*, now, CFG};
use std::{
fmt::Display,
io::{self, Write},
};
pub mod cfg {
pub const VERSION: &str = "version 0.0.1: OXIDIZED";
}
pub mod err {
pub const IO_ERR: i32 = 1;
pub const DB_CON_ERR: i32 = 2;
}
pub fn page<X, Y>(t: X, b: Y) -> String
where
String: From<X>,
String: From<Y>,
{
let t = String::from(t);
let b = String::from(b);
log!("page: t: {t:?}");
format!(
r#"
<!DOCTYPE html>
<html>
<head>
<title>{title} :: {t}</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="/style.css">
</head>
<body>
<div id="head">
<b><a href="/">{title}</a></b>
</div>
<div id="page">
{b}
</div>
<div id="foot">
{version}
</div>
</body>
</html>
"#,
title = match CFG["title"].as_str() {
Some(x) => x,
None => "badboy git",
},
version = cfg::VERSION
)
}
pub fn err(m: &str, goto: &str) -> String {
page(
format!("error :: {m}").as_str(),
format!(
r#"
<h1>{m}</h1>
<p><a href="{goto}">go back</a></p>
"#
),
)
}
pub fn mkhash() -> String {
thread_rng()
.sample_iter(&Alphanumeric)
.take(32)
.map(char::from)
.collect()
}
pub fn puts<T>(s: T)
where
String: From<T>,
T: Display,
{
print!("{s}");
match io::stdout().flush() {
Ok(_) => (),
Err(e) => eprintln!("error flushing stdout: {e}"),
};
}
/** panic except not really because we don't want to kill the server
* for now just log */
pub fn panic<T>(e: T) -> !
where
String: From<T>,
T: Display,
{
eprintln!("{}: {e}", "fatal error".bold().red());
std::process::exit(-1);
}
/** basename of a path */
pub fn basename(s: &str) -> &str {
let x: Vec<&str> = s.split("/").collect();
if x.len() > 0 {
x[x.len() - 1]
} else {
""
}
}
/** dirname of a path */
pub fn dirname(s: &str) -> String {
let mut x: Vec<&str> = s.split("/").collect();
/* remove the last item, which is the basename */
x.pop();
if x.len() > 0 {
x.join("/")
} else {
String::new()
}
}
/** generic trim for trim_right and trim_left, taking an argument that determines
* if the chars are reversed.
* setting rev to true makes it a trim left, otherwise it's a trim right */
fn trim_<T>(s: T, c: char, rev: bool) -> String
where
String: From<T>,
{
let mut s = {
let s = String::from(s);
/* reverse if needed */
if rev {
s.chars().rev().collect::<String>()
} else {
s
}
};
/* mutable iterator */
let mut i = s.chars().rev().collect::<Vec<char>>();
let mut i = i.iter_mut();
/* pop while char == c */
while let Some(x) = i.next() {
if *x == c {
let p = s.pop();
safe_assert_eq!(p, Some(c));
} else {
break;
}
}
if rev {
s.chars().rev().collect::<String>()
} else {
s
}
}
/** trim all chars matching c from the left */
pub fn trim_left<T>(s: T, c: char) -> String
where
String: From<T>,
{
trim_(s, c, true)
}
/** trim all chars matching c from the right */
pub fn trim_right<T>(s: T, c: char) -> String
where
String: From<T>,
{
trim_(s, c, false)
}
/**
* turn a raw string into a "heredoc" by stripping the whitespace on
* the beginning of each line
*/
/*
pub fn heredoc<X>(x: X) -> String
where
String: From<X>,
{
let x = String::from(x);
x.split("\n").map(|x| trim_left(x, ' ')).collect::<String>()
}
*/
/** convert an int to a corresponding bool */
pub fn i64_to_bool(x: i64) -> bool {
if x == 0 {
false
} else {
true
}
}
/** convert a bool to a corresponding int */
pub fn bool_to_i64(x: bool) -> i64 {
if x {
1
} else {
0
}
}