aboutsummaryrefslogtreecommitdiffstats
path: root/pkgs/sources/lf-make-map/src/mapping/mod.rs
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-05-20 16:10:21 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-05-20 16:14:26 +0200
commit368cb6b0d25db2ae23be42ad51584de059997e51 (patch)
tree3282e45d3ebced63c8498a47e83a255c35de620b /pkgs/sources/lf-make-map/src/mapping/mod.rs
parentrefactor(hm): Rename to `modules/home` (diff)
downloadnixos-config-368cb6b0d25db2ae23be42ad51584de059997e51.zip
refactor(sys): Modularize and move to `modules/system` or `pkgs`
Diffstat (limited to 'pkgs/sources/lf-make-map/src/mapping/mod.rs')
-rw-r--r--pkgs/sources/lf-make-map/src/mapping/mod.rs156
1 files changed, 156 insertions, 0 deletions
diff --git a/pkgs/sources/lf-make-map/src/mapping/mod.rs b/pkgs/sources/lf-make-map/src/mapping/mod.rs
new file mode 100644
index 00000000..114fdca0
--- /dev/null
+++ b/pkgs/sources/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)
+ }
+}