removed languages.json and territories.json

lib.rs is separated into src/modules now for cleaner code

optimized error handling to -> (storage.rs, uptime.rs, meta.rs, memory.rs, os.rs, network.rs)
optimized struct types to -> (storage.rs, uptime.rs, meta.rs, memory.rs, os.rs, network.rs)
This commit is contained in:
D0RYU 2025-05-01 19:02:59 -04:00
parent 91c80d0f91
commit 528d4b03a3
28 changed files with 1261 additions and 1726 deletions

View file

@ -4,8 +4,9 @@ version = "0.1.0"
edition = "2024"
[dependencies]
anyhow = "1.0.98"
ash = "0.38.0"
chrono = "0.4.40"
chrono = { version = "0.4.40", features = ["serde"] }
detect-desktop-environment = "1.2.0"
hidapi = "2.6.3"
humansize = "2.1.3"
@ -13,7 +14,9 @@ metal = { version = "0.32.0", optional = true }
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140"
sys-locale = "0.3.2"
sysinfo = "0.34.2"
sysinfo = { version = "0.34.2", features = ["serde"] }
timeago = "0.4.2"
versions = { version = "7.0.0", features = ["serde"] }
wgpu = "25.0.0"
winit = "0.30.9"

View file

@ -11,23 +11,11 @@ fn main() {
.and_then(|o| String::from_utf8(o.stdout).ok())
.unwrap_or_else(|| "unknown".into());
let commit_short_hash = Command::new("git")
.args(["rev-parse", "--short", "HEAD"])
.output()
.ok()
.and_then(|o| String::from_utf8(o.stdout).ok())
.unwrap_or_else(|| "unknown".into());
writeln!(f, "#[allow(dead_code)]").unwrap();
writeln!(
f,
"pub const GIT_COMMIT_HASH: &str = \"{}\";",
commit_hash.trim()
)
.unwrap();
writeln!(
f,
"pub const GIT_COMMIT_SHORT_HASH: &str = \"{}\";",
commit_short_hash.trim()
)
.unwrap();
}

View file

