removed languages.json and territories.json
Some checks failed
Build Zenyx ⚡ / 🧪 Run Cargo Tests (pull_request) Failing after 6m9s
Build Zenyx ⚡ / 🏗️ Build aarch64-apple-darwin (pull_request) Has been skipped
Build Zenyx ⚡ / 🏗️ Build aarch64-pc-windows-msvc (pull_request) Has been skipped
Build Zenyx ⚡ / 🏗️ Build aarch64-unknown-linux-gnu (pull_request) Has been skipped
Build Zenyx ⚡ / 🏗️ Build x86_64-apple-darwin (pull_request) Has been skipped
Build Zenyx ⚡ / 🏗️ Build x86_64-pc-windows-msvc (pull_request) Has been skipped
Build Zenyx ⚡ / 🏗️ Build x86_64-unknown-linux-gnu (pull_request) Has been skipped
Some checks failed
Build Zenyx ⚡ / 🧪 Run Cargo Tests (pull_request) Failing after 6m9s
Build Zenyx ⚡ / 🏗️ Build aarch64-apple-darwin (pull_request) Has been skipped
Build Zenyx ⚡ / 🏗️ Build aarch64-pc-windows-msvc (pull_request) Has been skipped
Build Zenyx ⚡ / 🏗️ Build aarch64-unknown-linux-gnu (pull_request) Has been skipped
Build Zenyx ⚡ / 🏗️ Build x86_64-apple-darwin (pull_request) Has been skipped
Build Zenyx ⚡ / 🏗️ Build x86_64-pc-windows-msvc (pull_request) Has been skipped
Build Zenyx ⚡ / 🏗️ Build x86_64-unknown-linux-gnu (pull_request) Has been skipped
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:
parent
91c80d0f91
commit
528d4b03a3
28 changed files with 1261 additions and 1726 deletions
132
Cargo.lock
generated
132
Cargo.lock
generated
|
@ -173,14 +173,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "async-executor"
|
||||
version = "1.13.1"
|
||||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec"
|
||||
checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa"
|
||||
dependencies = [
|
||||
"async-task",
|
||||
"concurrent-queue",
|
||||
"fastrand",
|
||||
"futures-lite",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
]
|
||||
|
||||
|
@ -300,7 +301,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"arrayvec",
|
||||
"log",
|
||||
"nom",
|
||||
"nom 7.1.3",
|
||||
"num-rational",
|
||||
"v_frame",
|
||||
]
|
||||
|
@ -398,9 +399,9 @@ checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
|
|||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.22.0"
|
||||
version = "1.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540"
|
||||
checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c"
|
||||
dependencies = [
|
||||
"bytemuck_derive",
|
||||
]
|
||||
|
@ -505,14 +506,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.40"
|
||||
version = "0.4.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
|
||||
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-link",
|
||||
]
|
||||
|
@ -1153,6 +1155,15 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "isolang"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe50d48c77760c55188549098b9a7f6e37ae980c586a24693d6b01c3b2010c3c"
|
||||
dependencies = [
|
||||
"phf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
|
@ -1162,6 +1173,15 @@ dependencies = [
|
|||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.15"
|
||||
|
@ -1495,6 +1515,15 @@ dependencies = [
|
|||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "8.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "noop_proc_macro"
|
||||
version = "0.3.0"
|
||||
|
@ -1951,6 +1980,24 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.10"
|
||||
|
@ -2107,9 +2154,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
|
|||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.37.4"
|
||||
version = "0.37.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4ce8c88de324ff838700f36fb6ab86c96df0e3c4ab6ef3a9b2044465cce1369"
|
||||
checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -2179,7 +2226,7 @@ dependencies = [
|
|||
"built",
|
||||
"cfg-if",
|
||||
"interpolate_name",
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"libc",
|
||||
"libfuzzer-sys",
|
||||
"log",
|
||||
|
@ -2476,6 +2523,12 @@ dependencies = [
|
|||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
|
@ -2630,6 +2683,7 @@ dependencies = [
|
|||
"memchr",
|
||||
"ntapi",
|
||||
"objc2-core-foundation",
|
||||
"serde",
|
||||
"windows 0.57.0",
|
||||
]
|
||||
|
||||
|
@ -2656,6 +2710,7 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
|||
name = "telemetry"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"ash",
|
||||
"chrono",
|
||||
"detect-desktop-environment",
|
||||
|
@ -2666,6 +2721,8 @@ dependencies = [
|
|||
"serde_json",
|
||||
"sys-locale",
|
||||
"sysinfo",
|
||||
"timeago",
|
||||
"versions",
|
||||
"wgpu",
|
||||
"winit",
|
||||
]
|
||||
|
@ -2746,6 +2803,16 @@ dependencies = [
|
|||
"weezl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "timeago"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1710e589de0a76aaf295cd47a6699f6405737dbfd3cf2b75c92d000b548d0e6"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"isolang",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-skia"
|
||||
version = "0.11.4"
|
||||
|
@ -2782,9 +2849,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.21"
|
||||
version = "0.8.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "900f6c86a685850b1bc9f6223b20125115ee3f31e01207d81655bbcc0aea9231"
|
||||
checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
|
@ -2803,9 +2870,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.25"
|
||||
version = "0.22.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10558ed0bd2a1562e630926a2d1f0b98c827da99fabd3fe20920a59642504485"
|
||||
checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
|
@ -2928,6 +2995,17 @@ version = "0.9.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "versions"
|
||||
version = "7.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80a7e511ce1795821207a837b7b1c8d8aca0c648810966ad200446ae58f6667f"
|
||||
dependencies = [
|
||||
"itertools 0.14.0",
|
||||
"nom 8.0.0",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vk-parse"
|
||||
version = "0.15.0"
|
||||
|
@ -2951,7 +3029,7 @@ dependencies = [
|
|||
"heck 0.4.1",
|
||||
"indexmap",
|
||||
"libloading",
|
||||
"nom",
|
||||
"nom 7.1.3",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"proc-macro2",
|
||||
|
@ -3079,9 +3157,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wayland-backend"
|
||||
version = "0.3.8"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7208998eaa3870dad37ec8836979581506e0c5c64c20c9e79e9d2a10d6f47bf"
|
||||
checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"downcast-rs",
|
||||
|
@ -3093,9 +3171,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wayland-client"
|
||||
version = "0.31.8"
|
||||
version = "0.31.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2120de3d33638aaef5b9f4472bff75f07c56379cf76ea320bd3a3d65ecaf73f"
|
||||
checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"rustix",
|
||||
|
@ -3116,9 +3194,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wayland-cursor"
|
||||
version = "0.31.8"
|
||||
version = "0.31.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a93029cbb6650748881a00e4922b076092a6a08c11e7fbdb923f064b23968c5d"
|
||||
checksum = "a65317158dec28d00416cb16705934070aef4f8393353d41126c54264ae0f182"
|
||||
dependencies = [
|
||||
"rustix",
|
||||
"wayland-client",
|
||||
|
@ -3127,9 +3205,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wayland-protocols"
|
||||
version = "0.32.6"
|
||||
version = "0.32.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0781cf46869b37e36928f7b432273c0995aa8aed9552c556fb18754420541efc"
|
||||
checksum = "779075454e1e9a521794fed15886323ea0feda3f8b0fc1390f5398141310422a"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"wayland-backend",
|
||||
|
@ -3139,9 +3217,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wayland-protocols-plasma"
|
||||
version = "0.3.6"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ccaacc76703fefd6763022ac565b590fcade92202492381c95b2edfdf7d46b3"
|
||||
checksum = "4fd38cdad69b56ace413c6bcc1fbf5acc5e2ef4af9d5f8f1f9570c0c83eae175"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"wayland-backend",
|
||||
|
@ -3152,9 +3230,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wayland-protocols-wlr"
|
||||
version = "0.3.6"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "248a02e6f595aad796561fa82d25601bd2c8c3b145b1c7453fc8f94c1a58f8b2"
|
||||
checksum = "1cb6cdc73399c0e06504c437fe3cf886f25568dd5454473d565085b36d6a8bbf"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"wayland-backend",
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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": "N’Ko",
|
||||
"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"
|
||||
}
|
|
@ -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()?))
|
||||
}
|
||||
|
|
69
subcrates/telemetry/src/modules/cpu.rs
Normal file
69
subcrates/telemetry/src/modules/cpu.rs
Normal 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())
|
||||
}
|
59
subcrates/telemetry/src/modules/devices.rs
Normal file
59
subcrates/telemetry/src/modules/devices.rs
Normal 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()?))
|
||||
}
|
63
subcrates/telemetry/src/modules/external.rs
Normal file
63
subcrates/telemetry/src/modules/external.rs
Normal 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())
|
||||
}
|
55
subcrates/telemetry/src/modules/formatted/architecture.rs
Normal file
55
subcrates/telemetry/src/modules/formatted/architecture.rs
Normal 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
|
||||
}
|
||||
}
|
38
subcrates/telemetry/src/modules/formatted/bytes.rs
Normal file
38
subcrates/telemetry/src/modules/formatted/bytes.rs
Normal 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
|
||||
}
|
||||
}
|
125
subcrates/telemetry/src/modules/formatted/date_time.rs
Normal file
125
subcrates/telemetry/src/modules/formatted/date_time.rs
Normal 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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
7
subcrates/telemetry/src/modules/formatted/mod.rs
Normal file
7
subcrates/telemetry/src/modules/formatted/mod.rs
Normal 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;
|
68
subcrates/telemetry/src/modules/formatted/offset_time.rs
Normal file
68
subcrates/telemetry/src/modules/formatted/offset_time.rs
Normal 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())
|
||||
}
|
||||
}
|
40
subcrates/telemetry/src/modules/formatted/relative_time.rs
Normal file
40
subcrates/telemetry/src/modules/formatted/relative_time.rs
Normal 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
|
||||
}
|
||||
}
|
38
subcrates/telemetry/src/modules/formatted/version.rs
Normal file
38
subcrates/telemetry/src/modules/formatted/version.rs
Normal 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
|
||||
}
|
||||
}
|
131
subcrates/telemetry/src/modules/gpu/mod.rs
Normal file
131
subcrates/telemetry/src/modules/gpu/mod.rs
Normal 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())
|
||||
}
|
67
subcrates/telemetry/src/modules/gpu/vram.rs
Normal file
67
subcrates/telemetry/src/modules/gpu/vram.rs
Normal 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(),
|
||||
}
|
||||
}
|
11
subcrates/telemetry/src/modules/macros/custom_anyhow.rs
Normal file
11
subcrates/telemetry/src/modules/macros/custom_anyhow.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
#[macro_export]
|
||||
macro_rules! custom_anyhow {
|
||||
($fmt:literal $(, $arg:expr)* $(,)?) => {
|
||||
::anyhow::anyhow!(
|
||||
concat!($fmt, " (file: {}, line: {})"),
|
||||
$($arg,)*
|
||||
file!(),
|
||||
line!()
|
||||
)
|
||||
};
|
||||
}
|
1
subcrates/telemetry/src/modules/macros/mod.rs
Normal file
1
subcrates/telemetry/src/modules/macros/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod custom_anyhow;
|
49
subcrates/telemetry/src/modules/memory.rs
Normal file
49
subcrates/telemetry/src/modules/memory.rs
Normal 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())
|
||||
}
|
33
subcrates/telemetry/src/modules/meta.rs
Normal file
33
subcrates/telemetry/src/modules/meta.rs
Normal 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()?))
|
||||
}
|
42
subcrates/telemetry/src/modules/mod.rs
Normal file
42
subcrates/telemetry/src/modules/mod.rs
Normal 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()
|
||||
}
|
||||
}
|
25
subcrates/telemetry/src/modules/network.rs
Normal file
25
subcrates/telemetry/src/modules/network.rs
Normal 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())
|
||||
}
|
54
subcrates/telemetry/src/modules/os.rs
Normal file
54
subcrates/telemetry/src/modules/os.rs
Normal 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()?))
|
||||
}
|
46
subcrates/telemetry/src/modules/storage.rs
Normal file
46
subcrates/telemetry/src/modules/storage.rs
Normal 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()?))
|
||||
}
|
54
subcrates/telemetry/src/modules/uptime.rs
Normal file
54
subcrates/telemetry/src/modules/uptime.rs
Normal 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()?))
|
||||
}
|
|
@ -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 d’Ivoire",
|
||||
"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"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue