supa_mdx_lint/
utils.rs
1mod char_tree;
2pub(crate) mod lru;
3pub(crate) mod mdast;
4pub(crate) mod path;
5pub(crate) mod regex;
6pub(crate) mod words;
7
8use std::{
9 borrow::Cow,
10 path::{Path, PathBuf},
11};
12
13pub(crate) fn num_digits(n: usize) -> usize {
14 if n == 0 {
15 return 1;
16 }
17
18 let mut count = 0;
19 let mut num = n;
20
21 while num > 0 {
22 count += 1;
23 num /= 10;
24 }
25
26 count
27}
28
29pub(crate) fn pluralize(num: usize) -> &'static str {
30 if num == 1 {
31 ""
32 } else {
33 "s"
34 }
35}
36
37pub(crate) fn escape_backticks(s: &str) -> Cow<'_, str> {
38 if s.contains('`') {
39 Cow::Owned(s.replace('`', "\\`"))
40 } else {
41 Cow::Borrowed(s)
42 }
43}
44
45pub(crate) fn path_relative_from(path: &Path, base: &Path) -> Option<PathBuf> {
47 use std::path::Component;
48
49 if path.is_absolute() != base.is_absolute() {
50 if path.is_absolute() {
51 Some(PathBuf::from(path))
52 } else {
53 None
54 }
55 } else {
56 let mut ita = path.components();
57 let mut itb = base.components();
58 let mut comps: Vec<Component> = vec![];
59 loop {
60 match (ita.next(), itb.next()) {
61 (None, None) => break,
62 (Some(a), None) => {
63 comps.push(a);
64 comps.extend(ita.by_ref());
65 break;
66 }
67 (None, _) => comps.push(Component::ParentDir),
68 (Some(a), Some(b)) if comps.is_empty() && a == b => (),
69 (Some(a), Some(Component::CurDir)) => comps.push(a),
70 (Some(_), Some(Component::ParentDir)) => return None,
71 (Some(a), Some(_)) => {
72 comps.push(Component::ParentDir);
73 for _ in itb {
74 comps.push(Component::ParentDir);
75 }
76 comps.push(a);
77 comps.extend(ita.by_ref());
78 break;
79 }
80 }
81 }
82 Some(comps.iter().map(|c| c.as_os_str()).collect())
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn test_num_digits() {
92 assert_eq!(num_digits(0), 1);
93 assert_eq!(num_digits(1), 1);
94 assert_eq!(num_digits(10), 2);
95 assert_eq!(num_digits(1000), 4);
96 assert_eq!(num_digits(8730240234), 10);
97 }
98
99 #[test]
100 fn test_path_relative_from() {
101 let path = Path::new("/foo/bar/baz");
102 let base = Path::new("/foo/qux");
103 assert_eq!(
104 path_relative_from(path, base).unwrap(),
105 PathBuf::from("../bar/baz")
106 );
107
108 let path = Path::new("/foo/bar/baz");
109 let base = Path::new("/foo/bar");
110 assert_eq!(
111 path_relative_from(path, base).unwrap(),
112 PathBuf::from("baz")
113 );
114
115 let path = Path::new("/foo/bar");
116 let base = Path::new("/foo/bar/baz");
117 assert_eq!(path_relative_from(path, base).unwrap(), PathBuf::from(".."));
118
119 let path = Path::new("/foo/qux/xyz");
120 let base = Path::new("/foo/bar/baz");
121 assert_eq!(
122 path_relative_from(path, base).unwrap(),
123 PathBuf::from("../../qux/xyz")
124 );
125
126 let path = Path::new("/foo/bar");
127 let base = Path::new("/qux/xyz");
128 assert_eq!(
129 path_relative_from(path, base).unwrap(),
130 PathBuf::from("../../foo/bar")
131 );
132 }
133}