@ -1,684 +0,0 @@
{
"aa": "Afar",
"ab": "Abkhazian",
"ace": "Acehnese",
"ach": "Acoli",
"ada": "Adangme",
"ady": "Adyghe",
"ae": "Avestan",
"aeb": "Tunisian Arabic",
"af": "Afrikaans",
"afh": "Afrihili",
"agq": "Aghem",
"ain": "Ainu",
"ak": "Akan",
"akk": "Akkadian",
"akz": "Alabama",
"ale": "Aleut",
"aln": "Gheg Albanian",
"alt": "Southern Altai",
"am": "Amharic",
"an": "Aragonese",
"ang": "Old English",
"ann": "Obolo",
"anp": "Angika",
"ar": "Arabic",
"ar-001": "Modern Standard Arabic",
"arc": "Aramaic",
"arn": "Mapuche",
"aro": "Araona",
"arp": "Arapaho",
"arq": "Algerian Arabic",
"ars": "Najdi Arabic",
"ars-alt-menu": "Arabic, Najdi",
"arw": "Arawak",
"ary": "Moroccan Arabic",
"arz": "Egyptian Arabic",
"as": "Assamese",
"asa": "Asu",
"ase": "American Sign Language",
"ast": "Asturian",
"atj": "Atikamekw",
"av": "Avaric",
"avk": "Kotava",
"awa": "Awadhi",
"ay": "Aymara",
"az": "Azerbaijani",
"az-alt-short": "Azeri",
"ba": "Bashkir",
"bal": "Baluchi",
"ban": "Balinese",
"bar": "Bavarian",
"bas": "Basaa",
"bax": "Bamun",
"bbc": "Batak Toba",
"bbj": "Ghomala",
"be": "Belarusian",
"bej": "Beja",
"bem": "Bemba",
"bew": "Betawi",
"bez": "Bena",
"bfd": "Bafut",
"bfq": "Badaga",
"bg": "Bulgarian",
"bgc": "Haryanvi",
"bgn": "Western Balochi",
"bho": "Bhojpuri",
"bi": "Bislama",
"bik": "Bikol",
"bin": "Bini",
"bjn": "Banjar",
"bkm": "Kom",
"bla": "Siksika",
"blo": "Anii",
"blt": "Tai Dam",
"bm": "Bambara",
"bn": "Bangla",
"bo": "Tibetan",
"bpy": "Bishnupriya",
"bqi": "Bakhtiari",
"br": "Breton",
"bra": "Braj",
"brh": "Brahui",
"brx": "Bodo",
"bs": "Bosnian",
"bss": "Akoose",
"bua": "Buriat",
"bug": "Buginese",
"bum": "Bulu",
"byn": "Blin",
"byv": "Medumba",
"ca": "Catalan",
"cad": "Caddo",
"car": "Carib",
"cay": "Cayuga",
"cch": "Atsam",
"ccp": "Chakma",
"ce": "Chechen",
"ceb": "Cebuano",
"cgg": "Chiga",
"ch": "Chamorro",
"chb": "Chibcha",
"chg": "Chagatai",
"chk": "Chuukese",
"chm": "Mari",
"chn": "Chinook Jargon",
"cho": "Choctaw",
"chp": "Chipewyan",
"chr": "Cherokee",
"chy": "Cheyenne",
"cic": "Chickasaw",
"ckb": "Central Kurdish",
"ckb-alt-menu": "Kurdish, Central",
"ckb-alt-variant": "Kurdish, Sorani",
"clc": "Chilcotin",
"co": "Corsican",
"cop": "Coptic",
"cps": "Capiznon",
"cr": "Cree",
"cr-alt-long": "Woods Cree",
"crg": "Michif",
"crh": "Crimean Tatar",
"crj": "Southern East Cree",
"crk": "Plains Cree",
"crl": "Northern East Cree",
"crm": "Moose Cree",
"crr": "Carolina Algonquian",
"crs": "Seselwa Creole French",
"cs": "Czech",
"csb": "Kashubian",
"csw": "Swampy Cree",
"cu": "Church Slavic",
"cv": "Chuvash",
"cy": "Welsh",
"da": "Danish",
"dak": "Dakota",
"dar": "Dargwa",
"dav": "Taita",
"de": "German",
"de-AT": "Austrian German",
"de-CH": "Swiss High German",
"del": "Delaware",
"den": "Slave",
"dgr": "Dogrib",
"din": "Dinka",
"dje": "Zarma",
"doi": "Dogri",
"dsb": "Lower Sorbian",
"dtp": "Central Dusun",
"dua": "Duala",
"dum": "Middle Dutch",
"dv": "Divehi",
"dyo": "Jola-Fonyi",
"dyu": "Dyula",
"dz": "Dzongkha",
"dzg": "Dazaga",
"ebu": "Embu",
"ee": "Ewe",
"efi": "Efik",
"egl": "Emilian",
"egy": "Ancient Egyptian",
"eka": "Ekajuk",
"el": "Greek",
"elx": "Elamite",
"en": "English",
"en-AU": "Australian English",
"en-CA": "Canadian English",
"en-GB": "British English",
"en-GB-alt-short": "UK English",
"en-US": "American English",
"en-US-alt-short": "US English",
"enm": "Middle English",
"eo": "Esperanto",
"es": "Spanish",
"es-419": "Latin American Spanish",
"es-ES": "European Spanish",
"es-MX": "Mexican Spanish",
"esu": "Central Yupik",
"et": "Estonian",
"eu": "Basque",
"ewo": "Ewondo",
"ext": "Extremaduran",
"fa": "Persian",
"fa-AF": "Dari",
"fan": "Fang",
"fat": "Fanti",
"ff": "Fula",
"fi": "Finnish",
"fil": "Filipino",
"fit": "Tornedalen Finnish",
"fj": "Fijian",
"fo": "Faroese",
"fon": "Fon",
"fr": "French",
"fr-CA": "Canadian French",
"fr-CH": "Swiss French",
"frc": "Cajun French",
"frm": "Middle French",
"fro": "Old French",
"frp": "Arpitan",
"frr": "Northern Frisian",
"frs": "Eastern Frisian",
"fur": "Friulian",
"fy": "Western Frisian",
"ga": "Irish",
"gaa": "Ga",
"gag": "Gagauz",
"gan": "Gan Chinese",
"gay": "Gayo",
"gba": "Gbaya",
"gbz": "Zoroastrian Dari",
"gd": "Scottish Gaelic",
"gez": "Geez",
"gil": "Gilbertese",
"gl": "Galician",
"glk": "Gilaki",
"gmh": "Middle High German",
"gn": "Guarani",
"goh": "Old High German",
"gon": "Gondi",
"gor": "Gorontalo",
"got": "Gothic",
"grb": "Grebo",
"grc": "Ancient Greek",
"gsw": "Swiss German",
"gu": "Gujarati",
"guc": "Wayuu",
"gur": "Frafra",
"guz": "Gusii",
"gv": "Manx",
"gwi": "Gwichʼin",
"ha": "Hausa",
"hai": "Haida",
"hak": "Hakka Chinese",
"haw": "Hawaiian",
"hax": "Southern Haida",
"he": "Hebrew",
"hi": "Hindi",
"hi-Latn": "Hindi (Latin)",
"hi-Latn-alt-variant": "Hinglish",
"hif": "Fiji Hindi",
"hil": "Hiligaynon",
"hit": "Hittite",
"hmn": "Hmong",
"hnj": "Hmong Njua",
"ho": "Hiri Motu",
"hr": "Croatian",
"hsb": "Upper Sorbian",
"hsn": "Xiang Chinese",
"ht": "Haitian Creole",
"hu": "Hungarian",
"hup": "Hupa",
"hur": "Halkomelem",
"hy": "Armenian",
"hz": "Herero",
"ia": "Interlingua",
"iba": "Iban",
"ibb": "Ibibio",
"id": "Indonesian",
"ie": "Interlingue",
"ig": "Igbo",
"ii": "Sichuan Yi",
"ik": "Inupiaq",
"ikt": "Western Canadian Inuktitut",
"ilo": "Iloko",
"inh": "Ingush",
"io": "Ido",
"is": "Icelandic",
"it": "Italian",
"iu": "Inuktitut",
"izh": "Ingrian",
"ja": "Japanese",
"jam": "Jamaican Creole English",
"jbo": "Lojban",
"jgo": "Ngomba",
"jmc": "Machame",
"jpr": "Judeo-Persian",
"jrb": "Judeo-Arabic",
"jut": "Jutish",
"jv": "Javanese",
"ka": "Georgian",
"kaa": "Kara-Kalpak",
"kab": "Kabyle",
"kac": "Kachin",
"kaj": "Jju",
"kam": "Kamba",
"kaw": "Kawi",
"kbd": "Kabardian",
"kbl": "Kanembu",
"kcg": "Tyap",
"kde": "Makonde",
"kea": "Kabuverdianu",
"ken": "Kenyang",
"kfo": "Koro",
"kg": "Kongo",
"kgp": "Kaingang",
"kha": "Khasi",
"kho": "Khotanese",
"khq": "Koyra Chiini",
"khw": "Khowar",
"ki": "Kikuyu",
"kiu": "Kirmanjki",
"kj": "Kuanyama",
"kk": "Kazakh",
"kkj": "Kako",
"kl": "Kalaallisut",
"kln": "Kalenjin",
"km": "Khmer",
"kmb": "Kimbundu",
"kn": "Kannada",
"ko": "Korean",
"koi": "Komi-Permyak",
"kok": "Konkani",
"kos": "Kosraean",
"kpe": "Kpelle",
"kr": "Kanuri",
"krc": "Karachay-Balkar",
"kri": "Krio",
"krj": "Kinaray-a",
"krl": "Karelian",
"kru": "Kurukh",
"ks": "Kashmiri",
"ksb": "Shambala",
"ksf": "Bafia",
"ksh": "Colognian",
"ku": "Kurdish",
"kum": "Kumyk",
"kut": "Kutenai",
"kv": "Komi",
"kw": "Cornish",
"kwk": "Kwakʼwala",
"kxv": "Kuvi",
"ky": "Kyrgyz",
"ky-alt-variant": "Kirghiz",
"la": "Latin",
"lad": "Ladino",
"lag": "Langi",
"lah": "Western Panjabi",
"lam": "Lamba",
"lb": "Luxembourgish",
"lez": "Lezghian",
"lfn": "Lingua Franca Nova",
"lg": "Ganda",
"li": "Limburgish",
"lij": "Ligurian",
"lil": "Lillooet",
"liv": "Livonian",
"lkt": "Lakota",
"lmo": "Lombard",
"ln": "Lingala",
"lo": "Lao",
"lol": "Mongo",
"lou": "Louisiana Creole",
"loz": "Lozi",
"lrc": "Northern Luri",
"lsm": "Saamia",
"lt": "Lithuanian",
"ltg": "Latgalian",
"lu": "Luba-Katanga",
"lua": "Luba-Lulua",
"lui": "Luiseno",
"lun": "Lunda",
"luo": "Luo",
"lus": "Mizo",
"luy": "Luyia",
"lv": "Latvian",
"lzh": "Literary Chinese",
"lzz": "Laz",
"mad": "Madurese",
"maf": "Mafa",
"mag": "Magahi",
"mai": "Maithili",
"mak": "Makasar",
"man": "Mandingo",
"mas": "Masai",
"mde": "Maba",
"mdf": "Moksha",
"mdr": "Mandar",
"men": "Mende",
"mer": "Meru",
"mfe": "Morisyen",
"mg": "Malagasy",
"mga": "Middle Irish",
"mgh": "Makhuwa-Meetto",
"mgo": "Metaʼ",
"mh": "Marshallese",
"mi": "Māori",
"mic": "Mi'kmaw",
"min": "Minangkabau",
"mk": "Macedonian",
"ml": "Malayalam",
"mn": "Mongolian",
"mnc": "Manchu",
"mni": "Manipuri",
"moe": "Innu-aimun",
"moh": "Mohawk",
"mos": "Mossi",
"mr": "Marathi",
"mrj": "Western Mari",
"ms": "Malay",
"mt": "Maltese",
"mua": "Mundang",
"mul": "Multiple languages",
"mus": "Creek",
"mus-alt-official": "Mvskoke",
"mwl": "Mirandese",
"mwr": "Marwari",
"mwv": "Mentawai",
"my": "Burmese",
"my-alt-variant": "Myanmar Language",
"mye": "Myene",
"myv": "Erzya",
"mzn": "Mazanderani",
"na": "Nauru",
"nan": "Min Nan Chinese",
"nap": "Neapolitan",
"naq": "Nama",
"nb": "Norwegian Bokmål",
"nd": "North Ndebele",
"nds": "Low German",
"nds-NL": "West Low German",
"ne": "Nepali",
"new": "Newari",
"ng": "Ndonga",
"nia": "Nias",
"niu": "Niuean",
"njo": "Ao Naga",
"nl": "Dutch",
"nl-BE": "Flemish",
"nmg": "Kwasio",
"nn": "Norwegian Nynorsk",
"nnh": "Ngiemboon",
"no": "Norwegian",
"nog": "Nogai",
"non": "Old Norse",
"nov": "Novial",
"nqo": "NKo",
"nr": "South Ndebele",
"nso": "Northern Sotho",
"nus": "Nuer",
"nv": "Navajo",
"nwc": "Classical Newari",
"ny": "Nyanja",
"nym": "Nyamwezi",
"nyn": "Nyankole",
"nyo": "Nyoro",
"nzi": "Nzima",
"oc": "Occitan",
"oj": "Ojibwa",
"ojb": "Northwestern Ojibwa",
"ojc": "Central Ojibwa",
"ojs": "Oji-Cree",
"ojw": "Western Ojibwa",
"oka": "Okanagan",
"om": "Oromo",
"or": "Odia",
"os": "Ossetic",
"osa": "Osage",
"ota": "Ottoman Turkish",
"pa": "Punjabi",
"pag": "Pangasinan",
"pal": "Pahlavi",
"pam": "Pampanga",
"pap": "Papiamento",
"pau": "Palauan",
"pcd": "Picard",
"pcm": "Nigerian Pidgin",
"pdc": "Pennsylvania German",
"pdt": "Plautdietsch",
"peo": "Old Persian",
"pfl": "Palatine German",
"phn": "Phoenician",
"pi": "Pali",
"pis": "Pijin",
"pl": "Polish",
"pms": "Piedmontese",
"pnt": "Pontic",
"pon": "Pohnpeian",
"pqm": "Maliseet-Passamaquoddy",
"prg": "Prussian",
"pro": "Old Provençal",
"ps": "Pashto",
"ps-alt-variant": "Pushto",
"pt": "Portuguese",
"pt-BR": "Brazilian Portuguese",
"pt-PT": "European Portuguese",
"qu": "Quechua",
"quc": "Kʼicheʼ",
"qug": "Chimborazo Highland Quichua",
"raj": "Rajasthani",
"rap": "Rapanui",
"rar": "Rarotongan",
"rgn": "Romagnol",
"rhg": "Rohingya",
"rif": "Riffian",
"rm": "Romansh",
"rn": "Rundi",
"ro": "Romanian",
"ro-MD": "Moldavian",
"rof": "Rombo",
"rom": "Romany",
"rtm": "Rotuman",
"ru": "Russian",
"rue": "Rusyn",
"rug": "Roviana",
"rup": "Aromanian",
"rw": "Kinyarwanda",
"rwk": "Rwa",
"sa": "Sanskrit",
"sad": "Sandawe",
"sah": "Yakut",
"sam": "Samaritan Aramaic",
"saq": "Samburu",
"sas": "Sasak",
"sat": "Santali",
"saz": "Saurashtra",
"sba": "Ngambay",
"sbp": "Sangu",
"sc": "Sardinian",
"scn": "Sicilian",
"sco": "Scots",
"sd": "Sindhi",
"sdc": "Sassarese Sardinian",
"sdh": "Southern Kurdish",
"se": "Northern Sami",
"se-alt-menu": "Sami, Northern",
"see": "Seneca",
"seh": "Sena",
"sei": "Seri",
"sel": "Selkup",
"ses": "Koyraboro Senni",
"sg": "Sango",
"sga": "Old Irish",
"sgs": "Samogitian",
"sh": "Serbo-Croatian",
"shi": "Tachelhit",
"shn": "Shan",
"shu": "Chadian Arabic",
"si": "Sinhala",
"sid": "Sidamo",
"sk": "Slovak",
"sl": "Slovenian",
"slh": "Southern Lushootseed",
"sli": "Lower Silesian",
"sly": "Selayar",
"sm": "Samoan",
"sma": "Southern Sami",
"sma-alt-menu": "Sami, Southern",
"smj": "Lule Sami",
"smj-alt-menu": "Sami, Lule",
"smn": "Inari Sami",
"smn-alt-menu": "Sami, Inari",
"sms": "Skolt Sami",
"sms-alt-menu": "Sami, Skolt",
"sn": "Shona",
"snk": "Soninke",
"so": "Somali",
"sog": "Sogdien",
"sq": "Albanian",
"sr": "Serbian",
"sr-ME": "Montenegrin",
"srn": "Sranan Tongo",
"srr": "Serer",
"ss": "Swati",
"ssy": "Saho",
"st": "Southern Sotho",
"stq": "Saterland Frisian",
"str": "Straits Salish",
"su": "Sundanese",
"suk": "Sukuma",
"sus": "Susu",
"sux": "Sumerian",
"sv": "Swedish",
"sw": "Swahili",
"sw-CD": "Congo Swahili",
"swb": "Comorian",
"syc": "Classical Syriac",
"syr": "Syriac",
"szl": "Silesian",
"ta": "Tamil",
"tce": "Southern Tutchone",
"tcy": "Tulu",
"te": "Telugu",
"tem": "Timne",
"teo": "Teso",
"ter": "Tereno",
"tet": "Tetum",
"tg": "Tajik",
"tgx": "Tagish",
"th": "Thai",
"tht": "Tahltan",
"ti": "Tigrinya",
"tig": "Tigre",
"tiv": "Tiv",
"tk": "Turkmen",
"tkl": "Tokelau",
"tkr": "Tsakhur",
"tl": "Tagalog",
"tlh": "Klingon",
"tli": "Tlingit",
"tly": "Talysh",
"tmh": "Tamashek",
"tn": "Tswana",
"to": "Tongan",
"tog": "Nyasa Tonga",
"tok": "Toki Pona",
"tpi": "Tok Pisin",
"tr": "Turkish",
"tru": "Turoyo",
"trv": "Taroko",
"trw": "Torwali",
"ts": "Tsonga",
"tsd": "Tsakonian",
"tsi": "Tsimshian",
"tt": "Tatar",
"ttm": "Northern Tutchone",
"ttt": "Muslim Tat",
"tum": "Tumbuka",
"tvl": "Tuvalu",
"tw": "Twi",
"twq": "Tasawaq",
"ty": "Tahitian",
"tyv": "Tuvinian",
"tzm": "Central Atlas Tamazight",
"udm": "Udmurt",
"ug": "Uyghur",
"ug-alt-variant": "Uighur",
"uga": "Ugaritic",
"uk": "Ukrainian",
"umb": "Umbundu",
"und": "Unknown language",
"ur": "Urdu",
"uz": "Uzbek",
"vai": "Vai",
"ve": "Venda",
"vec": "Venetian",
"vep": "Veps",
"vi": "Vietnamese",
"vls": "West Flemish",
"vmf": "Main-Franconian",
"vmw": "Makhuwa",
"vo": "Volapük",
"vot": "Votic",
"vro": "Võro",
"vun": "Vunjo",
"wa": "Walloon",
"wae": "Walser",
"wal": "Wolaytta",
"war": "Waray",
"was": "Washo",
"wbp": "Warlpiri",
"wo": "Wolof",
"wuu": "Wu Chinese",
"xal": "Kalmyk",
"xh": "Xhosa",
"xmf": "Mingrelian",
"xnr": "Kangri",
"xog": "Soga",
"yao": "Yao",
"yap": "Yapese",
"yav": "Yangben",
"ybb": "Yemba",
"yi": "Yiddish",
"yo": "Yoruba",
"yrl": "Nheengatu",
"yue": "Cantonese",
"yue-alt-menu": "Chinese, Cantonese",
"za": "Zhuang",
"zap": "Zapotec",
"zbl": "Blissymbols",
"zea": "Zeelandic",
"zen": "Zenaga",
"zgh": "Standard Moroccan Tamazight",
"zh": "Chinese",
"zh-alt-long": "Mandarin Chinese",
"zh-alt-menu": "Chinese, Mandarin",
"zh-Hans": "Simplified Chinese",
"zh-Hans-alt-long": "Simplified Mandarin Chinese",
"zh-Hant": "Traditional Chinese",
"zh-Hant-alt-long": "Traditional Mandarin Chinese",
"zu": "Zulu",
"zun": "Zuni",
"zxx": "No linguistic content",
"zza": "Zaza"
}

