1use crate::{Unit, CastTo};
2use std::fmt::{Display, Formatter};
3
4pub trait Length : Unit + From<f64> {}
5
6macro_rules! build_type {
7 ($type_name : ident,
8 $trait_name : ident,
9 $short_name : ident,
10 $display_name : expr,
11 $num : expr,$den : expr) => {
12 #[derive(Debug,Copy,Clone,PartialEq,PartialOrd)]
13 pub struct $type_name(f64);
14 impl<T : Into<f64>> From<T> for $type_name {
15 fn from(other : T) -> Self {
16 $type_name(other.into())
17 }
18 }
19 pub trait $trait_name {
20 fn $short_name(self) -> $type_name;
21 }
22 impl<T : Into<f64>> $trait_name for T {
23 fn $short_name(self) -> $type_name {
24 $type_name(self.into())
25 }
26 }
27 impl Unit for $type_name {
28 const NUM: i32 = $num;
29 const DEN: i32 = $den;
30
31 fn value(&self) -> f64 {
32 self.0
33 }
34 }
35 impl Length for $type_name {}
36 impl Display for $type_name {
37 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
38 write!(f,concat!("{}",$display_name),self.0)
39 }
40 }
41 impl<T : Length> CastTo<T> for $type_name {}
42 };
43}
44build_type!(Kilometer,BuildKilometer,km,"km",1000,1);
45build_type!(Meter,BuildMeter,m,"m",1,1);
46build_type!(Decimeter,BuildDecimeter,dm,"dm",1,10);
47build_type!(Centimeter,BuildCentimeter,cm,"cm",1,100);
48build_type!(Millimeter,BuildMillimeter,mm,"mm",1,1000);
49build_type!(Micrometer,BuildMicrometer,um,"um",1,1000_000);
50build_type!(Nanometer,BuildNanometer,nm,"nm",1,1000_000_000);
51
52#[cfg(test)]
53mod tests {
54 use crate::length::{BuildMeter, Centimeter, Millimeter};
55 use crate::CastTo;
56
57 #[test]
58 fn test() {
59 let m = 1.4444.m();
60 let cm : Centimeter = m.cast_to();
61 let mm : Millimeter = cm.cast_to();
62 println!("{}={}={}",m,cm,mm);
63 }
64}