1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use crate::prelude::*;
pub const SVG_SCALE: f64 = 6.;
pub fn timestring_abbreviate<'x>(base: &str, this: &'x str)
-> (&'x str, bool)
{
fn split(s: &str) -> ArrayVec<[&str; 3]> {
s.splitn(3, ' ').collect()
}
let base3 = split(base);
let this3 = split(this);
let matches = |i| base3.get(i) == this3.get(i);
if_chain! {
if matches(0) && matches(2);
if let Some(abbrev) = this3.get(1);
then { (abbrev, true) }
else { (this, false) }
}
}
pub fn raw_angle_transform(compass: u8) -> String {
assert!(compass < 8);
if compass == 0 { default() }
else { format!("rotate({})", -45 * (compass as i16)) }
}
pub fn default<T:Default>() -> T { Default::default() }
#[macro_export]
macro_rules! display_as_debug {
{$x:ty $( , $($gen_tt:tt)* )?} => {
impl $( $($gen_tt)* )? std::fmt::Display for $x {
#[throws(std::fmt::Error)]
fn fmt(&self, f: &mut std::fmt::Formatter) {
<Self as Debug>::fmt(self, f)?
}
}
}
}
pub use crate::display_as_debug;
pub type SvgAttrs = Vec<(HtmlLit,Html)>;
pub fn space_table_attrs(table_size: PosC<f64>) -> SvgAttrs {
let PosC { coords: [x, y] } = table_size.into();
vec![
(Html::lit("viewBox"), hformat!("0 0 {} {}", x, y) ),
(Html::lit("width" ), (SVG_SCALE * x).to_html() ),
(Html::lit("height" ), (SVG_SCALE * y).to_html() ),
]
}
pub fn space_rect_attrs(table_size: PosC<f64>) -> SvgAttrs {
vec![
(Html::lit("width" ), table_size.x().to_html() ),
(Html::lit("height"), table_size.y().to_html() ),
]
}
#[macro_export]
macro_rules! if_let {
{ $($variant:ident)::+ ($binding:pat) = $input:expr;
else $($otherwise:tt)*
} => {
let $binding = match $input {
$($variant)::+ (y) => y,
_ => { $($otherwise)* },
};
};
}