View file

@ -1,677 +1,9 @@
use serde::Serialize;
use serde_json::{Value, json};
pub mod gpu {
use serde::Serialize;
use serde_json::{Value, json};
use wgpu;
use winit::{
application::ApplicationHandler,
event::WindowEvent,
event_loop::{ActiveEventLoop, EventLoop},
window::WindowId,
};
#[derive(Debug, Serialize)]
pub struct DriverInfo {
version: String,
name: String,
}
#[derive(Debug, Serialize)]
pub struct AdapterInfo {
vendor: String,
model: String,
driver: DriverInfo,
vram: String,
display: DisplayInfo,
}
#[derive(Debug, Serialize)]
pub struct GPUInfo {
supported_backends: Vec<String>,
gpus: Vec<AdapterInfo>,
}
#[derive(Debug, Serialize, Default)]
pub struct DisplayInfo {
resolution: String,
refresh_rate: String,
}
impl ApplicationHandler for DisplayInfo {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
if let Some(monitor) = event_loop.primary_monitor() {
let size = monitor.size();
let refresh_rate = monitor.refresh_rate_millihertz();
self.resolution = format!("{}x{}", size.width, size.height);
self.refresh_rate = if let Some(refresh) = refresh_rate {
format!("{} hz", refresh / 1000)
} else {
String::from("Unknown")
}
} else {
self.resolution = String::from("Unknown");
self.refresh_rate = String::from("Unknown");
}
event_loop.exit();
}
fn window_event(
&mut self,
_event_loop: &ActiveEventLoop,
_window_id: WindowId,
_event: WindowEvent,
) {
}
}
mod vram {
use ash::vk::{API_VERSION_1_2, ApplicationInfo, InstanceCreateInfo, MemoryHeapFlags};
use humansize::{DECIMAL, make_format};
#[cfg(not(target_os = "macos"))]
pub fn get_metal() -> u64 {
0
}
#[cfg(target_os = "macos")]
pub fn get_metal() -> u64 {
use metal::Device as MetalDevice;
let device = MetalDevice::system_default().expect("No Metal-compatible GPU found");
device.recommended_max_working_set_size()
}
pub fn get_vulkan(device_id: u32) -> u64 {
let entry = unsafe { ash::Entry::load().unwrap() };
let app_info = ApplicationInfo {
p_application_name: std::ptr::null(),
application_version: 0,
p_engine_name: std::ptr::null(),
engine_version: 0,
api_version: API_VERSION_1_2,
..Default::default()
};
let create_info = InstanceCreateInfo {
p_application_info: &app_info,
..Default::default()
};
let instance = unsafe { entry.create_instance(&create_info, None).unwrap() };
let physical_devices = unsafe { instance.enumerate_physical_devices().unwrap() };
let mut total_vram = 0;
for device in physical_devices {
let memory_properties =
unsafe { instance.get_physical_device_memory_properties(device) };
let device_properties = unsafe { instance.get_physical_device_properties(device) };
if device_id != device_properties.device_id {
continue;
}
for heap in memory_properties.memory_heaps {
if heap.flags.contains(MemoryHeapFlags::DEVICE_LOCAL) {
total_vram += heap.size;
}
}
break;
}
total_vram
}
pub fn get(vendor: u32, device_id: u32) -> String {
let formatter = make_format(DECIMAL);
match vendor {
0x10DE | 0x1002 | 0x8086 | 0x5143 => formatter(get_vulkan(device_id)),
0x1010 => formatter(get_metal()),
_ => String::from("Unknown"),
}
}
}
fn vendor_name(vendor: u32) -> &'static str {
match vendor {
0x10DE => "NVIDIA",
0x1002 => "AMD(Advanced Micro Devices), Inc.",
0x8086 => "Intel(integrated electronics)",
0x13B5 => "ARM(Advanced RISC Machines)",
0x5143 => "Qualcomm(Quality Communications)",
0x1010 => "Apple Inc.",
_ => "Unknown",
}
}
pub fn get_struct() -> GPUInfo {
let mut gpu_data: Vec<AdapterInfo> = Vec::new();
let mut backends: Vec<String> = Vec::new();
let instance_descriptor = wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
flags: wgpu::InstanceFlags::empty(),
backend_options: Default::default(),
};
let instance = wgpu::Instance::new(&instance_descriptor);
let event_loop = EventLoop::new().unwrap();
let mut app = DisplayInfo::default();
event_loop.run_app(&mut app).unwrap();
for adapter in instance.enumerate_adapters(wgpu::Backends::all()) {
let info = adapter.get_info();
if !backends.contains(&info.backend.to_string()) {
backends.push(info.backend.to_string());
}
if info.driver.is_empty() || info.driver_info.is_empty() {
continue;
}
gpu_data.push(AdapterInfo {
vendor: vendor_name(info.vendor).to_string(),
model: info.name,
driver: DriverInfo {
version: info.driver_info,
name: info.driver,
},
vram: vram::get(info.vendor, info.device),
display: DisplayInfo {
resolution: app.resolution.to_string(),
refresh_rate: app.refresh_rate.to_string(),
},
});
}
GPUInfo {
supported_backends: backends,
gpus: gpu_data,
}
}
pub fn get_json() -> Value {
json!(get_struct())
}
}
pub mod cpu {
use serde::Serialize;
use serde_json::{Value, json};
use std::collections::HashMap;
use sysinfo::{CpuRefreshKind, RefreshKind, System};
#[derive(Debug, Serialize)]
pub struct ProcessorInfo {
vendor: String,
brand: String,
total_system_cores: String,
threads: u16,
architecture: String,
byte_order: String,
}
#[derive(Debug, Serialize)]
pub struct CPUInfo {
cpus: Vec<ProcessorInfo>,
}
pub fn get_struct() -> CPUInfo {
let system = System::new_with_specifics(
RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
);
let mut processors = Vec::new();
let mut processor_count: HashMap<String, ProcessorInfo> = HashMap::new();
for cpu in system.cpus() {
let brand = cpu.brand().trim();
let total_cores = System::physical_core_count();
if processor_count.contains_key(brand) {
processor_count.get_mut(brand).unwrap().threads += 1;
continue;
}
processor_count.insert(
brand.to_string(),
ProcessorInfo {
vendor: cpu.vendor_id().trim().to_string(),
brand: brand.to_string(),
total_system_cores: if let Some(cores) = total_cores {
cores.to_string()
} else {
String::from("Unknown")
},
threads: 1,
architecture: System::cpu_arch().trim().to_string(),
byte_order: if cfg!(target_endian = "little") {
String::from("little-endian")
} else {
String::from("big-endian")
},
},
);
}
for (_brand, info) in processor_count {
processors.push(info);
}
CPUInfo { cpus: processors }
}
pub fn get_json() -> Value {
json!(get_struct())
}
}
pub mod memory {
use humansize::{DECIMAL, make_format};
use serde::Serialize;
use serde_json::{Value, json};
use sysinfo::System;
#[derive(Debug, Serialize)]
pub struct PhysicalInfo {
total: String,
used: String,
free: String,
available: String,
}
#[derive(Debug, Serialize)]
pub struct VirtualInfo {
total: String,
used: String,
free: String,
}
#[derive(Debug, Serialize)]
pub struct MemoryInfo {
physical: PhysicalInfo,
virtual_swap: VirtualInfo,
}
pub fn get_struct() -> MemoryInfo {
let system = System::new_all();
let formatter = make_format(DECIMAL);
MemoryInfo {
physical: PhysicalInfo {
total: formatter(system.total_memory()),
used: formatter(system.used_memory()),
free: formatter(system.free_memory()),
available: formatter(system.available_memory()),
},
virtual_swap: VirtualInfo {
total: formatter(system.total_swap()),
used: formatter(system.used_swap()),
free: formatter(system.free_swap()),
},
}
}
pub fn get_json() -> Value {
json!(get_struct())
}
}
pub mod os {
use detect_desktop_environment::DesktopEnvironment;
use serde::Serialize;
use serde_json::{Value, json};
use sysinfo::System;
#[derive(Debug, Serialize)]
pub struct OSInfo {
name: String,
edition: String,
version: String,
architecture: String,
kernel: String,
de: String,
}
pub fn get_struct() -> OSInfo {
OSInfo {
name: System::name().unwrap_or(String::from("Unknown")),
edition: System::long_os_version().unwrap_or(String::from("Unknown")),
version: System::os_version().unwrap_or(String::from("Unknown")),
architecture: if cfg!(target_pointer_width = "64") {
String::from("64 bit")
} else if cfg!(target_pointer_width = "32") {
String::from("32 bit")
} else {
String::from("16 bit")
},
kernel: System::kernel_long_version(),
de: match DesktopEnvironment::detect() {
Some(de) => format!("{de:?}"),
None => String::from(""),
},
}
}
pub fn get_json() -> Value {
json!(get_struct())
}
}
pub mod storage {
use humansize::{DECIMAL, make_format};
use serde::Serialize;
use serde_json::{Value, json};
use sysinfo::Disks;
#[derive(Debug, Serialize)]
pub struct StorageInfo {
name: String,
mount_point: String,
kind: String,
space_left: String,
total: String,
}
pub fn get_list() -> Vec<StorageInfo> {
let disks = Disks::new_with_refreshed_list();
let mut drive_data = Vec::new();
let formatter = make_format(DECIMAL);
for disk in disks.list() {
drive_data.push(StorageInfo {
name: format!("{:?}", disk.name()).trim_matches('\"').to_string(),
mount_point: format!("{:?}", disk.mount_point())
.replace("\\", "")
.trim_matches('\"')
.to_string(),
kind: format!("{:?}", disk.kind()),
space_left: formatter(disk.available_space()),
total: formatter(disk.total_space()),
});
}
drive_data
}
pub fn get_json() -> Value {
json!(get_list())
}
}
pub mod network {
use serde::Serialize;
use serde_json::{Value, json};
use sysinfo::Networks;
#[derive(Debug, Serialize)]
pub struct NetworkInfo {
adapters: Vec<String>,
}
pub fn get_struct() -> NetworkInfo {
let networks = Networks::new_with_refreshed_list();
let mut adapters = Vec::new();
for (interface_name, _network_data) in &networks {
adapters.push(interface_name.to_string());
}
NetworkInfo { adapters }
}
pub fn get_json() -> Value {
json!(get_struct())
}
}
pub mod external {
use serde::Serialize;
use serde_json::{Value, json};
use std::{cmp::Ordering::Equal, collections::HashMap};
use sysinfo::{System, Users};
#[derive(Debug, Serialize)]
pub struct SoftwareInfo {
name: String,
count: usize,
}
#[derive(Debug, Serialize)]
pub struct ExternalInfo {
softwares: Vec<SoftwareInfo>,
}
pub fn get_struct() -> ExternalInfo {
let mut system = System::new_all();
system.refresh_all();
let users = &Users::new_with_refreshed_list();
let mut grouped_processes: HashMap<String, Vec<i32>> = HashMap::new();
for process in system.processes().values() {
let name = process.name().to_str().unwrap().to_string();
let user_id = process.user_id();
let is_user_owned = user_id.is_some_and(|uid| {
users
.list()
.iter()
.any(|u| u.id() == uid && u.name() != "root")
});
if is_user_owned && !name.trim().is_empty() && !name.starts_with('[') {
grouped_processes
.entry(name)
.or_default()
.push(process.pid().as_u32() as i32);
}
}
let mut softwares = Vec::new();
let mut grouped_vec: Vec<_> = grouped_processes.into_iter().collect();
grouped_vec.sort_by(|a, b| match b.1.len().cmp(&a.1.len()) {
Equal => a.0.to_lowercase().cmp(&b.0.to_lowercase()),
other => other,
});
for (name, pids) in grouped_vec {
softwares.push(SoftwareInfo {
name,
count: pids.len(),
});
}
ExternalInfo { softwares }
}
pub fn get_json() -> Value {
json!(get_struct())
}
}
pub mod devices {
use serde::Serialize;
use serde_json::{Value, json};
extern crate hidapi;
use hidapi::HidApi;
use std::collections::HashMap;
#[derive(Debug, Serialize)]
pub struct DeviceInfo {
manufacturer: String,
products: Vec<String>,
}
#[derive(Debug, Serialize)]
pub struct DevicesInfo {
devices: Vec<DeviceInfo>,
}
pub fn get_struct() -> DevicesInfo {
let api = HidApi::new().unwrap();
let mut grouped_devices: HashMap<String, Vec<String>> = HashMap::new();
for device in api.device_list() {
let manufacturer = device
.manufacturer_string()
.unwrap_or("Unknown")
.to_string()
.to_lowercase();
let product = device.product_string().unwrap_or("Unknown").to_string();
if !manufacturer.trim().is_empty() && !product.trim().is_empty() {
let entry = grouped_devices.entry(manufacturer).or_default();
if !entry.contains(&product) {
entry.push(product);
}
}
}
let mut devices = Vec::new();
let mut grouped_vec: Vec<_> = grouped_devices.into_iter().collect();
grouped_vec.sort_by(|a, b| a.0.to_lowercase().cmp(&b.0.to_lowercase()));
for (manufacturer, products) in grouped_vec {
devices.push(DeviceInfo {
manufacturer,
products,
});
}
DevicesInfo { devices }
}
pub fn get_json() -> Value {
json!(get_struct())
}
}
pub mod meta {
use serde::Serialize;
use serde_json::{Value, from_str, json};
use std::{collections::HashMap, fs};
use sys_locale::get_locale;
include!(concat!(env!("OUT_DIR"), "/built.rs"));
#[derive(Debug, Serialize)]
pub struct MetaInfo {
version: String,
commit_hash: String,
commit_short_hash: String,
locale: String,
language: String,
territory: String,
}
pub fn get_struct() -> MetaInfo {
let default = String::from("Unknown");
let locale = get_locale().unwrap_or_else(|| String::from("en-US"));
let split_locale: Vec<&str> = locale.split("-").collect();
let language_json = fs::read_to_string("subcrates/telemetry/src/languages.json").unwrap();
let parsed_languages = from_str::<HashMap<String, String>>(&language_json).unwrap();
let language_map = parsed_languages.get(split_locale[0]).unwrap_or(&default);
let territory_json =
fs::read_to_string("subcrates/telemetry/src/territories.json").unwrap();
let parsed_territories = from_str::<HashMap<String, String>>(&territory_json).unwrap();
let territory_map = parsed_territories.get(split_locale[1]).unwrap_or(&default);
MetaInfo {
version: env!("CARGO_PKG_VERSION").to_string(),
commit_hash: GIT_COMMIT_HASH.to_string(),
commit_short_hash: GIT_COMMIT_SHORT_HASH.to_string(),
locale,
language: language_map.to_string(),
territory: territory_map.to_string(),
}
}
pub fn get_json() -> Value {
json!(get_struct())
}
}
pub mod uptime {
use chrono::{DateTime, Utc};
use serde::Serialize;
use serde_json::{Value, json};
use std::time::Duration as StdDuration;
use sysinfo::System;
#[derive(Debug, Serialize)]
pub struct DateInfo {
zone: String,
date: String,
time: String,
}
#[derive(Debug, Serialize)]
pub struct UptimeInfo {
boot: DateInfo,
now: DateInfo,
relative: String,
}
pub fn format_duration(duration: StdDuration) -> String {
let mut parts = Vec::new();
let mut remaining = duration.as_secs();
let units = [
(" months", 30 * 24 * 60 * 60),
(" weeks", 7 * 24 * 60 * 60),
(" days", 24 * 60 * 60),
(" hours", 60 * 60),
(" minutes", 60),
(" seconds", 1),
];
for &(label, unit_secs) in &units {
match remaining / unit_secs {
0 => continue,
value => {
parts.push(format!("{}{}", value, label));
remaining %= unit_secs;
}
}
}
if parts.is_empty() {
parts.push("0 seconds".to_string());
}
parts.join(", ")
}
pub fn get_struct() -> UptimeInfo {
let boot_time: DateTime<Utc> =
DateTime::<Utc>::from_timestamp(System::boot_time() as i64, 0)
.expect("Invalid or out-of-range timestamp");
let relative_time = StdDuration::from_secs((Utc::now() - boot_time).num_seconds() as u64);
UptimeInfo {
boot: DateInfo {
zone: String::from("UTC"),
date: boot_time.format("%Y-%m-%d").to_string(),
time: boot_time.format("%H:%M:%S").to_string(),
},
now: DateInfo {
zone: String::from("UTC"),
date: Utc::now().format("%Y-%m-%d").to_string(),
time: Utc::now().format("%H:%M:%S").to_string(),
},
relative: format_duration(relative_time).to_string(),
}
}
pub fn get_json() -> Value {
json!(get_struct())
}
}
#[macro_use]
mod modules;
use crate::modules::{cpu, devices, external, gpu, memory, meta, network, os, storage, uptime};
use anyhow::Result;
#[derive(Debug, Serialize)]
pub struct TelemetryInfo {
@ -692,23 +24,25 @@ pub struct AllInfo {
uptime: uptime::UptimeInfo,
}
pub fn get_struct() -> TelemetryInfo {
TelemetryInfo {
#[allow(dead_code)]
pub fn get_struct() -> Result<TelemetryInfo> {
Ok(TelemetryInfo {
telemetry: AllInfo {
gpu: gpu::get_struct(),
cpu: cpu::get_struct(),
memory: memory::get_struct(),
os: os::get_struct(),
storage: storage::get_list(),
os: os::get_struct()?,
storage: storage::get_list()?,
network: network::get_struct(),
external: external::get_struct(),
devices: devices::get_struct(),
meta: meta::get_struct(),
uptime: uptime::get_struct(),
devices: devices::get_struct()?,
meta: meta::get_struct()?,
uptime: uptime::get_struct()?,
},
}
})
}
pub fn get_json() -> Value {
json!(get_struct())
#[allow(dead_code)]
pub fn get_json() -> Result<Value> {
Ok(json!(get_struct()?))
}

View file

@ -0,0 +1,69 @@
use super::Defaults::Unknown;
use serde::Serialize;
use serde_json::{Value, json};
use std::collections::HashMap;
use sysinfo::{CpuRefreshKind, RefreshKind, System};
#[derive(Debug, Serialize)]
pub struct ProcessorInfo {
vendor: String,
brand: String,
total_system_cores: String,
threads: u16,
architecture: String,
byte_order: String,
}
#[derive(Debug, Serialize)]
pub struct CPUInfo {
cpus: Vec<ProcessorInfo>,
}
#[allow(dead_code)]
pub fn get_struct() -> CPUInfo {
let system =
System::new_with_specifics(RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()));
let mut processors = Vec::new();
let mut processor_count: HashMap<String, ProcessorInfo> = HashMap::new();
for cpu in system.cpus() {
let brand = cpu.brand().trim();
let total_cores = System::physical_core_count();
if processor_count.contains_key(brand) {
processor_count.get_mut(brand).unwrap().threads += 1;
continue;
}
processor_count.insert(
brand.to_string(),
ProcessorInfo {
vendor: cpu.vendor_id().trim().to_string(),
brand: brand.to_string(),
total_system_cores: if let Some(cores) = total_cores {
cores.to_string()
} else {
Unknown.into()
},
threads: 1,
architecture: System::cpu_arch().trim().to_string(),
byte_order: if cfg!(target_endian = "little") {
String::from("little-endian")
} else {
String::from("big-endian")
},
},
);
}
for (_brand, info) in processor_count {
processors.push(info);
}
CPUInfo { cpus: processors }
}
#[allow(dead_code)]
pub fn get_json() -> Value {
json!(get_struct())
}

View file

@ -0,0 +1,59 @@
//use crate::custom_anyhow;
use anyhow::Result;
use serde::Serialize;
use serde_json::{Value, json};
extern crate hidapi;
use hidapi::HidApi;
use std::collections::HashMap;
#[derive(Debug, Serialize)]
pub struct DeviceInfo {
manufacturer: String,
products: Vec<String>,
}
#[derive(Debug, Serialize)]
pub struct DevicesInfo {
devices: Vec<DeviceInfo>,
}
#[allow(dead_code)]
pub fn get_struct() -> Result<DevicesInfo> {
let api = HidApi::new().unwrap();
let mut grouped_devices: HashMap<String, Vec<String>> = HashMap::new();
for device in api.device_list() {
let manufacturer = device
.manufacturer_string()
.unwrap_or("Unknown")
.to_string()
.to_lowercase();
let product = device.product_string().unwrap_or("Unknown").to_string();
if !manufacturer.trim().is_empty() && !product.trim().is_empty() {
let entry = grouped_devices.entry(manufacturer).or_default();
if !entry.contains(&product) {
entry.push(product);
}
}
}
let mut devices = Vec::new();
let mut grouped_vec: Vec<_> = grouped_devices.into_iter().collect();
grouped_vec.sort_by(|a, b| a.0.to_lowercase().cmp(&b.0.to_lowercase()));
for (manufacturer, products) in grouped_vec {
devices.push(DeviceInfo {
manufacturer,
products,
});
}
Ok(DevicesInfo { devices })
}
#[allow(dead_code)]
pub fn get_json() -> Result<Value> {
Ok(json!(get_struct()?))
}

View file

@ -0,0 +1,63 @@
use serde::Serialize;
use serde_json::{Value, json};
use std::{cmp::Ordering::Equal, collections::HashMap};
use sysinfo::{System, Users};
#[derive(Debug, Serialize)]
pub struct SoftwareInfo {
name: String,
count: usize,
}
#[derive(Debug, Serialize)]
pub struct ExternalInfo {
softwares: Vec<SoftwareInfo>,
}
#[allow(dead_code)]
pub fn get_struct() -> ExternalInfo {
let mut system = System::new_all();
system.refresh_all();
let users = &Users::new_with_refreshed_list();
let mut grouped_processes: HashMap<String, Vec<i32>> = HashMap::new();
for process in system.processes().values() {
let name = process.name().to_str().unwrap().to_string();
let user_id = process.user_id();
let is_user_owned = user_id.is_some_and(|uid| {
users
.list()
.iter()
.any(|u| u.id() == uid && u.name() != "root")
});
if is_user_owned && !name.trim().is_empty() && !name.starts_with('[') {
grouped_processes
.entry(name)
.or_default()
.push(process.pid().as_u32() as i32);
}
}
let mut softwares = Vec::new();
let mut grouped_vec: Vec<_> = grouped_processes.into_iter().collect();
grouped_vec.sort_by(|a, b| match b.1.len().cmp(&a.1.len()) {
Equal => a.0.to_lowercase().cmp(&b.0.to_lowercase()),
other => other,
});
for (name, pids) in grouped_vec {
softwares.push(SoftwareInfo {
name,
count: pids.len(),
});
}
ExternalInfo { softwares }
}
#[allow(dead_code)]
pub fn get_json() -> Value {
json!(get_struct())
}

View file

@ -0,0 +1,55 @@
use serde::Serialize;
use std::{
fmt::{Debug, Display, Formatter, Result as FmtResult},
ops::Deref,
};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Serialize)]
pub enum TargetPointerWidth {
W32Bit,
W64Bit,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct FmtOSArchitecture(pub TargetPointerWidth);
impl FmtOSArchitecture {
pub const W32_BIT: Self = FmtOSArchitecture(TargetPointerWidth::W32Bit);
pub const W64_BIT: Self = FmtOSArchitecture(TargetPointerWidth::W64Bit);
}
impl Display for FmtOSArchitecture {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(
f,
"{}",
match self.0 {
TargetPointerWidth::W32Bit => "32 Bit",
TargetPointerWidth::W64Bit => "64 Bit",
}
)
}
}
impl Debug for FmtOSArchitecture {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
Display::fmt(self, f)
}
}
impl Serialize for FmtOSArchitecture {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Deref for FmtOSArchitecture {
type Target = TargetPointerWidth;
fn deref(&self) -> &Self::Target {
&self.0
}
}

View file

@ -0,0 +1,38 @@
use serde::Serialize;
use std::{
fmt::{Debug, Display, Formatter, Result as FmtResult},
ops::Deref,
};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct FmtBytes(pub u64);
impl Display for FmtBytes {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
use humansize::{DECIMAL, format_size};
write!(f, "{}", format_size(self.0, DECIMAL))
}
}
impl Debug for FmtBytes {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
Display::fmt(self, f)
}
}
impl Serialize for FmtBytes {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Deref for FmtBytes {
type Target = u64;
fn deref(&self) -> &Self::Target {
&self.0
}
}

View file

@ -0,0 +1,125 @@
use chrono::{DateTime, Local, TimeZone, Utc};
use serde::Serialize;
use std::{
fmt::{Debug, Display, Formatter, Result as FMTResult},
ops::Deref,
};
#[derive(Debug, Serialize)]
pub struct DateTimeInfo {
date: String,
time: String,
}
#[derive(Clone)]
pub struct FmtDateTime<Tz: TimeZone>(pub DateTime<Tz>);
impl<Tz: TimeZone> Display for FmtDateTime<Tz>
where
Tz: TimeZone,
Tz::Offset: std::fmt::Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> FMTResult {
write!(
f,
"{:#?}",
DateTimeInfo {
date: self.0.format("%Y-%m-%d").to_string(),
time: self.0.format("%H:%M:%S").to_string()
}
)
}
}
impl<Tz: TimeZone> Debug for FmtDateTime<Tz>
where
Tz::Offset: std::fmt::Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> FMTResult {
Display::fmt(self, f)
}
}
impl<Tz: TimeZone> Serialize for FmtDateTime<Tz>
where
DateTime<Tz>: Display,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<Tz: TimeZone> Deref for FmtDateTime<Tz> {
type Target = DateTime<Tz>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<Tz: TimeZone> Eq for FmtDateTime<Tz> where DateTime<Tz>: Eq {}
impl<Tz: TimeZone> PartialEq for FmtDateTime<Tz>
where
DateTime<Tz>: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<Tz: TimeZone> PartialOrd for FmtDateTime<Tz>
where
DateTime<Tz>: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<Tz: TimeZone> Ord for FmtDateTime<Tz>
where
DateTime<Tz>: Ord,
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.0.cmp(&other.0)
}
}
impl From<FmtDateTime<Utc>> for FmtDateTime<Local> {
fn from(dt: FmtDateTime<Utc>) -> Self {
FmtDateTime(dt.0.with_timezone(&Local))
}
}
impl From<FmtDateTime<Local>> for FmtDateTime<Utc> {
fn from(dt: FmtDateTime<Local>) -> Self {
FmtDateTime(dt.0.with_timezone(&Utc))
}
}
#[allow(dead_code)]
pub trait IntoDateTime {
fn into_utc(self) -> FmtDateTime<Utc>;
fn into_local(self) -> FmtDateTime<Local>;
}
impl IntoDateTime for FmtDateTime<Local> {
fn into_utc(self) -> FmtDateTime<Utc> {
FmtDateTime(self.0.with_timezone(&Utc))
}
fn into_local(self) -> FmtDateTime<Local> {
self
}
}
impl IntoDateTime for FmtDateTime<Utc> {
fn into_local(self) -> FmtDateTime<Local> {
FmtDateTime(self.0.with_timezone(&Local))
}
fn into_utc(self) -> FmtDateTime<Utc> {
self
}
}

