1 use {
2     crate::*,
3     anyhow::*,
4     chrono::{DateTime, FixedOffset, SecondsFormat, Utc},
5 };
6 
7 #[derive(Debug)]
8 pub struct Seq {
9     pub header: String,
10     pub nature: Nature,
11     pub raw: Vec<Option<String>>,
12     pub ival: Vec<Option<i64>>,
13     pub min: i64,
14     pub max: i64,
15 }
16 impl Seq {
from_increasing_times(header: String, times: Vec<DateTime<Utc>>) -> Result<Self>17     pub fn from_increasing_times(header: String, times: Vec<DateTime<Utc>>) -> Result<Self> {
18         if times.is_empty() {
19             bail!("empty column");
20         }
21         let mut raw = Vec::new();
22         let mut ival = Vec::new();
23         for time in times {
24             raw.push(Some(time.to_rfc3339_opts(SecondsFormat::Secs, true)));
25             ival.push(Some(time.timestamp_millis()));
26         }
27         Ok(Self {
28             header,
29             nature: Nature::Date(FixedOffset::east(0)), // should be Utc if I understand chrono
30             raw,
31             min: ival[0].unwrap(),
32             max: ival[ival.len()-1].unwrap(),
33             ival,
34         })
35     }
from_integers(header: String, ival: Vec<Option<i64>>) -> Result<Self>36     pub fn from_integers(header: String, ival: Vec<Option<i64>>) -> Result<Self> {
37         let mut min_max: Option<(i64, i64)> = None;
38         let mut raw = vec![None; ival.len()];
39         for (idx, val) in ival.iter().enumerate() {
40             if let Some(val) = val {
41                 raw[idx] = Some(val.to_string());
42                 min_max = Some(match min_max {
43                     Some((min, max)) => (min.min(*val), max.max(*val)),
44                     None => (*val, *val),
45                 });
46             }
47         }
48         if let Some((min, max)) = min_max {
49             Ok(Self {
50                 header,
51                 nature: Nature::Integer,
52                 raw,
53                 ival,
54                 min,
55                 max,
56             })
57         } else {
58             Err(anyhow!("Empty column"))
59         }
60     }
new(raw_col: RawCol) -> Result<Self>61     pub fn new(raw_col: RawCol) -> Result<Self> {
62         let RawCol { header, cells: raw } = raw_col;
63         let mut ival = vec![None; raw.len()];
64         let mut nature = None;
65         let mut min_max: Option<(i64, i64)> = None;
66         for (x, cell) in raw.iter().enumerate() {
67             if let Some(s) = cell {
68                 let v = match nature {
69                     Some(Nature::Date(_)) => {
70                         if let Ok(dt) = DateTime::parse_from_rfc3339(s) {
71                             dt.timestamp_millis()
72                         } else if let Ok(int) = s.parse::<i64>() {
73                             // we change the seq nature
74                             nature = Some(Nature::Integer);
75                             int
76                         } else {
77                             bail!("cell can't be used: {:?}", s);
78                         }
79                     }
80                     Some(Nature::Integer) => {
81                         if let Ok(int) = s.parse::<i64>() {
82                             int
83                         } else {
84                             bail!("cell can't be used: {:?}", s);
85                         }
86                     }
87                     None => {
88                         if let Ok(dt) = DateTime::parse_from_rfc3339(s) {
89                             nature = Some(Nature::Date(*dt.offset()));
90                             dt.timestamp_millis()
91                         } else if let Ok(int) = s.parse::<i64>() {
92                             nature = Some(Nature::Integer);
93                             int
94                         } else {
95                             bail!("cell can't be used: {:?}", s);
96                         }
97                     }
98                 };
99                 ival[x] = Some(v);
100                 min_max = Some(min_max.map_or((v, v), |mm| (mm.0.min(v), mm.1.max(v))));
101             }
102         }
103         nature
104             .map(|nature| {
105                 let (min, max) = min_max.unwrap();
106                 Self {
107                     header,
108                     nature,
109                     raw,
110                     ival,
111                     min,
112                     max,
113                 }
114             })
115             .ok_or_else(||anyhow!("empty column"))
116     }
is_full_and_increasing(&self) -> bool117     pub fn is_full_and_increasing(&self) -> bool {
118         for idx in 1..self.ival.len() {
119             match (self.ival.get(idx - 1), self.ival.get(idx)) {
120                 (Some(a), Some(b)) if a < b => {} // ok
121                 _ => {
122                     return false;
123                 }
124             }
125         }
126         true
127     }
len(&self) -> usize128     pub fn len(&self) -> usize {
129         self.raw.len()
130     }
131 }
132