1use crate::prelude::*;
6
7pub trait IpAddress: Debug {
13 fn with_port(&self, port: u16) -> SocketAddr;
14}
15
16impl<A> IpAddress for A where A: Into<IpAddr> + Debug + Clone {
17 fn with_port(&self, port: u16) -> SocketAddr {
18 match (self.clone().into(), port)
19 .to_socket_addrs()
20 .map(|i| i.at_most_one()) {
21 Ok(Ok(Some(addr))) => addr,
22 x => panic!("{:?},{} gave {:?}", self, port, x),
23 }
24 }
25}
26
27#[derive(Debug,Copy,Clone,Eq,PartialEq,Ord,PartialOrd)]
30pub struct TomlQuote<'s>(pub &'s str);
31
32impl<'s> Display for TomlQuote<'s> {
35 #[throws(fmt::Error)]
36 fn fmt(&self, f: &mut fmt::Formatter) {
37 for c in self.0.chars() {
38 match c {
39 '"' | '\\'=> write!(f, "\\{}", c)?,
40 c if (c < ' ' && c != '\t') || c == '\x7f' => {
41 write!(f, r#"\u{:04x}"#, c as u32).unwrap();
42 continue;
43 }
44 c => write!(f, "{}", c)?,
45 }
46 }
47 }
48}
49
50#[test]
51fn toml_quote_string_test(){
52 assert_eq!(TomlQuote(r#"w \ " ƒ."#).to_string(),
53 r#"w \\ \" \u0007\u007fƒ."#);
54}
55
56pub fn toml_merge<'u,
57 S: 'u + AsRef<str>,
58 KV: IntoIterator<Item=(&'u S, &'u toml::Value)>
59 >(
60 table: &mut toml::value::Table,
61 updates: KV,
62) {
63 use toml::value::{Table, Value};
64 type TME<'e> = toml::map::Entry<'e>;
65
66 let mut kv = updates.into_iter().map(|(k, v)| (k.as_ref(), v));
67 inner(table, &mut kv);
68
69 fn inner<'u>(
70 table: &mut Table,
71 updates: &'u mut dyn Iterator<Item=(&'u str, &'u Value)>
72 ) {
73 for (k, v) in updates {
74 let e = table.entry(k);
75 match e {
76 TME::Vacant(ve) => {
77 ve.insert(v.clone());
78 }
79 TME::Occupied(mut oe) => match (oe.get_mut(), v) {
80 (Value::Table(old), Value::Table(new)) => {
81 toml_merge(old, new);
82 }
83 (Value::Array(old), Value::Array(new)) => {
84 old.extend(new.iter().cloned());
85 }
86 (old, new) => {
87 *old = new.clone();
88 }
89 }
90 }
91 }
92 }
93}
94
95#[derive(Copy,Clone,Debug,Serialize,Deserialize,Eq,Ord,PartialEq,PartialOrd)]
98#[serde(transparent)]
99pub struct Timestamp(pub u64); impl Timestamp {
102 pub fn now() -> Timestamp {
104 use std::time::SystemTime;
105 let now = SystemTime::now()
106 .duration_since(SystemTime::UNIX_EPOCH)
107 .unwrap()
108 .as_secs();
109 Timestamp(now)
110 }
111
112 pub fn render(&self, tz: &Timezone) -> String {
113 tz.format(*self)
114 }
115}
116
117paste!{
120 #[cfg(debug_assertions)]
121 pub fn [<x x x>]<T>() -> T { panic!("todo item triggered") }
122}
123
124#[macro_export]
125macro_rules! trace_dbg {
126 ($msg:expr $(,$val:expr)*) => {
127 if log_enabled!(log::Level::Trace) {
128 #[allow(unused_mut)]
129 let mut buf = format!("{}", &$msg);
130 $( write!(&mut buf, " {}={:?}", stringify!($val), &$val).unwrap(); )*
131 trace!("{}", buf);
132 }
133 }
134
135}
136
137#[macro_export] macro_rules! matches_doesnot_yn2bool {
141 (=) => (true);
142 (!) => (false);
143}
144
145#[macro_export]
146macro_rules! matches_doesnot {
147 ($v:expr,
148 $(
149 $yn:tt $p:pat
150 ),* $(,)?
151 ) => {
152 match $v {
153 $(
154 $p => $crate::matches_doesnot_yn2bool!($yn),
155 )*
156 }
157 }
158}
159
160#[test]
161fn matches_doesnot_test() {
162 assert!(
163 matches_doesnot!(
164 Some(42),
165 = Some(_),
166 ! None
167 )
168 );
169 assert!(
170 matches_doesnot!(
171 Some(42),
172 ! None,
173 ! Some(3),
174 = Some(_),
175 )
176 );
177 assert!(
178 matches_doesnot!(
179 Some(1),
180 = Some(1) | Some(2),
181 ! Some(_) | None
182 )
183 );
184 assert!(
185 ! matches_doesnot!(
186 Some(1),
187 ! Some(1) | Some(2),
188 = Some(_) | None
189 )
190 );
191}
192