View file

@ -0,0 +1,59 @@
use detect_desktop_environment::DesktopEnvironment;
use serde::{Serialize, Serializer};
use std::{
fmt::{Debug, Display, Formatter, Result as FmtResult},
ops::Deref,
};
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct SerdeDE(pub DesktopEnvironment);
impl Serialize for SerdeDE {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&format!("{:?}", self.0))
}
}
impl SerdeDE {
pub fn detect() -> Option<Self> {
DesktopEnvironment::detect().map(SerdeDE)
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct FmtDE(pub SerdeDE);
impl FmtDE {
pub fn detect() -> Option<Self> {
SerdeDE::detect().map(FmtDE)
}
}
impl Display for FmtDE {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "{:?}", self.0.0)
}
}
impl Debug for FmtDE {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
Display::fmt(self, f)
}
}
impl Serialize for FmtDE {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Deref for FmtDE {
type Target = SerdeDE;
fn deref(&self) -> &Self::Target {
&self.0
}
}

View file

@ -0,0 +1,7 @@
pub mod architecture;
pub mod bytes;
pub mod date_time;
pub mod desktop_environment;
pub mod offset_time;
pub mod relative_time;
pub mod version;

View file

@ -0,0 +1,68 @@
use chrono::{DateTime, Local, Offset};
use serde::Serialize;
use std::{
cmp::Ordering,
fmt::{Debug, Display, Formatter, Result as FmtResult},
ops::Deref,
};
#[derive(Copy, Clone)]
pub struct FmtOffsetTime(pub DateTime<Local>);
impl Display for FmtOffsetTime {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "UTC{}", self.0.offset())
}
}
impl Debug for FmtOffsetTime {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
Display::fmt(self, f)
}
}
impl Serialize for FmtOffsetTime {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Deref for FmtOffsetTime {
type Target = DateTime<Local>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Eq for FmtOffsetTime {}
impl PartialEq for FmtOffsetTime {
fn eq(&self, other: &Self) -> bool {
self.0.offset().fix() == other.0.offset().fix()
}
}
impl PartialOrd for FmtOffsetTime {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(
self.0
.offset()
.fix()
.local_minus_utc()
.cmp(&other.0.offset().fix().local_minus_utc()),
)
}
}
impl Ord for FmtOffsetTime {
fn cmp(&self, other: &Self) -> Ordering {
self.0
.offset()
.fix()
.local_minus_utc()
.cmp(&other.0.offset().fix().local_minus_utc())
}
}

View file

@ -0,0 +1,40 @@
use serde::Serialize;
use std::{
fmt::{Debug, Display, Formatter, Result as FmtResult},
ops::Deref,
time::Duration,
};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct FmtRelativeTime(pub Duration);
impl Display for FmtRelativeTime {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
let formatter = timeago::Formatter::new();
write!(f, "{}", formatter.convert(self.0))
}
}
impl Debug for FmtRelativeTime {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
Display::fmt(self, f)
}
}
impl Serialize for FmtRelativeTime {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Deref for FmtRelativeTime {
type Target = Duration;
fn deref(&self) -> &Self::Target {
&self.0
}
}

View file

@ -0,0 +1,38 @@
use serde::Serialize;
use std::{
fmt::{Debug, Display, Formatter, Result as FmtResult},
ops::Deref,
};
use versions::Versioning;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct FmtVersion(pub Versioning);
impl Display for FmtVersion {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "{}", self.0)
}
}
impl Debug for FmtVersion {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
Display::fmt(self, f)
}
}
impl Serialize for FmtVersion {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Deref for FmtVersion {
type Target = Versioning;
fn deref(&self) -> &Self::Target {
&self.0
}
}

View file

@ -0,0 +1,131 @@
use super::Defaults::Unknown;
use serde::Serialize;
use serde_json::{Value, json};
use wgpu;
use winit::{
application::ApplicationHandler,
event::WindowEvent,
event_loop::{ActiveEventLoop, EventLoop},
window::WindowId,
};
mod vram;
#[derive(Debug, Serialize)]
pub struct DriverInfo {
version: String,
name: String,
}
#[derive(Debug, Serialize)]
pub struct AdapterInfo {
vendor: String,
model: String,
driver: DriverInfo,
vram: String,
display: DisplayInfo,
}
#[derive(Debug, Serialize)]
pub struct GPUInfo {
supported_backends: Vec<String>,
gpus: Vec<AdapterInfo>,
}
#[derive(Debug, Serialize, Default)]
pub struct DisplayInfo {
resolution: String,
refresh_rate: String,
}
impl ApplicationHandler for DisplayInfo {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
if let Some(monitor) = event_loop.primary_monitor() {
let size = monitor.size();
let refresh_rate = monitor.refresh_rate_millihertz();
self.resolution = format!("{}x{}", size.width, size.height);
self.refresh_rate = if let Some(refresh) = refresh_rate {
format!("{} hz", refresh / 1000)
} else {
Unknown.into()
}
} else {
self.resolution = Unknown.into();
self.refresh_rate = Unknown.into();
}
event_loop.exit();
}
fn window_event(
&mut self,
_event_loop: &ActiveEventLoop,
_window_id: WindowId,
_event: WindowEvent,
) {
}
}
fn vendor_name(vendor: u32) -> &'static str {
match vendor {
0x10DE => "NVIDIA",
0x1002 => "AMD(Advanced Micro Devices), Inc.",
0x8086 => "Intel(integrated electronics)",
0x13B5 => "ARM(Advanced RISC Machines)",
0x5143 => "Qualcomm(Quality Communications)",
0x1010 => "Apple Inc.",
_ => "Unknown",
}
}
#[allow(dead_code)]
pub fn get_struct() -> GPUInfo {
let mut gpu_data: Vec<AdapterInfo> = Vec::new();
let mut backends: Vec<String> = Vec::new();
let instance_descriptor = wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
flags: wgpu::InstanceFlags::empty(),
backend_options: Default::default(),
};
let instance = wgpu::Instance::new(&instance_descriptor);
let event_loop = EventLoop::new().unwrap();
let mut app = DisplayInfo::default();
event_loop.run_app(&mut app).unwrap();
for adapter in instance.enumerate_adapters(wgpu::Backends::all()) {
let info = adapter.get_info();
if !backends.contains(&info.backend.to_string()) {
backends.push(info.backend.to_string());
}
if info.driver.is_empty() || info.driver_info.is_empty() {
continue;
}
gpu_data.push(AdapterInfo {
vendor: vendor_name(info.vendor).to_string(),
model: info.name,
driver: DriverInfo {
version: info.driver_info,
name: info.driver,
},
vram: vram::get(info.vendor, info.device),
display: DisplayInfo {
resolution: app.resolution.to_string(),
refresh_rate: app.refresh_rate.to_string(),
},
});
}
GPUInfo {
supported_backends: backends,
gpus: gpu_data,
}
}
#[allow(dead_code)]
pub fn get_json() -> Value {
json!(get_struct())
}

