diff options
Diffstat (limited to 'pkgs/by-name/lf/lf-make-map/src/mapping/mod.rs')
-rw-r--r-- | pkgs/by-name/lf/lf-make-map/src/mapping/mod.rs | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/pkgs/by-name/lf/lf-make-map/src/mapping/mod.rs b/pkgs/by-name/lf/lf-make-map/src/mapping/mod.rs new file mode 100644 index 00000000..114fdca0 --- /dev/null +++ b/pkgs/by-name/lf/lf-make-map/src/mapping/mod.rs @@ -0,0 +1,156 @@ +use std::{ + fmt::{Display, Write}, + hash::Hash, +}; + +use log::debug; + +pub mod map_tree; + +#[derive(Clone, Debug, Eq)] +pub struct MapKey { + pub key: char, + + resolution: usize, + + /// Part of the path, used to derive the key + part_path: String, +} + +impl Hash for MapKey { + fn hash<H: std::hash::Hasher>(&self, state: &mut H) { + self.key.hash(state) + } +} + +impl PartialEq for MapKey { + fn eq(&self, other: &Self) -> bool { + self.key == other.key + } +} + +impl MapKey { + pub fn new_from_part_path(part_path: &str, resolution: usize) -> Vec<Self> { + let key = Self::part_path_to_key(&part_path, resolution); + + key.chars() + .map(|ch| Self { + key: ch, + resolution, + part_path: part_path.to_owned(), + }) + .collect() + } + + pub fn new_ones_from_path(path: &str, number_of_chars: usize) -> Vec<Self> { + let key: Vec<MapKey> = path + .split('/') + .map(|part| Self::new_from_part_path(part, number_of_chars)) + .flatten() + .collect(); + + debug!( + "Generated full MapKeys: '{}' -> '{}'", + path, + MapKey::display(&key) + ); + key + } + + pub fn increment(&self, target_resolution: usize) -> Vec<Self> { + let new_resolution = target_resolution; + + // debug!("Incrementing: '{}' ('{}')", &self, &self.part_path); + + let added_chars = if new_resolution < self.part_path.len() { + MapKey::part_path_to_key(&self.part_path, new_resolution) + } else { + let mut generated_chars = + MapKey::part_path_to_key(&self.part_path, self.part_path.len()); + + generated_chars.extend( + (0..(new_resolution - self.part_path.len())) + .into_iter() + .map(|_| self.part_path.chars().last().expect("This will exists")), + ); + + generated_chars + }; + + let part_path = self.part_path.clone(); + let output: Vec<Self> = added_chars + .chars() + .enumerate() + .map(|(res, ch)| MapKey { + key: ch, + resolution: res + 1, + part_path: part_path.clone(), + }) + .collect(); + + // debug!("Finished increment: '{}' ('{}')", MapKey::display(&output), output[0].part_path); + output + } + + pub fn display(values: &[Self]) -> String { + values.iter().map(|value| value.key.clone()).collect() + } + fn part_path_to_key(part: &str, number_of_chars: usize) -> String { + fn make(pat: char, part: &str, number_of_chars: usize) -> String { + let mut acc = String::new(); + + if !part.split(pat).all(|part| part.len() > 0) { + panic!( + "\ +Can't turn this path '{}' to a mapping. +This should not happen, please report the bug!", + part + ) + } + + let mut last_working = None; + for i in 0..number_of_chars { + for str in part.split(pat) { + if acc.len() != number_of_chars { + acc.push(match str.chars().nth(i) { + Some(ch) => ch, + None => { + if let Some(last) = last_working { + str.chars().nth(last).expect("This should always exist") + } else { + last_working = Some(i - 1); + str.chars().nth(i - 1).expect("This should always exist") + } + } + }) + } + } + } + + acc + } + + let value = if part.contains('_') && !part.starts_with('_') && !part.ends_with('_') { + make('_', part, number_of_chars) + } else if part.contains('-') && !part.starts_with('-') && !part.ends_with('-') { + make('-', part, number_of_chars) + } else { + part.chars().take(number_of_chars).collect::<String>() + }; + + assert_eq!( + value.len(), + number_of_chars, + "'{}' does not have expected length of: {}", + value, + number_of_chars + ); + value + } +} + +impl Display for MapKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_char(self.key) + } +} |