qust_ds/
func.rs

1
2use serde::{Deserialize, Serialize};
3use std::{
4    fmt::Debug, fs::{self, DirEntry, ReadDir}, hash::Hash, io::{self, Write}, path::Path, sync::Mutex, time::Instant
5};
6use crate::prelude::*;
7use chrono::{Local, ParseError, Timelike};
8/* #region dt */
9pub trait Fromt<T> {
10    fn fromt(data: &T) -> Self;
11}
12
13impl Fromt<dt> for dt {
14    fn fromt(data: &dt) -> Self {
15        *data
16    }
17}
18impl Fromt<da> for dt {
19    fn fromt(data: &da) -> Self {
20        data.and_hms_opt(0, 0, 0).unwrap()
21    }
22}
23impl Fromt<Year> for dt {
24    fn fromt(data: &Year) -> Self {
25        dt::fromt(&da::fromt(data))
26    }
27}
28impl Fromt<&str> for dt {
29    fn fromt(data: &&str) -> Self {
30        dt::parse_from_str(data, "%Y-%m-%d %H:%M:%S%.f").unwrap()
31    }
32}
33
34pub trait ToDt {
35    fn to_dt(&self) -> dt;
36}
37
38impl<T> ToDt for T where dt: Fromt<T> {
39    fn to_dt(&self) -> dt {
40        dt::fromt(self)
41    }
42}
43/* #endregion */
44
45/* #region da */
46impl Fromt<dt> for da {
47    fn fromt(data: &dt) -> Self {
48        data.date()
49    }
50}
51impl Fromt<da> for da {
52    fn fromt(data: &da) -> Self {
53        *data
54    }
55}
56impl Fromt<Year> for da {
57    fn fromt(data: &Year) -> Self {
58        da::from_ymd_opt(data.0 as i32, 1, 1).unwrap()
59    }
60}
61impl Fromt<usize> for da {
62    fn fromt(data: &usize) -> Self {
63        let year = data / 10000;
64        let month_date = data % 10000;
65        let month = month_date / 100;
66        let date = month_date % 100;
67        da::from_ymd_opt(year as i32, month as u32, date as u32).unwrap()
68    }
69}
70impl Fromt<String> for da {
71    fn fromt(data: &String) -> Self {
72        da::parse_from_str(data, "%Y-%m-%d").unwrap()
73    }
74}
75impl Fromt<&str> for da {
76    fn fromt(data: &&str) -> Self {
77        let res = da::parse_from_str(data, "%Y-%m-%d");
78        res.expect(data)
79    }
80}
81pub trait ToDa {
82    fn to_da(&self) -> da;
83}
84
85impl<T> ToDa for T where da: Fromt<T> {
86    fn to_da(&self) -> da {
87        da::fromt(self)
88    }
89}
90
91/* #endregion */
92
93/* #region tt */
94impl Fromt<dt> for tt {
95    fn fromt(data: &dt) -> Self {
96        tt::from_hms_opt(data.hour(), data.minute(), data.second()).unwrap()
97    }
98}
99
100impl Fromt<f64> for tt {
101    fn fromt(data: &f64) -> Self {
102        let usize_part = *data as u32;
103        let float_part = ((data % usize_part as f64) * 1000.) as u32;
104        let hour = usize_part / 10000;
105        let minitue_second = usize_part % 10000;
106        let minitue = minitue_second / 100;
107        let second = minitue_second % 100;
108        tt::from_hms_milli_opt(hour, minitue, second, float_part).unwrap()
109    }
110}
111impl Fromt<usize> for tt {
112    fn fromt(data: &usize) -> Self {
113        tt::fromt(&(*data as f64))
114    }
115}
116impl Fromt<&str> for tt {
117    fn fromt(data: &&str) -> Self {
118        tt::parse_from_str(data, "%H:%M:%S").unwrap()
119    }
120}
121
122pub trait ToTt {
123    fn to_tt(&self) -> tt;
124}
125
126impl<T> ToTt for T where tt: Fromt<T> {
127    fn to_tt(&self) -> tt {
128        tt::fromt(self)
129    }
130}
131
132/* #endregion */
133
134/* #region Year */
135#[derive(Clone, Debug, Serialize, Deserialize)]
136pub struct Year(pub usize);
137
138impl Fromt<usize> for Year {
139    fn fromt(data: &usize) -> Self {
140        Year(*data)
141    }
142}
143
144pub trait ToYear {
145    fn to_year(&self) -> Year;
146}
147
148impl<T> ToYear for T where Year: Fromt<T> {
149    fn to_year(&self) -> Year {
150        Year::fromt(self)
151    }
152}
153/* #endregion */
154
155/* #region ForCompare */
156#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
157pub enum ForCompare<T> {
158    After(T),
159    Before(T),
160    Between(std::ops::Range<T>),
161    List(Vec<Box<ForCompare<T>>>),
162}
163impl<T: std::fmt::Debug> std::fmt::Display for ForCompare<T> {
164    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165        <Self as std::fmt::Debug>::fmt(self, f)
166    }
167}
168
169impl<T> ForCompare<T> 
170where 
171    T: PartialOrd,
172{
173    pub fn compare_time<N>(&self, other: &N) -> bool 
174    where 
175        T: Fromt<N>, 
176    {
177        self.compare_same(&T::fromt(other))
178    }
179
180    pub fn compare_same(&self, other: &T) -> bool {
181        match self {
182            ForCompare::After(x) => other >= x,
183            ForCompare::Before(x) => other < x,
184            ForCompare::Between(x) => x.contains(other),
185            ForCompare::List(x) => {
186                for i in x.iter() {
187                    if i.compare_same(other) { 
188                        return true
189                    }
190                }
191                false
192            }
193        }
194    }
195
196    pub fn compare<N>(&self, other: N) -> bool
197    where
198        T: From<N>,
199    {
200        self.compare_same(&T::from(other))
201    }
202}
203/* #endregion */
204
205/* #region Convenient select */
206pub trait TimeSelect: ToDt {
207    fn before(&self) -> ForCompare<dt> {
208        ForCompare::Before(self.to_dt())
209    }
210
211    fn after(&self) -> ForCompare<dt> {
212        ForCompare::After(self.to_dt())
213    }
214
215    fn to<T: ToDt>(&self, other: T) -> ForCompare<dt> {
216        ForCompare::Between(self.to_dt()..other.to_dt())
217    }
218}
219impl<T: ToDt + Clone> TimeSelect for T {}
220
221pub fn last_days(n: i64) -> ForCompare<dt> {
222    let today = Local::now().date_naive();
223    let start_date = today - chrono::Duration::days(n);
224    start_date.to_da().after()
225}
226/* #endregion */
227
228pub trait ToDa2 {
229    fn to_da2(self) -> Result<da, ParseError>;
230}
231
232impl ToDa2 for &str {
233    fn to_da2(self) -> Result<da, ParseError> {
234        da::parse_from_str(self, "%Y%m%d")
235    }
236}
237
238/* #region ProgressBar */
239pub struct ProgressBar<T> {
240    t: Instant,
241    total: Vec<T>,
242    last_i: Mutex<usize>,
243    last_l: Mutex<usize>,
244    thre: usize,
245    count: usize,
246    size: usize,
247}
248
249impl<T> ProgressBar<T> {
250    pub fn inc(&self) {
251        *self.last_i.lock().unwrap() += 1;
252        let b = *self.last_i.lock().unwrap();
253        let l = *self.last_l.lock().unwrap();
254        let t = b.checked_sub(l);
255        match t {
256            Some(i) => {
257                if i >= self.thre || (self.size >= self.thre && b == self.size) {
258                    *self.last_l.lock().unwrap() = b;
259                    self.print();
260                }
261            }
262            None => {
263                println!("b: {b} l: {l}");
264            }
265        }
266    }
267    pub fn print(&self) {
268        println!("{:?} / {:?}, {:.0?}", self.last_i.lock().unwrap(), self.size, self.t.elapsed());
269    }
270}
271
272impl<'a, T> Iterator for ProgressBar<&'a T> {
273    type Item = &'a T;
274    fn next(&mut self) -> Option<Self::Item> {
275        let res = if self.count < self.size {
276            self.inc();
277            Some(self.total[self.count])
278        } else {
279            None
280        };
281        self.count += 1;
282        res
283    }
284}
285
286pub trait ToProgressBar {
287    type Output<'a> where Self: 'a;
288    fn to_progressbar(&self) -> ProgressBar<Self::Output<'_>>;
289}
290
291impl<T> ToProgressBar for [T] {
292    type Output<'a> = &'a T where Self: 'a;
293    fn to_progressbar(&self) -> ProgressBar<Self::Output<'_>> {
294        ProgressBar {
295            t: Instant::now(),
296            size: self.len(),
297            total: self.iter().collect_vec(),
298            last_i: Mutex::new(0),
299            last_l: Mutex::new(0),
300            thre: 1000,
301            count: 0,
302        }
303    }
304}
305
306impl Iterator for ProgressBar<usize> {
307    type Item = usize;
308    fn next(&mut self) -> Option<Self::Item> {
309        let res = if self.count < self.size {
310            self.inc();
311            Some(self.total[self.count])
312        } else {
313            None
314        };
315        self.count += 1;
316        res
317    }
318}
319
320impl ToProgressBar for usize {
321    type Output<'a> = usize;
322    fn to_progressbar(&self) -> ProgressBar<Self::Output<'_>> {
323        ProgressBar {
324            t: Instant::now(),
325            size: *self,
326            total: (0..*self).collect_vec(),
327            last_i: Mutex::new(0),
328            last_l: Mutex::new(0),
329            thre: 1000,
330            count: 0,
331        }
332    }
333}
334
335impl ToProgressBar for (usize, usize) {
336    type Output<'a> = usize;
337    fn to_progressbar(&self) -> ProgressBar<Self::Output<'_>> {
338        ProgressBar {
339            t: Instant::now(),
340            size: self.0,
341            total: (0..self.0).collect_vec(),
342            last_i: Mutex::new(0),
343            last_l: Mutex::new(0),
344            thre: self.1,
345            count: 0,
346        }
347    }
348}
349
350impl ToProgressBar for  (usize, f32) {
351    type Output<'a> = usize;
352    fn to_progressbar(&self) -> ProgressBar<Self::Output<'_>> {
353        (self.0, (self.0 as f32 * self.1) as usize).to_progressbar()
354    }
355}
356/* #endregion */
357
358pub trait Pip: Sized {
359    fn pip<F: Fn(Self) -> T, T>(self, f: F) -> T {
360        f(self)
361    }
362    fn pip_ref<F: Fn(&Self) -> T, T>(&self, f: F) -> T {
363        f(self)
364    }
365    fn pip_clone<F, T>(&self, f: F) -> T
366    where
367        Self: Clone,
368        F: Fn(Self) -> T,
369    {
370        self.clone().pip(f)
371    }
372}
373impl<T> Pip for T {}
374
375pub trait BoolToOption: Sized {
376    fn bool_to_option<F>(self, f: F) -> Option<Self>
377    where
378        F: Fn(&Self) -> bool,
379    {
380        if f(&self) { Some(self) } else { None }
381    }
382    fn bool_to_option_else<F, N>(self, f: F, other: N) -> Option<N>
383    where
384        F: Fn(Self) -> bool,
385    {
386        if f(self) { Some(other) } else { None }
387    }
388}
389impl<T> BoolToOption for T {}
390
391
392pub trait StrHandle: AsRef<str> {
393    fn split_path(&self) -> (&str, &str) {
394        let p = Path::new(self.as_ref());
395        (
396            p.file_name().unwrap().to_str().unwrap(), 
397            p.parent().unwrap().to_str().unwrap()
398        )
399    }
400}
401impl<T: AsRef<str>> StrHandle for T {}
402
403///```
404///     let k = HandleDir { 
405///  dir: String::from("D:/Rust/arcta/data"),
406///   exclude: vec![String::from("Rtick")],
407///   let x_path = x.split_path();
408///    let y_path = y.split_path();
409///    let pcon = rof::<Pcon>(x_path.0, x_path.1);
410///    let price = pcon.price.clone();
411///    (
412///        pcon.ident(),
413///        pcon.price.t,
414///        vec![price.o, price.h, price.l, price.c, price.v],
415///        price.ct,
416///    ).sof(y_path.0, y_path.1);
417///}
418///};
419///k.file_move_change("D:/Rust/arcta/data2");
420/// 
421/// use std::fs;
422///DirHandle { 
423///    dir: "..".into(),
424///    exclude: vec!["notebook".into(), "target".into(), "axum".into()],
425///    f: |x: &str, y: &str| { fs::copy(x, y); },
426///}
427///    .file_move_change("../axum/crates");
428/// 
429/// {
430///let dir_handle = DirHandle {
431///    dir: String::from("/root/arcta/data/Rtick"),
432///    exclude: vec![],
433///    f: |x: &str, y: &str| {
434///        let x_path = x.split_path();
435///        let y_path = y.split_path();
436///        let price_tick = rof::<PriceTick>(x_path.0, x_path.1);
437///        let price_tick2: PriceTickVersion = price_tick.into();
438///        price_tick2.sof(y_path.0, y_path.1);
439///    }
440///};
441///dir_handle.file_move_change("/mnt/d/Rtick");
442///}
443/// ```
444pub struct DirHandle<T> {
445    pub dir: String,
446    pub exclude: Vec<String>,
447    pub f: T
448}
449
450impl<T> DirHandle<T>
451where
452    T: Fn(&str, &str) + Clone,
453{
454    pub fn read_dir(&self) -> ReadDir {
455        let p = Path::new(&self.dir);
456        fs::read_dir(p).unwrap()
457    }
458
459    pub fn file_move_change(&self, target: &str) {
460        if !Path::new(target).is_dir() {
461            fs::create_dir(target).unwrap_or_else(|_| panic!("not such dir: {:?}", target));
462        }
463        for entry in self.read_dir() {
464            let dir = entry.unwrap();
465            let b = dir.path();
466            let f_n = b.file_name().unwrap().to_str().unwrap();
467            let t_a = format!("{}/{}", target, f_n);
468            if self.exclude.contains(&f_n.to_string()) {
469                continue
470            } else if b.is_dir() {
471                let handle_dir_next = DirHandle {
472                    dir: b.to_str().unwrap().to_string(),
473                    exclude: self.exclude.clone(),
474                    f: self.f.clone()
475                };
476                handle_dir_next.file_move_change(&t_a);
477            } else {
478                (self.f)(b.to_str().unwrap(), &t_a);
479            }
480        }
481    }
482}
483
484
485pub trait IntoTuple
486where
487    Self: Sized,
488{
489    fn tuple(&self) -> (Self,)
490    where
491        Self: Clone,
492    {
493        (self.clone(),)
494    }
495    fn into_tuple<T>(self, other: T) -> (Self, T) {
496        (self, other)
497    }
498}
499impl<T: Sized> IntoTuple for T {}
500
501pub trait Print {
502    fn print(&self)
503    where
504        Self: std::fmt::Debug,
505    {
506        println!("{:?}", self);
507    }
508    fn println(&self)
509    where
510        Self: std::fmt::Display,
511    {
512        println!("{}", self);
513    }
514    fn print_type(&self)
515    where
516        Self: Sized,
517    {
518        type_of(self);
519    }
520}
521impl<T> Print for T {}
522
523pub trait DebugString {
524    fn debug_string(&self) -> String;
525}
526impl<T: std::fmt::Debug> DebugString for T {
527    fn debug_string(&self) -> String {
528        format!("{:?}", self)
529    }
530}
531
532
533pub fn copy_dir_for_axum() {
534    DirHandle { 
535        dir: "/root/arcta".into(),
536        exclude: vec![
537            "notebook".into(), "target".into(), "axum".into(),
538             "OPT2".into(), "data".into()],
539        f: |x: &str, y: &str| { fs::copy(x, y).unwrap(); },
540    }
541        .file_move_change("/root/arcta/axum/crates")
542}
543
544pub trait FileStr: AsRef<Path> {
545    fn clear_dir(&self) {
546        let path = self.as_ref();
547        if !path.is_dir() { return }
548        self
549            .get_file_vec()
550            .unwrap_or_default()
551            .iter()
552            .for_each(|x| {
553                path.join(x).remove();
554            })
555    }
556
557    fn remove(&self) {
558        let path = Path::new(self.as_ref());
559        if path.is_dir() {
560            self.clear_dir();
561            std::fs::remove_dir(self).unwrap();
562        } else if path.is_file() {
563            std::fs::remove_file(self).unwrap();
564        }
565    }
566
567    fn build_an_empty_dir(&self) {
568        let path = Path::new(self.as_ref());
569        if path.is_dir() {
570            self.clear_dir();
571        } else {
572            if path.exists() && path.is_file() {
573                std::fs::remove_file(path).unwrap();
574            }
575            std::fs::create_dir(path).unwrap();
576        }
577    }
578
579    fn create_a_dir(&self) {
580        let path = PathBuf::from(self.as_ref());
581        if !path.exists() {
582            std::fs::create_dir(path).unwrap();
583        } 
584    }
585
586    fn get_file_vec(&self) -> io::Result<Vec<String>> {
587        self
588            .as_ref()
589            .read_dir()?
590            .map(|x| {
591                let path_str = x.unwrap().path();
592                path_str.file_name_str().to_string()
593            })
594            .collect_vec()
595            .pip(Ok)
596    }
597
598    fn get_file_vec_sort(&self) -> io::Result<Vec<String>> {
599        let mut res = self.get_file_vec()?;
600        res.sort();
601        Ok(res)
602    }
603
604    fn get_file_map(&self) -> io::Result<impl Iterator<Item = DirEntry>> {
605        self
606            .as_ref()
607            .read_dir()?
608            .map(|x| x.unwrap())
609            .pip(Ok)
610    }
611
612    fn write_by<T: AsRef<Path> + Debug>(&self, data: T) {
613        let mut path = std::fs::File
614            ::create(Path::new(self.as_ref())).unwrap();
615        write!(path, "{:?}", data).unwrap();
616    }
617
618    fn write_to<T: AsRef<Path>>(&self, data: T)
619    where
620        Self: Debug,
621    {
622        data.write_by(self.as_ref());
623    }
624
625    fn handle_file_recur(&self, f: fn(&Path)) {
626        if self.as_ref().is_dir() {
627            self
628                .get_file_vec()
629                .unwrap()
630                .iter()
631                .for_each(|x| {
632                    self.as_ref().join(x).as_path().handle_file_recur(f);
633                })
634        } else {
635            f(self.as_ref());
636        }
637    }
638
639    fn file_name_str(&self) -> &str {
640        self.as_ref().file_name().unwrap().to_str().unwrap()
641    }
642
643    fn parent_str(&self) -> &str {
644        self.as_ref().parent().unwrap().to_str().unwrap()
645    }
646
647    fn split_dir_and_file(&self) -> (&str, &str) {
648        (
649            self.parent_str(),
650            self.file_name_str(),
651        )
652    }
653
654    fn file_size(&self) -> f64 {
655        self.as_ref().metadata().unwrap().len() as f64 / 1024. / 1024.
656    }
657
658    fn check_or_make(&self) {
659        if !self.as_ref().exists() {
660            self.build_an_empty_dir()
661        }
662    }
663}
664impl<T: AsRef<Path>> FileStr for T {}
665
666
667pub trait ToStr {
668    fn to_str(&self) -> &str;
669}
670
671impl ToStr for [u8] {
672    fn to_str(&self) -> &str {
673        std::str::from_utf8(self).unwrap()
674    }
675}
676
677pub trait IoTest {
678    fn io_test(&self);
679}
680
681impl<T> IoTest for T
682where
683   for<'de> T: Serialize + Deserialize<'de>,
684{
685    fn io_test(&self) {
686        t!(self.sof("_", "."));
687        t!(rof::<T>("_", "."));
688        "_".file_size().print();
689        "_".remove();
690    }
691}
692
693use std::path::PathBuf;
694pub fn rename_date(p: &PathBuf) -> std::io::Result<()> {
695    p
696        .get_file_vec()
697        .unwrap()
698        .into_iter()
699        .for_each(|x| {
700            let x_new = x.replace('-', "");
701            let path_old = p.join(&x);
702            if path_old.is_dir() { panic!() }
703            let path_new = p.join(x_new);
704            std::fs::rename(path_old, path_new).unwrap();
705        });
706    Ok(())
707}
708
709
710use std::time::SystemTime;
711use std::time::UNIX_EPOCH;
712use chrono::{DateTime, TimeZone};
713pub fn system_time_to_date_time(t: SystemTime) -> DateTime<Local> {
714    let (sec, nsec) = match t.duration_since(UNIX_EPOCH) {
715        Ok(dur) => (dur.as_secs() as i64, dur.subsec_nanos()),
716        Err(e) => { // unlikely but should be handled
717            let dur = e.duration();
718            let (sec, nsec) = (dur.as_secs() as i64, dur.subsec_nanos());
719            if nsec == 0 {
720                (-sec, 0)
721            } else {
722                (-sec - 1, 1_000_000_000 - nsec)
723            }
724        },
725    };
726    Local.timestamp_opt(sec, nsec).unwrap()
727}
728
729pub struct DateRange {
730    start: da,
731    end: da,
732}
733
734pub struct DateRangeIter {
735    end: da,
736    last: da,
737}
738
739impl DateRange {
740    pub fn new(start: da, end: da) -> Self {
741        Self { start, end }
742    }
743}
744
745impl IntoIterator for DateRange {
746    type Item = da;
747    type IntoIter = DateRangeIter;
748    fn into_iter(self) -> Self::IntoIter {
749        DateRangeIter {
750            end: self.end,
751            last: self.start.pred_opt().unwrap(),
752        }        
753    }
754}
755
756impl Iterator for DateRangeIter {
757    type Item = da;
758    fn next(&mut self) -> Option<Self::Item> {
759        if self.last >= self.end {
760            return None;
761        }
762        self.last = self.last.succ_opt()?;
763        Some(self.last)
764    }
765}
766
767
768pub trait LeakData {
769    type Output;
770    fn leak_data(&self) -> Self::Output;
771}
772
773impl<T: Clone + Hash + std::cmp::Eq> LeakData for std::collections::HashMap<T, String> {
774    type Output = std::collections::HashMap<T, &'static str>;
775    fn leak_data(&self) -> Self::Output {
776        self
777            .iter()
778            .fold(Self::Output::default(), |mut accu, (k, v)| {
779                let v_str: &'static str = Box::leak(v.clone().into_boxed_str());
780                accu.insert(k.clone(), v_str);
781                accu
782            })
783    }
784}
785
786#[derive(Debug, Clone, Serialize, Deserialize)]
787pub struct WithInfo<T, N> {
788    pub data: T,
789    pub info: N,
790}
791
792pub trait WithInfoTrait: Sized {
793    fn with_info<T>(self, info: T) -> WithInfo<Self, T> {
794        WithInfo {
795            data: self,
796            info,
797        }
798    }
799}
800impl<T> WithInfoTrait for T {}
801
802
803pub trait GenUniqueId {
804    fn gen_unique_id(&self, n: usize) -> String 
805    where
806        Self: std::fmt::Debug,
807    {
808       use sha2::{Sha256, Digest}; 
809       let input = format!("{self:?}");
810       let mut hasher = Sha256::new();
811        hasher.update(input);
812        let result = hasher.finalize();
813        hex::encode(result).chars().take(n).collect()
814    }
815}
816
817impl<T> GenUniqueId for T {}