View file

@ -0,0 +1,67 @@
use super::super::Defaults::Unknown;
use ash::vk::{API_VERSION_1_2, ApplicationInfo, InstanceCreateInfo, MemoryHeapFlags};
use humansize::{DECIMAL, make_format};
#[cfg(not(target_os = "macos"))]
pub fn get_metal() -> u64 {
0
}
#[cfg(target_os = "macos")]
pub fn get_metal() -> u64 {
use metal::Device as MetalDevice;
let device = MetalDevice::system_default().expect("No Metal-compatible GPU found");
device.recommended_max_working_set_size()
}
pub fn get_vulkan(device_id: u32) -> u64 {
let entry = unsafe { ash::Entry::load().unwrap() };
let app_info = ApplicationInfo {
p_application_name: std::ptr::null(),
application_version: 0,
p_engine_name: std::ptr::null(),
engine_version: 0,
api_version: API_VERSION_1_2,
..Default::default()
};
let create_info = InstanceCreateInfo {
p_application_info: &app_info,
..Default::default()
};
let instance = unsafe { entry.create_instance(&create_info, None).unwrap() };
let physical_devices = unsafe { instance.enumerate_physical_devices().unwrap() };
let mut total_vram = 0;
for device in physical_devices {
let memory_properties = unsafe { instance.get_physical_device_memory_properties(device) };
let device_properties = unsafe { instance.get_physical_device_properties(device) };
if device_id != device_properties.device_id {
continue;
}
for heap in memory_properties.memory_heaps {
if heap.flags.contains(MemoryHeapFlags::DEVICE_LOCAL) {
total_vram += heap.size;
}
}
break;
}
total_vram
}
pub fn get(vendor: u32, device_id: u32) -> String {
let formatter = make_format(DECIMAL);
match vendor {
0x10DE | 0x1002 | 0x8086 | 0x5143 => formatter(get_vulkan(device_id)),
0x1010 => formatter(get_metal()),
_ => Unknown.into(),
}
}

