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
use std::{
fs::File,
hash::{Hash, Hasher},
io::{BufReader, Read},
path::{Path, PathBuf},
};
mod watcher;
pub use self::workspace::*;
use crate::CalamineTable;
use calamine::{open_workbook_auto, DataType, Reader};
use itertools::Itertools;
use pathdiff::diff_paths;
use twox_hash::XxHash64;
use xcell_errors::{XError, XResult};
mod workspace;
pub fn find_first_table(path: &PathBuf) -> XResult<CalamineTable> {
let mut workbook = open_workbook_auto(path)?;
let ranges = match workbook.worksheet_range_at(0) {
None => return Err(XError::table_error("找不到配置表, 文件是空的, 或者表格式非法")),
Some(s) => s?,
};
Ok(ranges)
}
pub fn first_not_nil(row: &[DataType]) -> bool {
match row.first() {
Some(s) => match s {
DataType::Int(_) => true,
DataType::Float(_) => true,
DataType::String(s) => !s.is_empty(),
DataType::Bool(_) => true,
DataType::DateTime(_) => true,
DataType::Error(_) => false,
DataType::Empty => false,
},
None => false,
}
}
pub fn xx_hash<T>(body: T) -> u64
where
T: Hash,
{
let mut hasher = XxHash64::default();
body.hash(&mut hasher);
hasher.finish()
}
pub fn xx_file(path: &Path) -> XResult<u64> {
let mut hasher = XxHash64::default();
let input = File::open(path)?;
let mut reader = BufReader::new(input);
let mut buffer = [0; 1024];
loop {
let count = reader.read(&mut buffer)?;
if count == 0 {
break;
}
hasher.write(&buffer[..count]);
}
Ok(hasher.finish())
}
pub fn split_file_name(s: &str) -> String {
let mut all = vec![];
for name in s.split(|c| c == '/' || c == '\\') {
if !name.trim().is_empty() {
all.push(name)
}
}
all.join("/")
}
pub fn split_namespace(s: &str) -> Vec<&str> {
let mut all = vec![];
for s in s.split("::") {
for name in s.split('.') {
if !name.trim().is_empty() {
all.push(name)
}
}
}
all
}