use crate::errors::AtomicResult;
use std::collections::hash_map::IntoIter;
use std::{collections::HashMap, fs, path::Path};
#[derive(Clone)]
pub struct Mapping {
hashmap: HashMap<String, String>,
}
impl Mapping {
pub fn init() -> Mapping {
let hashmap: HashMap<String, String> = HashMap::new();
Mapping { hashmap }
}
pub fn try_mapping_or_url(&self, mapping_or_url: &str) -> Option<String> {
match self.get(mapping_or_url) {
Some(hit) => Some(hit.into()),
None => {
if is_url(mapping_or_url) {
return Some(mapping_or_url.into());
}
None
}
}
}
pub fn insert(&mut self, shortname: String, url: String) {
self.hashmap.insert(shortname, url);
}
pub fn get(&self, bookmark: &str) -> Option<&String> {
self.hashmap.get(bookmark)
}
pub fn read_mapping_from_file(&mut self, path: &Path) -> AtomicResult<()> {
let mapping_string = std::fs::read_to_string(path)?;
self.parse_mapping(&mapping_string)?;
Ok(())
}
pub fn parse_mapping(&mut self, mapping_string: &str) -> AtomicResult<()> {
for line in mapping_string.lines() {
match line.chars().next() {
Some('#') => {}
Some(' ') => {}
Some(_) => {
let split: Vec<&str> = line.split('=').collect();
if split.len() == 2 {
self.hashmap
.insert(String::from(split[0]), String::from(split[1]));
} else {
return Err(format!("Error reading line {:?}", line).into());
};
}
None => {}
};
}
Ok(())
}
pub fn contains_key(&self, key: &str) -> bool {
self.hashmap.contains_key(key)
}
pub fn write_mapping_to_disk(&self, path: &Path) {
let mut file_string: String = String::new();
for (key, url) in self.hashmap.clone().iter() {
let map = format!("{}={}\n", key, url);
file_string.push_str(&map);
}
fs::create_dir_all(path.parent().expect("Cannot create above root"))
.expect("Unable to create dirs");
fs::write(path, file_string).expect("Unable to write file");
}
pub fn populate(&mut self) -> AtomicResult<()> {
let mapping = include_str!("../defaults/default_mapping.amp");
self.parse_mapping(mapping)?;
Ok(())
}
}
pub fn is_url(string: &str) -> bool {
string.starts_with("http") || string.starts_with("_:")
}
impl IntoIterator for Mapping {
type Item = (String, String);
type IntoIter = IntoIter<String, String>;
fn into_iter(self) -> Self::IntoIter {
self.hashmap.into_iter()
}
}