View file

@ -0,0 +1,11 @@
#[macro_export]
macro_rules! custom_anyhow {
($fmt:literal $(, $arg:expr)* $(,)?) => {
::anyhow::anyhow!(
concat!($fmt, " (file: {}, line: {})"),
$($arg,)*
file!(),
line!()
)
};
}

View file

@ -0,0 +1 @@
pub mod custom_anyhow;

View file

@ -0,0 +1,49 @@
use crate::modules::FmtBytes;
use serde::Serialize;
use serde_json::{Value, json};
use sysinfo::System;
#[derive(Debug, Serialize)]
pub struct PhysicalInfo {
total: FmtBytes,
used: FmtBytes,
free: FmtBytes,
available: FmtBytes,
}
#[derive(Debug, Serialize)]
pub struct VirtualInfo {
total: FmtBytes,
used: FmtBytes,
free: FmtBytes,
}
#[derive(Debug, Serialize)]
pub struct MemoryInfo {
physical: PhysicalInfo,
virtual_swap: VirtualInfo,
}
#[allow(dead_code)]
pub fn get_struct() -> MemoryInfo {
let system = System::new_all();
MemoryInfo {
physical: PhysicalInfo {
total: FmtBytes(system.total_memory()),
used: FmtBytes(system.used_memory()),
free: FmtBytes(system.free_memory()),
available: FmtBytes(system.available_memory()),
},
virtual_swap: VirtualInfo {
total: FmtBytes(system.total_swap()),
used: FmtBytes(system.used_swap()),
free: FmtBytes(system.free_swap()),
},
}
}
#[allow(dead_code)]
pub fn get_json() -> Value {
json!(get_struct())
}

