grafix_toolbox/kit/policies/func/
vec.rs1use crate::{lib::*, math::*};
2use std::hash::Hash;
3
4pub trait Utf8Len {
5 fn utf8_len_at<T>(&self, idx: T) -> usize
6 where
7 usize: Cast<T>;
8 fn utf8_count(&self) -> usize;
9 fn utf8_slice(&self, r: impl uRange) -> &str;
10 fn slice(&self, r: impl uRange) -> &str;
11}
12impl Utf8Len for str {
13 fn utf8_len_at<T>(&self, char_idx: T) -> usize
14 where
15 usize: Cast<T>,
16 {
17 let char_idx = usize(char_idx);
18 self.char_indices()
19 .enumerate()
20 .take(char_idx + 1)
21 .last()
22 .map_or(0, |(n, (i, _))| if n == char_idx { i } else { self.len() })
23 }
24 fn utf8_count(&self) -> usize {
25 self.chars().count()
26 }
27 fn utf8_slice(&self, r: impl uRange) -> &str {
28 let (b, e) = r.get_range();
29 let beg = self.utf8_len_at(b);
30 if e == usize::MAX {
31 return &self[beg..];
32 }
33
34 let end = self[beg..].utf8_len_at(e - b);
35 &self[beg..beg + end]
36 }
37 fn slice(&self, r: impl uRange) -> &str {
38 let (b, e) = r.get_range().fmin(self.len());
39 &self[b..e]
40 }
41}
42
43pub trait CountItems<T: Eq + Hash>: Sized + Iterator<Item = T> {
44 fn map_count(self) -> HashMap<T, usize> {
45 let mut map = HashMap::new();
46 for i in self {
47 *map.entry(i).or_default() += 1;
48 }
49 map
50 }
51}
52impl<T: Eq + Hash, V: Sized + Iterator<Item = T>> CountItems<T> for V {}
53
54pub trait CollectVec<T>: Sized + Iterator<Item = T> {
55 fn collect_vec(self) -> Vec<T> {
56 self.collect()
57 }
58 fn collect_box(self) -> Box<[T]> {
59 self.collect()
60 }
61 fn collect_arr<const N: usize>(self) -> [T; N] {
62 let vec = self.collect_vec();
63 vec.try_into()
64 .map_err(|v: Vec<_>| format!("Cannot collect [_][..{}] into [{}; {N}]", v.len(), type_name::<T>()))
65 .fail()
66 }
67}
68impl<V: Sized + Iterator<Item = T>, T> CollectVec<T> for V {}