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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! provides utilities for parser, compiler, and vm crate.
use std::fmt;

pub mod cache;
pub mod config;
pub mod datetime;
pub mod error;
pub mod lazy_buffer;
pub mod levenshtein;
pub mod codeobj;
pub mod combinations;
pub mod value;
pub mod color;
pub mod macros;
pub mod opcode;
pub mod python_util;
pub mod serialize;
pub mod deserialize;
pub mod traits;
pub mod tsort;
pub mod ty;
pub mod lazy;
pub mod rccell;
pub mod stdin;
pub mod str;
pub mod fxhash;
pub mod set;
pub mod dict;

pub use crate::str::Str;
use crate::set::Set;

pub type RcArray<T> = std::rc::Rc<[T]>;

pub fn open_read(filename: &str) -> std::io::Result<String> {
    let f = std::fs::File::open(filename)?;
    read_file(f)
}

pub fn read_file(mut f: std::fs::File) -> std::io::Result<String> {
    let mut s = "".to_string();
    std::io::Read::read_to_string(&mut f, &mut s).unwrap();
    Ok(s)
}

pub fn fmt_vec<T: fmt::Display>(v: &Vec<T>) -> String {
    fmt_iter(v.iter())
}

pub fn fmt_slice<T: fmt::Display>(v: &[T]) -> String {
    fmt_iter(v.iter())
}

pub fn fmt_vec_split_with<T: fmt::Display>(v: &Vec<T>, splitter: &str) -> String {
    fmt_iter_split_with(v.iter(), splitter)
}

pub fn fmt_set_split_with<T: fmt::Display + std::hash::Hash>(s: &Set<T>, splitter: &str) -> String {
    fmt_iter_split_with(s.iter(), splitter)
}

pub fn debug_fmt_iter<T: fmt::Debug, I: Iterator<Item=T>>(iter: I) -> String {
    let mut s = iter.fold("".to_string(), |sum, elem| format!("{sum}{elem:?}, "));
    s.pop();
    s.pop();
    s
}

pub fn fmt_iter<T: fmt::Display, I: Iterator<Item=T>>(iter: I) -> String {
    let mut s = iter.fold("".to_string(), |sum, elem| sum + &elem.to_string() + ", ");
    s.pop();
    s.pop();
    s
}

pub fn fmt_iter_split_with<T: fmt::Display, I: Iterator<Item=T>>(i: I, splitter: &str) -> String {
    let mut s = i.fold("".to_string(), |sum, elem| {
        sum + &elem.to_string() + splitter
    });
    for _ in 0..splitter.len() {
        s.pop();
    }
    s
}

pub fn fmt_indent(s: String, depth: usize) -> String {
    let indent = " ".repeat(depth);
    s.split("\n").map(|s| indent.clone() + s).collect()
}

pub fn get_hash<T: std::hash::Hash>(t: &T) -> usize {
    let mut s = fxhash::FxHasher::default();
    t.hash(&mut s);
    let res = std::hash::Hasher::finish(&s);
    if cfg!(target_pointer_width = "64") { res as usize }
    else { (res % usize::MAX as u64) as usize }
}

/// \r\n (Windows), \r (old MacOS) -> \n (Unix)
#[inline]
pub fn normalize_newline(src: &str) -> String {
    src.replace("\r\n", "\n").replace("\r", "\n")
}

/// cut \n
#[inline]
pub fn chomp(src: &str) -> String {
    normalize_newline(src).replace("\n", "")
}

pub fn try_map<T, U, E, F, I>(i: I, f: F) -> Result<Vec<U>, E>
where
    F: Fn(T) -> Result<U, E>,
    I: Iterator<Item=T> {
        let mut v = vec![];
        for x in i {
            let y = f(x)?;
            v.push(y);
        }
        Ok(v)
}