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
42pub 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 new_path = PathBuf::from(add_path);
86 } else {
87 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
103pub fn format_seconds(seconds: u64) -> String {
105 let mut m = (seconds / 60).to_string(); 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