View file

@ -0,0 +1,33 @@
use crate::{custom_anyhow, modules::FmtVersion};
use anyhow::Result;
use serde::Serialize;
use serde_json::{Value, json};
use sys_locale::get_locale;
use versions::Versioning;
include!(concat!(env!("OUT_DIR"), "/built.rs"));
#[derive(Debug, Serialize)]
pub struct MetaInfo {
version: FmtVersion,
commit_hash: String,
locale: String,
}
#[allow(dead_code)]
pub fn get_struct() -> Result<MetaInfo> {
let locale = get_locale().unwrap_or_else(|| String::from("en-US"));
let version = Versioning::new(env!("CARGO_PKG_VERSION"))
.ok_or(custom_anyhow!("Invalid version").context("Invalid Semver version"))?;
Ok(MetaInfo {
version: FmtVersion(version),
commit_hash: GIT_COMMIT_HASH.to_string(),
locale,
})
}
#[allow(dead_code)]
pub fn get_json() -> Result<Value> {
Ok(json!(get_struct()?))
}

View file

@ -0,0 +1,42 @@
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
pub mod cpu;
pub mod devices;
pub mod external;
pub mod formatted;
pub mod gpu;
pub mod macros;
pub mod memory;
pub mod meta;
pub mod network;
pub mod os;
pub mod storage;
pub mod uptime;
#[allow(unused_imports)]
pub use formatted::{
architecture::FmtOSArchitecture,
bytes::FmtBytes,
date_time::{FmtDateTime, IntoDateTime},
desktop_environment::FmtDE,
offset_time::FmtOffsetTime,
relative_time::FmtRelativeTime,
version::FmtVersion,
};
#[derive(Debug)]
pub enum Defaults {
Unknown,
}
impl Display for Defaults {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "{:?}", self)
}
}
impl From<Defaults> for String {
fn from(value: Defaults) -> Self {
value.to_string()
}
}

View file

@ -0,0 +1,25 @@
use serde::Serialize;
use serde_json::{Value, json};
use sysinfo::Networks;
#[derive(Debug, Serialize)]
pub struct NetworkInfo {
adapters: Vec<String>,
}
#[allow(dead_code)]
pub fn get_struct() -> NetworkInfo {
let networks = Networks::new_with_refreshed_list();
let mut adapters = Vec::new();
for (interface_name, _network_data) in &networks {
adapters.push(interface_name.to_string());
}
NetworkInfo { adapters }
}
#[allow(dead_code)]
pub fn get_json() -> Value {
json!(get_struct())
}

View file

@ -0,0 +1,54 @@
use super::Defaults::Unknown;
use crate::{
custom_anyhow,
modules::{FmtDE, FmtOSArchitecture},
};
use anyhow::Result;
use serde::Serialize;
use serde_json::{Value, json};
use sysinfo::System;
#[derive(Debug, Serialize)]
pub struct OSInfo {
name: String,
edition: String,
version: String,
architecture: FmtOSArchitecture,
kernel: Option<String>,
desktop_environment: Option<FmtDE>,
}
#[allow(dead_code)]
pub fn get_struct() -> Result<OSInfo> {
let architecture = if cfg!(target_pointer_width = "64") {
Ok(FmtOSArchitecture::W64_BIT)
} else if cfg!(target_pointer_width = "32") {
Ok(FmtOSArchitecture::W32_BIT)
} else {
Err(custom_anyhow!("Unsupported pointer width").context("16 bit systems are not supported"))
}?;
let kernel = if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
Some(System::kernel_long_version())
} else {
None
};
let desktop_environment = if cfg!(target_os = "linux") {
FmtDE::detect()
} else {
None
};
Ok(OSInfo {
name: System::name().unwrap_or(Unknown.into()),
edition: System::long_os_version().unwrap_or(Unknown.into()),
version: System::os_version().unwrap_or(Unknown.into()),
architecture,
kernel,
desktop_environment,
})
}
#[allow(dead_code)]
pub fn get_json() -> Result<Value> {
Ok(json!(get_struct()?))
}

View file

@ -0,0 +1,46 @@
use crate::{custom_anyhow, modules::FmtBytes};
use anyhow::Result;
use serde::Serialize;
use serde_json::{Value, json};
pub use sysinfo::DiskKind;
use sysinfo::Disks;
#[derive(Debug, Serialize)]
pub struct StorageInfo {
name: String,
mount_point: String,
disk_kind: DiskKind,
space_left: FmtBytes,
total: FmtBytes,
}
#[allow(dead_code)]
pub fn get_list() -> Result<Vec<StorageInfo>> {
let disks = Disks::new_with_refreshed_list();
let mut drive_data = Vec::new();
for disk in disks.list() {
drive_data.push(StorageInfo {
name: format!("{:?}", disk.name()).trim_matches('\"').to_string(),
mount_point: format!("{:?}", disk.mount_point())
.replace("\\", "")
.trim_matches('\"')
.to_string(),
disk_kind: disk.kind(),
space_left: FmtBytes(disk.available_space()),
total: FmtBytes(disk.total_space()),
});
}
if drive_data.is_empty() {
return Err(custom_anyhow!("No storage drives found")
.context("Drive_data is empty, expected disks.list() to return non-zero at line 39"));
}
Ok(drive_data)
}
#[allow(dead_code)]
pub fn get_json() -> Result<Value> {
Ok(json!(get_list()?))
}

View file

@ -0,0 +1,54 @@
use crate::{
custom_anyhow,
modules::{FmtDateTime, FmtOffsetTime, FmtRelativeTime},
};
use anyhow::Result;
use chrono::{DateTime, Local, Utc};
use serde::Serialize;
use serde_json::{Value, json};
use std::time::Duration as StdDuration;
use sysinfo::System;
#[derive(Debug, Serialize)]
struct DateInfo {
time_offset: FmtOffsetTime,
local_date_time: FmtDateTime<Local>,
utc_date_time: FmtDateTime<Utc>,
}
#[derive(Debug, Serialize)]
pub struct UptimeInfo {
boot: DateInfo,
now: DateInfo,
relative: FmtRelativeTime,
}
#[allow(dead_code)]
pub fn get_struct() -> Result<UptimeInfo> {
let boot_time_utc = DateTime::<Utc>::from_timestamp(System::boot_time() as i64, 0).ok_or(
custom_anyhow!("Invalid, or out of range timestamp")
.context("Invalid timestamp: check seconds < 8_220_000_000_000"),
)?;
let boot_time_local: DateTime<Local> = boot_time_utc.with_timezone(&Local);
let relative_time =
StdDuration::from_secs((Local::now() - boot_time_local).num_seconds() as u64);
Ok(UptimeInfo {
boot: DateInfo {
time_offset: FmtOffsetTime(Local::now()),
local_date_time: FmtDateTime(boot_time_local),
utc_date_time: FmtDateTime(boot_time_utc),
},
now: DateInfo {
time_offset: FmtOffsetTime(Local::now()),
local_date_time: FmtDateTime(Local::now()),
utc_date_time: FmtDateTime(Utc::now()),
},
relative: FmtRelativeTime(relative_time),
})
}
#[allow(dead_code)]
pub fn get_json() -> Result<Value> {
Ok(json!(get_struct()?))
}

View file

