ming_wm_lib/
utils.rs

1use std::path::PathBuf;
2
3use crate::framebuffer_types::{ Dimensions, Point };
4
5pub fn min(one: usize, two: usize) -> usize {
6  if one > two { two } else { one } 
7}
8
9pub trait Substring {
10  fn substring(&self, start: usize, end: usize) -> &str;
11  fn remove(&self, index: usize, len: usize) -> String;
12  fn remove_last(&self) -> String;
13}
14
15impl Substring for String {
16  fn substring(&self, start: usize, end: usize) -> &str {
17    let mut byte_start = 0;
18    let mut byte_end = 0;
19    let mut chars = self.chars();
20    for i in 0..end {
21      let char_length = chars.next().unwrap().len_utf8();
22      if i < start {
23        byte_start += char_length;
24      }
25      if i == end {
26        break;
27      }
28      byte_end += char_length;
29    }
30    &self[byte_start..byte_end]
31  }
32
33  fn remove(&self, index: usize, len: usize) -> String {
34    self.substring(0, index).to_string() + self.substring(index + len, self.chars().count())
35  }
36
37  fn remove_last(&self) -> String {
38    self.substring(0, self.chars().count() - 1).to_string()
39  }
40}
41
42//the tuple is first, line #, actual line
43pub fn calc_actual_lines<'a>(lines: impl Iterator<Item = &'a String>, max_chars_per_line: usize, one_extra: bool) -> Vec<(bool, usize, String)> {
44  let mut actual_lines = Vec::new();
45  let mut line_num = 0;
46  for real_line in lines {
47    let mut line = real_line.to_string() + if one_extra { " " } else { "" };
48    let mut first = true;
49    loop {
50      if line.chars().count() <= max_chars_per_line {
51        actual_lines.push((first, line_num, line));
52        break;
53      } else {
54        let mut line_chars = line.chars();
55        let mut push_string = String::new();
56        for _i in 0..max_chars_per_line {
57          push_string += &line_chars.next().unwrap().to_string();
58        }
59        actual_lines.push((first, line_num, push_string));
60        line = line_chars.collect();
61      }
62      first = false;
63    }
64    line_num += 1;
65  }
66  actual_lines
67}
68
69pub fn calc_new_cursor_pos(cursor_pos: usize, new_length: usize) -> usize {
70  if cursor_pos >= new_length {
71    if new_length == 0 {
72      0
73    } else {
74      new_length - 1
75    }
76  } else {
77    cursor_pos
78  }
79}
80
81pub fn concat_paths(current_path: &str, add_path: &str) -> Result<PathBuf, ()> {
82  let mut new_path = PathBuf::from(current_path);
83  if add_path.starts_with("/") {
84    //absolute path
85    new_path = PathBuf::from(add_path);
86  } else {
87    //relative path
88    for part in add_path.split("/") {
89      if part == ".." {
90        if let Some(parent) = new_path.parent() {
91          new_path = parent.to_path_buf();
92        } else {
93          return Err(());
94        }
95      } else {
96        new_path.push(part);
97      }
98    }
99  }
100  Ok(new_path)
101}
102
103//go from seconds to minutes:seconds
104pub fn format_seconds(seconds: u64) -> String {
105  let mut m = (seconds / 60).to_string(); //automatically rounds down
106  if m.len() == 1 {
107    m = "0".to_string() + &m;
108  }
109  let mut s = (seconds % 60).to_string();
110  if s.len() == 1 {
111    s = "0".to_string() + &s;
112  }
113  m + ":" + &s
114}
115
116pub const HEX_CHARS: [char; 16] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
117
118pub fn u8_to_hex(u: u8) -> String {
119  let mut h = String::new();
120  h.push(HEX_CHARS[(u / 16) as usize]);
121  h.push(HEX_CHARS[(u % 16) as usize]);
122  h
123}
124
125pub fn hex_to_u8(c1: char, c2: char) -> u8 {
126  (HEX_CHARS.iter().position(|c| c == &c1).unwrap() * 16 + HEX_CHARS.iter().position(|c| c == &c2).unwrap()) as u8
127}
128
129pub fn is_hex(c: char) -> bool {
130  HEX_CHARS.iter().position(|hc| hc == &c).is_some()
131}
132
133pub fn point_inside(point: Point, top_left: Point, size: Dimensions) -> bool {
134  let x = point[0];
135  let y = point[1];
136  let x2 = top_left[0];
137  let y2 = top_left[1];
138  let x3 = x2 + size[0];
139  let y3 = y2 + size[1];
140  x >= x2 && y >= y2 && x <= x3 && y <= y3
141}
142
143pub fn get_rest_of_split(split: &mut dyn Iterator<Item = &str>, sep: Option<&str>) -> String {
144  let mut rest = String::new();
145  let mut n = split.next();
146  loop {
147    if n.is_none() {
148      break;
149    }
150    rest += &n.unwrap();
151    n = split.next();
152    if n.is_some() && sep.is_some() {
153      rest += sep.unwrap();
154    }
155  }
156  rest
157}
158