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};
8pub 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}
43impl 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
91impl 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#[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#[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}
203pub 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}
226pub 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
238pub 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}
356pub 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
403pub 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) => { 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 {}