use crate::prelude::*;
pub trait IpAddress: Debug {
fn with_port(&self, port: u16) -> SocketAddr;
}
impl<A> IpAddress for A where A: Into<IpAddr> + Debug + Clone {
fn with_port(&self, port: u16) -> SocketAddr {
match (self.clone().into(), port)
.to_socket_addrs()
.map(|i| i.at_most_one()) {
Ok(Ok(Some(addr))) => addr,
x => panic!("{:?},{} gave {:?}", self, port, x),
}
}
}
#[derive(Debug,Copy,Clone,Eq,PartialEq,Ord,PartialOrd)]
pub struct TomlQuote<'s>(pub &'s str);
impl<'s> Display for TomlQuote<'s> {
#[throws(fmt::Error)]
fn fmt(&self, f: &mut fmt::Formatter) {
for c in self.0.chars() {
match c {
'"' | '\\'=> write!(f, "\\{}", c)?,
c if (c < ' ' && c != '\t') || c == '\x7f' => {
write!(f, r#"\u{:04x}"#, c as u32).unwrap();
continue;
}
c => write!(f, "{}", c)?,
}
}
}
}
#[test]
fn toml_quote_string_test(){
assert_eq!(TomlQuote(r#"w \ " Æ’."#).to_string(),
r#"w \\ \" \u0007\u007fÆ’."#);
}
pub fn toml_merge<'u,
S: 'u + AsRef<str>,
KV: IntoIterator<Item=(&'u S, &'u toml::Value)>
>(
table: &mut toml::value::Table,
updates: KV,
) {
use toml::value::{Table, Value};
type TME<'e> = toml::map::Entry<'e>;
let mut kv = updates.into_iter().map(|(k, v)| (k.as_ref(), v));
inner(table, &mut kv);
fn inner<'u>(
table: &mut Table,
updates: &'u mut dyn Iterator<Item=(&'u str, &'u Value)>
) {
for (k, v) in updates {
let e = table.entry(k);
match e {
TME::Vacant(ve) => {
ve.insert(v.clone());
}
TME::Occupied(mut oe) => match (oe.get_mut(), v) {
(Value::Table(old), Value::Table(new)) => {
toml_merge(old, new);
}
(Value::Array(old), Value::Array(new)) => {
old.extend(new.iter().cloned());
}
(old, new) => {
*old = new.clone();
}
}
}
}
}
}
#[derive(Copy,Clone,Debug,Serialize,Deserialize,Eq,Ord,PartialEq,PartialOrd)]
#[serde(transparent)]
pub struct Timestamp(pub u64);
impl Timestamp {
pub fn now() -> Timestamp {
use std::time::SystemTime;
let now = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs();
Timestamp(now)
}
pub fn render(&self, tz: &Timezone) -> String {
tz.format(*self)
}
}
paste!{
#[cfg(debug_assertions)]
pub fn [<x x x>]<T>() -> T { panic!("todo item triggered") }
}
#[macro_export]
macro_rules! trace_dbg {
($msg:expr $(,$val:expr)*) => {
if log_enabled!(log::Level::Trace) {
#[allow(unused_mut)]
let mut buf = format!("{}", &$msg);
$( write!(&mut buf, " {}={:?}", stringify!($val), &$val).unwrap(); )*
trace!("{}", buf);
}
}
}
#[macro_export] macro_rules! matches_doesnot_yn2bool {
(=) => (true);
(!) => (false);
}
#[macro_export]
macro_rules! matches_doesnot {
($v:expr,
$(
$yn:tt $p:pat
),* $(,)?
) => {
match $v {
$(
$p => $crate::matches_doesnot_yn2bool!($yn),
)*
}
}
}
#[test]
fn matches_doesnot_test() {
assert!(
matches_doesnot!(
Some(42),
= Some(_),
! None
)
);
assert!(
matches_doesnot!(
Some(42),
! None,
! Some(3),
= Some(_),
)
);
assert!(
matches_doesnot!(
Some(1),
= Some(1) | Some(2),
! Some(_) | None
)
);
assert!(
! matches_doesnot!(
Some(1),
! Some(1) | Some(2),
= Some(_) | None
)
);
}