#![deny(missing_docs)]
#[macro_export]
macro_rules! transparent_mod {
($($mod:ident),*) => {
$(
mod $mod;
pub use $mod::*;
)*
};
($($mod:ident,)*) => {
transparent_mod!($($mod),*);
}
}
transparent_mod!(adapter, swap);
pub mod thread;
pub use std::{
cmp::Ordering,
collections::{HashMap, HashSet},
error::Error,
f32::consts::PI as PI32,
f64::consts::PI as PI64,
fmt::{Debug, Display, Formatter},
fs::{self, File},
io::{stdin, BufRead, Read, Write},
iter,
ops::{self, Deref, DerefMut, Index, IndexMut},
path::{Path, PathBuf},
rc::Rc,
str::FromStr,
sync::{Arc, Mutex},
time::Duration,
vec::IntoIter,
};
#[macro_export]
macro_rules! variant {
($pattern:pat = $input:expr => $output:expr) => {
if let $pattern = $input {
Some($output)
} else {
None
}
};
}
pub trait BoolMap {
fn map<T>(self, value: T) -> Option<T>;
fn map_with<T, F>(self, f: F) -> Option<T>
where
F: FnMut() -> T;
}
impl<B> BoolMap for B
where
B: Into<bool>,
{
fn map<T>(self, value: T) -> Option<T> {
if self.into() {
Some(value)
} else {
None
}
}
fn map_with<T, F>(self, mut f: F) -> Option<T>
where
F: FnMut() -> T,
{
if self.into() {
Some(f())
} else {
None
}
}
}
pub trait Bind: Sized {
fn bind_mut<F>(mut self, mut f: F) -> Self
where
F: FnMut(&mut Self),
{
f(&mut self);
self
}
fn bind_map<F, R>(self, mut f: F) -> R
where
F: FnMut(Self) -> R,
{
f(self)
}
}
impl<T> Bind for T {}
pub enum ChainIf<I, J>
where
I: IntoIterator,
J: IntoIterator<Item = I::Item>,
{
Chained(I::IntoIter, J::IntoIter),
NotChained(I::IntoIter),
}
impl<I, J> Iterator for ChainIf<I, J>
where
I: IntoIterator,
J: IntoIterator<Item = I::Item>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
use ChainIf::*;
match self {
Chained(first, second) => first.next().or_else(|| second.next()),
NotChained(iter) => iter.next(),
}
}
}
pub enum ChainIfElse<I, J, K>
where
I: IntoIterator,
J: IntoIterator<Item = I::Item>,
K: IntoIterator<Item = I::Item>,
{
If(I::IntoIter, J::IntoIter),
Else(I::IntoIter, K::IntoIter),
}
impl<I, J, K> Iterator for ChainIfElse<I, J, K>
where
I: IntoIterator,
J: IntoIterator<Item = I::Item>,
K: IntoIterator<Item = I::Item>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
use ChainIfElse::*;
match self {
If(first, second) => first.next().or_else(|| second.next()),
Else(first, second) => first.next().or_else(|| second.next()),
}
}
}
pub trait KaiIterator: IntoIterator + Sized {
fn chain_if<I, F>(self, condition: bool, f: F) -> ChainIf<Self, I>
where
I: IntoIterator<Item = Self::Item>,
F: FnOnce() -> I,
{
if condition {
ChainIf::Chained(self.into_iter(), f().into_iter())
} else {
ChainIf::NotChained(self.into_iter())
}
}
fn chain_if_else<J, K, F, G>(self, condition: bool, f: F, g: G) -> ChainIfElse<Self, J, K>
where
J: IntoIterator<Item = Self::Item>,
K: IntoIterator<Item = Self::Item>,
F: FnOnce() -> J,
G: FnOnce() -> K,
{
if condition {
ChainIfElse::If(self.into_iter(), f().into_iter())
} else {
ChainIfElse::Else(self.into_iter(), g().into_iter())
}
}
}
impl<I> KaiIterator for I where I: IntoIterator + Sized {}
pub type DynResult<T> = Result<T, Box<dyn Error>>;
pub type IoResult<T> = std::io::Result<T>;
pub type FmtResult = std::fmt::Result;
pub mod order {
use std::cmp::Ordering;
pub fn or_less<T>(a: &T, b: &T) -> Ordering
where
T: PartialOrd,
{
a.partial_cmp(&b).unwrap_or(Ordering::Less)
}
pub fn or_greater<T>(a: &T, b: &T) -> Ordering
where
T: PartialOrd,
{
a.partial_cmp(&b).unwrap_or(Ordering::Greater)
}
pub fn or_equal<T>(a: &T, b: &T) -> Ordering
where
T: PartialOrd,
{
a.partial_cmp(&b).unwrap_or(Ordering::Equal)
}
}
pub mod close {
#![allow(clippy::trivially_copy_pass_by_ref)]
pub fn f32(a: f32, b: f32) -> bool {
(a - b).abs() < std::f32::EPSILON
}
pub fn f32_ref(a: &f32, b: &f32) -> bool {
(*a - *b).abs() < std::f32::EPSILON
}
pub fn f64(a: f64, b: f64) -> bool {
(a - b).abs() < std::f64::EPSILON
}
pub fn f64_ref(a: &f64, b: &f64) -> bool {
(*a - *b).abs() < std::f64::EPSILON
}
}
pub unsafe fn promote_then<T, R, F>(var: &T, f: F) -> R
where
F: FnOnce(&mut T) -> R,
{
f((var as *const T as *mut T).as_mut().unwrap())
}
#[macro_export]
macro_rules! cond_vec {
($($cond:expr => $elem:expr),* $(,)*) => {{
let mut new_vec = Vec::new();
$(if $cond {
new_vec.push($elem);
})*
new_vec
}};
}