@ -1,318 +0,0 @@
{
"001": "world",
"002": "Africa",
"003": "North America",
"005": "South America",
"009": "Oceania",
"011": "Western Africa",
"013": "Central America",
"014": "Eastern Africa",
"015": "Northern Africa",
"017": "Middle Africa",
"018": "Southern Africa",
"019": "Americas",
"021": "Northern America",
"029": "Caribbean",
"030": "Eastern Asia",
"034": "Southern Asia",
"035": "Southeast Asia",
"039": "Southern Europe",
"053": "Australasia",
"054": "Melanesia",
"057": "Micronesian Region",
"061": "Polynesia",
"142": "Asia",
"143": "Central Asia",
"145": "Western Asia",
"150": "Europe",
"151": "Eastern Europe",
"154": "Northern Europe",
"155": "Western Europe",
"202": "Sub-Saharan Africa",
"419": "Latin America",
"AC": "Ascension Island",
"AD": "Andorra",
"AE": "United Arab Emirates",
"AF": "Afghanistan",
"AG": "Antigua & Barbuda",
"AI": "Anguilla",
"AL": "Albania",
"AM": "Armenia",
"AO": "Angola",
"AQ": "Antarctica",
"AR": "Argentina",
"AS": "American Samoa",
"AT": "Austria",
"AU": "Australia",
"AW": "Aruba",
"AX": "Åland Islands",
"AZ": "Azerbaijan",
"BA": "Bosnia & Herzegovina",
"BA-alt-short": "Bosnia",
"BB": "Barbados",
"BD": "Bangladesh",
"BE": "Belgium",
"BF": "Burkina Faso",
"BG": "Bulgaria",
"BH": "Bahrain",
"BI": "Burundi",
"BJ": "Benin",
"BL": "St Barthélemy",
"BM": "Bermuda",
"BN": "Brunei",
"BO": "Bolivia",
"BQ": "Caribbean Netherlands",
"BR": "Brazil",
"BS": "Bahamas",
"BT": "Bhutan",
"BV": "Bouvet Island",
"BW": "Botswana",
"BY": "Belarus",
"BZ": "Belize",
"CA": "Canada",
"CC": "Cocos (Keeling) Islands",
"CC-alt-short": "Cocos Islands",
"CD": "Congo - Kinshasa",
"CD-alt-variant": "Congo (DRC)",
"CF": "Central African Republic",
"CG": "Congo - Brazzaville",
"CG-alt-variant": "Congo (Republic)",
"CH": "Switzerland",
"CI": "Côte dIvoire",
"CI-alt-variant": "Ivory Coast",
"CK": "Cook Islands",
"CL": "Chile",
"CM": "Cameroon",
"CN": "China",
"CO": "Colombia",
"CP": "Clipperton Island",
"CQ": "Sark",
"CR": "Costa Rica",
"CU": "Cuba",
"CV": "Cape Verde",
"CV-alt-variant": "Cabo Verde",
"CW": "Curaçao",
"CX": "Christmas Island",
"CY": "Cyprus",
"CZ": "Czechia",
"CZ-alt-variant": "Czech Republic",
"DE": "Germany",
"DG": "Diego Garcia",
"DJ": "Djibouti",
"DK": "Denmark",
"DM": "Dominica",
"DO": "Dominican Republic",
"DZ": "Algeria",
"EA": "Ceuta & Melilla",
"EC": "Ecuador",
"EE": "Estonia",
"EG": "Egypt",
"EH": "Western Sahara",
"ER": "Eritrea",
"ES": "Spain",
"ET": "Ethiopia",
"EU": "European Union",
"EZ": "Eurozone",
"FI": "Finland",
"FJ": "Fiji",
"FK": "Falkland Islands",
"FK-alt-variant": "Falkland Islands (Islas Malvinas)",
"FM": "Micronesia",
"FO": "Faroe Islands",
"FR": "France",
"GA": "Gabon",
"GB": "United Kingdom",
"GB-alt-short": "UK",
"GD": "Grenada",
"GE": "Georgia",
"GF": "French Guiana",
"GG": "Guernsey",
"GH": "Ghana",
"GI": "Gibraltar",
"GL": "Greenland",
"GM": "Gambia",
"GN": "Guinea",
"GP": "Guadeloupe",
"GQ": "Equatorial Guinea",
"GR": "Greece",
"GS": "South Georgia & South Sandwich Islands",
"GT": "Guatemala",
"GU": "Guam",
"GW": "Guinea-Bissau",
"GY": "Guyana",
"HK": "Hong Kong SAR China",
"HK-alt-short": "Hong Kong",
"HM": "Heard & McDonald Islands",
"HN": "Honduras",
"HR": "Croatia",
"HT": "Haiti",
"HU": "Hungary",
"IC": "Canary Islands",
"ID": "Indonesia",
"IE": "Ireland",
"IL": "Israel",
"IM": "Isle of Man",
"IN": "India",
"IO": "British Indian Ocean Territory",
"IO-alt-chagos": "Chagos Archipelago",
"IQ": "Iraq",
"IR": "Iran",
"IS": "Iceland",
"IT": "Italy",
"JE": "Jersey",
"JM": "Jamaica",
"JO": "Jordan",
"JP": "Japan",
"KE": "Kenya",
"KG": "Kyrgyzstan",
"KH": "Cambodia",
"KI": "Kiribati",
"KM": "Comoros",
"KN": "St Kitts & Nevis",
"KP": "North Korea",
"KR": "South Korea",
"KW": "Kuwait",
"KY": "Cayman Islands",
"KZ": "Kazakhstan",
"LA": "Laos",
"LB": "Lebanon",
"LC": "St Lucia",
"LI": "Liechtenstein",
"LK": "Sri Lanka",
"LR": "Liberia",
"LS": "Lesotho",
"LT": "Lithuania",
"LU": "Luxembourg",
"LV": "Latvia",
"LY": "Libya",
"MA": "Morocco",
"MC": "Monaco",
"MD": "Moldova",
"ME": "Montenegro",
"MF": "St Martin",
"MG": "Madagascar",
"MH": "Marshall Islands",
"MK": "North Macedonia",
"ML": "Mali",
"MM": "Myanmar (Burma)",
"MM-alt-short": "Myanmar",
"MN": "Mongolia",
"MO": "Macao SAR China",
"MO-alt-short": "Macao",
"MP": "Northern Mariana Islands",
"MQ": "Martinique",
"MR": "Mauritania",
"MS": "Montserrat",
"MT": "Malta",
"MU": "Mauritius",
"MV": "Maldives",
"MW": "Malawi",
"MX": "Mexico",
"MY": "Malaysia",
"MZ": "Mozambique",
"NA": "Namibia",
"NC": "New Caledonia",
"NE": "Niger",
"NF": "Norfolk Island",
"NG": "Nigeria",
"NI": "Nicaragua",
"NL": "Netherlands",
"NO": "Norway",
"NP": "Nepal",
"NR": "Nauru",
"NU": "Niue",
"NZ": "New Zealand",
"NZ-alt-variant": "Aotearoa New Zealand",
"OM": "Oman",
"PA": "Panama",
"PE": "Peru",
"PF": "French Polynesia",
"PG": "Papua New Guinea",
"PH": "Philippines",
"PK": "Pakistan",
"PL": "Poland",
"PM": "St Pierre & Miquelon",
"PN": "Pitcairn Islands",
"PN-alt-short": "Pitcairn",
"PR": "Puerto Rico",
"PS": "Palestinian Territories",
"PS-alt-short": "Palestine",
"PT": "Portugal",
"PW": "Palau",
"PY": "Paraguay",
"QA": "Qatar",
"QO": "Outlying Oceania",
"RE": "Réunion",
"RO": "Romania",
"RS": "Serbia",
"RU": "Russia",
"RW": "Rwanda",
"SA": "Saudi Arabia",
"SB": "Solomon Islands",
"SC": "Seychelles",
"SD": "Sudan",
"SE": "Sweden",
"SG": "Singapore",
"SH": "St Helena",
"SI": "Slovenia",
"SJ": "Svalbard & Jan Mayen",
"SK": "Slovakia",
"SL": "Sierra Leone",
"SM": "San Marino",
"SN": "Senegal",
"SO": "Somalia",
"SR": "Suriname",
"SS": "South Sudan",
"ST": "São Tomé & Príncipe",
"SV": "El Salvador",
"SX": "Sint Maarten",
"SY": "Syria",
"SZ": "Eswatini",
"SZ-alt-variant": "Swaziland",
"TA": "Tristan da Cunha",
"TC": "Turks & Caicos Islands",
"TD": "Chad",
"TF": "French Southern Territories",
"TG": "Togo",
"TH": "Thailand",
"TJ": "Tajikistan",
"TK": "Tokelau",
"TL": "Timor-Leste",
"TL-alt-variant": "East Timor",
"TM": "Turkmenistan",
"TN": "Tunisia",
"TO": "Tonga",
"TR": "Türkiye",
"TR-alt-variant": "Turkey",
"TT": "Trinidad & Tobago",
"TV": "Tuvalu",
"TW": "Taiwan",
"TZ": "Tanzania",
"UA": "Ukraine",
"UG": "Uganda",
"UM": "US Outlying Islands",
"UN": "United Nations",
"UN-alt-short": "UN",
"US": "United States",
"US-alt-short": "US",
"UY": "Uruguay",
"UZ": "Uzbekistan",
"VA": "Vatican City",
"VC": "St Vincent & the Grenadines",
"VE": "Venezuela",
"VG": "British Virgin Islands",
"VI": "US Virgin Islands",
"VN": "Vietnam",
"VU": "Vanuatu",
"WF": "Wallis & Futuna",
"WS": "Samoa",
"XA": "Pseudo-Accents",
"XB": "Pseudo-Bidi",
"XK": "Kosovo",
"YE": "Yemen",
"YT": "Mayotte",
"ZA": "South Africa",
"ZM": "Zambia",
"ZW": "Zimbabwe",
"ZZ": "Unknown Region"
}