use serde::Deserialize;
use std::collections::HashMap;
use std::fs::File;
use std::io::BufReader;
#[derive(Debug, Deserialize, Clone)]
pub struct IconData {
pub title: String,
pub hex: String,
pub source: String,
pub aliases: Option<Aliases>,
pub guidelines: Option<String>,
pub license: Option<License>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct Aliases {
pub aka: Option<Vec<String>>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct License {
#[serde(rename = "type")]
pub license_type: Option<String>,
}
pub struct Icon {
icons: Vec<IconData>,
name_map: HashMap<String, usize>,
}
impl Icon {
pub fn new() -> Self {
let file = File::open("data/simple-icons.json").expect("无法打开 simple-icons.json");
let reader = BufReader::new(file);
let icons: Vec<IconData> = serde_json::from_reader(reader).expect("JSON 解析失败");
let mut name_map = HashMap::new();
for (i, icon) in icons.iter().enumerate() {
name_map.insert(icon.title.clone(), i);
name_map.insert(icon.title.to_lowercase(), i);
if let Some(aliases) = &icon.aliases {
if let Some(aka_vec) = &aliases.aka {
for aka in aka_vec {
name_map.insert(aka.clone(), i);
name_map.insert(aka.to_lowercase(), i);
}
}
}
}
Icon { icons, name_map }
}
pub fn get(&self, name: &str) -> Option<&IconData> {
self.name_map
.get(&name.to_lowercase())
.and_then(|&i| self.icons.get(i))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_icon() {
let icon_lib = Icon::new();
let icon = icon_lib.get(".env").expect("未找到 .env");
assert_eq!(icon.title, ".ENV");
let icon2 = icon_lib.get("Dotenv").expect("未找到 Dotenv aka");
assert_eq!(icon2.title, ".ENV");
let icon3 = icon_lib.get("不存在的名称");
assert!(icon3.is_none());
}
}