diff options
Diffstat (limited to '')
| -rw-r--r-- | Cargo.lock | 1330 | ||||
| -rw-r--r-- | Cargo.toml | 3 | ||||
| -rw-r--r-- | cmd/apple-silicon-info/README.org | 15 | ||||
| -rw-r--r-- | cmd/apple-silicon-info/main.go | 281 | ||||
| -rw-r--r-- | cmd/apple-silicon-info/main_test.go | 197 | ||||
| -rw-r--r-- | rust-toolchain.toml | 3 | ||||
| -rw-r--r-- | src/apple_silicon/Cargo.lock | 65 | ||||
| -rw-r--r-- | src/apple_silicon/Cargo.toml | 18 | ||||
| -rw-r--r-- | src/apple_silicon/README.md | 1 | ||||
| -rw-r--r-- | src/apple_silicon/src/bin/apple_silicon.rs | 12 | ||||
| -rw-r--r-- | src/apple_silicon/src/error.rs | 23 | ||||
| -rw-r--r-- | src/apple_silicon/src/lib.rs | 2 | ||||
| -rw-r--r-- | src/apple_silicon/src/soc.rs | 302 | ||||
| -rw-r--r-- | treefmt.nix | 3 |
14 files changed, 493 insertions, 1762 deletions
diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 5c31fb2..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,1330 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anstream" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" - -[[package]] -name = "anstyle-parse" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" -dependencies = [ - "windows-sys 0.60.2", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" -dependencies = [ - "anstyle", - "once_cell_polyfill", - "windows-sys 0.60.2", -] - -[[package]] -name = "anyhow" -version = "1.0.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" - -[[package]] -name = "apple_silicon" -version = "0.1.0" -dependencies = [ - "thiserror 2.0.16", -] - -[[package]] -name = "asn1-rs" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" -dependencies = [ - "asn1-rs-derive", - "asn1-rs-impl", - "displaydoc", - "nom", - "num-traits", - "rusticata-macros", - "thiserror 1.0.69", - "time", -] - -[[package]] -name = "asn1-rs-derive" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "asn1-rs-impl" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "aws-lc-rs" -version = "1.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c953fe1ba023e6b7730c0d4b031d06f267f23a46167dcbd40316644b10a17ba" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbfd150b5dbdb988bcc8fb1fe787eb6b7ee6180ca24da683b61ea5405f3d43ff" -dependencies = [ - "bindgen", - "cc", - "cmake", - "dunce", - "fs_extra", -] - -[[package]] -name = "bindgen" -version = "0.69.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn", - "which", -] - -[[package]] -name = "bitflags" -version = "2.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" - -[[package]] -name = "bumpalo" -version = "3.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" - -[[package]] -name = "cc" -version = "1.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" - -[[package]] -name = "chrono" -version = "0.4.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "num-traits", - "windows-link", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "4.5.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" - -[[package]] -name = "cmake" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" -dependencies = [ - "cc", -] - -[[package]] -name = "colorchoice" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "data-encoding" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" - -[[package]] -name = "der-parser" -version = "9.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" -dependencies = [ - "asn1-rs", - "displaydoc", - "nom", - "num-bigint", - "num-traits", - "rusticata-macros", -] - -[[package]] -name = "deranged" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "errno" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" -dependencies = [ - "libc", - "windows-sys 0.60.2", -] - -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "getrandom" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.11.1+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi 0.14.3+wasi-0.2.4", -] - -[[package]] -name = "glob" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "home" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.3", - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "libc" -version = "0.2.175" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" - -[[package]] -name = "libloading" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" -dependencies = [ - "cfg-if", - "windows-targets 0.53.3", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "memchr" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "oid-registry" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" -dependencies = [ - "asn1-rs", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "once_cell_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - -[[package]] -name = "proc-macro2" -version = "1.0.101" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "regex" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.16", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rusticata-macros" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" -dependencies = [ - "nom", -] - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustls" -version = "0.23.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" -dependencies = [ - "aws-lc-rs", - "log", - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" -dependencies = [ - "openssl-probe", - "rustls-pemfile", - "rustls-pki-types", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" -dependencies = [ - "zeroize", -] - -[[package]] -name = "rustls-webpki" -version = "0.103.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" -dependencies = [ - "aws-lc-rs", - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "schannel" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "serde" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "2.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" -dependencies = [ - "thiserror-impl 2.0.16", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "time" -version = "0.3.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" - -[[package]] -name = "time-macros" -version = "0.2.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "wasi" -version = "0.14.3+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "webpki-roots" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" -dependencies = [ - "webpki-roots 1.0.2", -] - -[[package]] -name = "webpki-roots" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.59.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.3", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - -[[package]] -name = "wit-bindgen" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814" - -[[package]] -name = "x509-info" -version = "0.1.0" -dependencies = [ - "anyhow", - "chrono", - "clap", - "rustls", - "rustls-native-certs", - "webpki-roots 0.26.11", - "x509-parser", -] - -[[package]] -name = "x509-parser" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" -dependencies = [ - "asn1-rs", - "data-encoding", - "der-parser", - "lazy_static", - "nom", - "oid-registry", - "rusticata-macros", - "thiserror 1.0.69", - "time", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index f0b7ea9..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,3 +0,0 @@ -[workspace] -members = ["src/apple_silicon/"] -resolver = "3" diff --git a/cmd/apple-silicon-info/README.org b/cmd/apple-silicon-info/README.org new file mode 100644 index 0000000..682a11c --- /dev/null +++ b/cmd/apple-silicon-info/README.org @@ -0,0 +1,15 @@ +* socinfo + +A lightweight macOS utility that gathers detailed information about Apple Silicon System-on-Chip (SoC) specifications. + +** What it does + +=socinfo= queries your Mac's hardware through system utilities to retrieve: + +- CPU brand name and core configuration +- GPU core count +- Performance and efficiency core breakdown +- Thermal Design Power (TDP) specifications +- Memory bandwidth specifications + +The tool automatically detects your specific Apple Silicon variant (M1, M1 Pro/Max/Ultra, M2, M2 Pro/Max/Ultra, M3, M3 Pro/Max) and provides the corresponding technical specifications. diff --git a/cmd/apple-silicon-info/main.go b/cmd/apple-silicon-info/main.go new file mode 100644 index 0000000..f733d7e --- /dev/null +++ b/cmd/apple-silicon-info/main.go @@ -0,0 +1,281 @@ +package main + +import ( + "bufio" + "errors" + "fmt" + "os/exec" + "strconv" + "strings" +) + +// Custom error types +var ( + ErrParse = errors.New("socinfo parsing error") + ErrCommand = errors.New("command execution error") + ErrConvert = errors.New("conversion error") +) + +type ( + Watts = uint32 + Bandwidth = uint32 + CoreCount = uint16 +) + +// SocInfo represents information about the Silicon chip +type SocInfo struct { + CPUBrandName string `json:"cpu_brand_name"` + NumCPUCores CoreCount `json:"num_cpu_cores"` + NumGPUCores CoreCount `json:"num_gpu_cores"` + CPUMaxPower *Watts `json:"cpu_max_power,omitempty"` + GPUMaxPower *Watts `json:"gpu_max_power,omitempty"` + CPUMaxBW *Bandwidth `json:"cpu_max_bw,omitempty"` + GPUMaxBW *Bandwidth `json:"gpu_max_bw,omitempty"` + ECoreCount CoreCount `json:"e_core_count"` + PCoreCount CoreCount `json:"p_core_count"` +} + +// AppleChip represents different Apple Silicon variants +type AppleChip int + +const ( + M1 AppleChip = iota + M1Pro + M1Max + M1Ultra + M2 + M2Pro + M2Max + M2Ultra + M3 + M3Pro + M3Max + Unknown +) + +// ChipSpecs holds the specifications for each chip variant +type ChipSpecs struct { + CPUTDP Watts + GPUTDP Watts + CPUBW Bandwidth + GPUBW Bandwidth +} + +// fromBrandString determines the Apple chip type from brand string +func fromBrandString(brand string) AppleChip { + switch { + case strings.Contains(brand, "M1 Pro"): + return M1Pro + case strings.Contains(brand, "M1 Max"): + return M1Max + case strings.Contains(brand, "M1 Ultra"): + return M1Ultra + case strings.Contains(brand, "M1"): + return M1 + case strings.Contains(brand, "M2 Pro"): + return M2Pro + case strings.Contains(brand, "M2 Max"): + return M2Max + case strings.Contains(brand, "M2 Ultra"): + return M2Ultra + case strings.Contains(brand, "M2"): + return M2 + case strings.Contains(brand, "M3 Pro"): + return M3Pro + case strings.Contains(brand, "M3 Max"): + return M3Max + case strings.Contains(brand, "M3"): + return M3 + default: + return Unknown + } +} + +// getSpecs returns the specifications for the chip +func (chip AppleChip) getSpecs() ChipSpecs { + switch chip { + case M1: + return ChipSpecs{CPUTDP: 20, GPUTDP: 20, CPUBW: 70, GPUBW: 70} + case M1Pro: + return ChipSpecs{CPUTDP: 30, GPUTDP: 30, CPUBW: 200, GPUBW: 200} + case M1Max: + return ChipSpecs{CPUTDP: 30, GPUTDP: 60, CPUBW: 250, GPUBW: 400} + case M1Ultra: + return ChipSpecs{CPUTDP: 60, GPUTDP: 120, CPUBW: 500, GPUBW: 800} + case M2: + return ChipSpecs{CPUTDP: 25, GPUTDP: 15, CPUBW: 100, GPUBW: 100} + case M2Pro: + return ChipSpecs{CPUTDP: 30, GPUTDP: 35, CPUBW: 0, GPUBW: 0} + case M2Max: + return ChipSpecs{CPUTDP: 30, GPUTDP: 40, CPUBW: 0, GPUBW: 0} + default: + return ChipSpecs{CPUTDP: 0, GPUTDP: 0, CPUBW: 0, GPUBW: 0} + } +} + +// SystemCommand interface for testable command execution +type SystemCommand interface { + Execute(binary string, args ...string) ([]byte, error) +} + +// RealCommand implements SystemCommand for actual system calls +type RealCommand struct{} + +func (r *RealCommand) Execute(binary string, args ...string) ([]byte, error) { + cmd := exec.Command(binary, args...) + output, err := cmd.Output() + if err != nil { + return nil, fmt.Errorf("%w: %v", ErrCommand, err) + } + return output, nil +} + +const sysctlPath = "/usr/sbin/sysctl" + +// getCPUInfo retrieves CPU information using sysctl +func getCPUInfo(cmd SystemCommand) (string, CoreCount, CoreCount, CoreCount, error) { + args := []string{ + "-n", // don't display the variable name + "machdep.cpu.brand_string", + "machdep.cpu.core_count", + "hw.perflevel0.logicalcpu", + "hw.perflevel1.logicalcpu", + } + + output, err := cmd.Execute(sysctlPath, args...) + if err != nil { + return "", 0, 0, 0, err + } + + lines := strings.Split(strings.TrimSpace(string(output)), "\n") + if len(lines) < 4 { + return "", 0, 0, 0, fmt.Errorf("%w: insufficient output lines", ErrParse) + } + + cpuBrandName := lines[0] + + numCPUCores, err := strconv.ParseUint(lines[1], 10, 16) + if err != nil { + return "", 0, 0, 0, fmt.Errorf("%w: parsing cpu cores: %v", ErrConvert, err) + } + + numPerformanceCores, err := strconv.ParseUint(lines[2], 10, 16) + if err != nil { + return "", 0, 0, 0, fmt.Errorf("%w: parsing performance cores: %v", ErrConvert, err) + } + + numEfficiencyCores, err := strconv.ParseUint(lines[3], 10, 16) + if err != nil { + return "", 0, 0, 0, fmt.Errorf("%w: parsing efficiency cores: %v", ErrConvert, err) + } + + return cpuBrandName, CoreCount( + numCPUCores, + ), CoreCount( + numPerformanceCores, + ), CoreCount( + numEfficiencyCores, + ), nil +} + +// getGPUInfo retrieves GPU information using system_profiler +func getGPUInfo(cmd SystemCommand) (CoreCount, error) { + args := []string{"-detailLevel", "basic", "SPDisplaysDataType"} + + output, err := cmd.Execute("/usr/sbin/system_profiler", args...) + if err != nil { + return 0, err + } + + scanner := bufio.NewScanner(strings.NewReader(string(output))) + for scanner.Scan() { + line := scanner.Text() + trimmed := strings.TrimSpace(line) + if strings.HasPrefix(trimmed, "Total Number of Cores") { + parts := strings.Split(trimmed, ": ") + if len(parts) == 2 { + cores, err := strconv.ParseUint(strings.TrimSpace(parts[1]), 10, 16) + if err != nil { + return 0, fmt.Errorf("%w: parsing gpu cores: %v", ErrConvert, err) + } + return CoreCount(cores), nil + } + } + } + + if err := scanner.Err(); err != nil { + return 0, fmt.Errorf("%w: scanning output: %v", ErrParse, err) + } + + return 0, fmt.Errorf("%w: GPU core count not found", ErrParse) +} + +// NewSocInfo creates a new SocInfo instance by gathering system information +func NewSocInfo() (*SocInfo, error) { + cmd := &RealCommand{} + return NewSocInfoWithCommand(cmd) +} + +// NewSocInfoWithCommand creates a new SocInfo instance with a custom command executor (for testing) +func NewSocInfoWithCommand(cmd SystemCommand) (*SocInfo, error) { + cpuBrandName, numCPUCores, eCoreCount, pCoreCount, err := getCPUInfo(cmd) + if err != nil { + return nil, err + } + + numGPUCores, err := getGPUInfo(cmd) + if err != nil { + return nil, err + } + + chip := fromBrandString(cpuBrandName) + specs := chip.getSpecs() + + var cpuMaxPower, gpuMaxPower *Watts + var cpuMaxBW, gpuMaxBW *Bandwidth + + if specs.CPUTDP > 0 { + cpuMaxPower = &specs.CPUTDP + } + if specs.GPUTDP > 0 { + gpuMaxPower = &specs.GPUTDP + } + if specs.CPUBW > 0 { + cpuMaxBW = &specs.CPUBW + } + if specs.GPUBW > 0 { + gpuMaxBW = &specs.GPUBW + } + + return &SocInfo{ + CPUBrandName: cpuBrandName, + NumCPUCores: numCPUCores, + NumGPUCores: numGPUCores, + CPUMaxPower: cpuMaxPower, + GPUMaxPower: gpuMaxPower, + CPUMaxBW: cpuMaxBW, + GPUMaxBW: gpuMaxBW, + ECoreCount: eCoreCount, + PCoreCount: pCoreCount, + }, nil +} + +func main() { + socInfo, err := NewSocInfo() + if err != nil { + fmt.Printf("Error getting SoC info: %v\n", err) + return + } + + var cpuPower Watts + if socInfo.CPUMaxPower != nil { + cpuPower = *socInfo.CPUMaxPower + } + + fmt.Printf("Our CPU is an %s, and we have %d CPU cores, and %d GPU cores. The TDP is %d.\n", + socInfo.CPUBrandName, + socInfo.NumCPUCores, + socInfo.NumGPUCores, + cpuPower, + ) +} diff --git a/cmd/apple-silicon-info/main_test.go b/cmd/apple-silicon-info/main_test.go new file mode 100644 index 0000000..a9b7caf --- /dev/null +++ b/cmd/apple-silicon-info/main_test.go @@ -0,0 +1,197 @@ +package main + +import ( + "errors" + "testing" +) + +type MockCommand struct { + output string + err error +} + +func NewMockCommand(output string) *MockCommand { + return &MockCommand{output: output} +} + +func NewMockCommandWithError(err error) *MockCommand { + return &MockCommand{err: err} +} + +func (m *MockCommand) Execute(binary string, args ...string) ([]byte, error) { + if m.err != nil { + return nil, m.err + } + return []byte(m.output), nil +} + +func TestGetGPUInfo(t *testing.T) { + mockOutput := `Graphics/Displays: + Apple M2: + Total Number of Cores: 10` + + cmd := NewMockCommand(mockOutput) + + result, err := getGPUInfo(cmd) + if err != nil { + t.Fatalf("Expected no error, got: %v", err) + } + + expected := CoreCount(10) + if result != expected { + t.Errorf("Expected %d GPU cores, got %d", expected, result) + } +} + +func TestGetGPUInfoNotFound(t *testing.T) { + mockOutput := `Graphics/Displays: + Apple M2: + Some other field: 10` + + cmd := NewMockCommand(mockOutput) + + _, err := getGPUInfo(cmd) + if err == nil { + t.Fatal("Expected error when GPU cores not found, got nil") + } +} + +func TestGetCPUInfoSuccess(t *testing.T) { + mockOutput := "Apple M2\n8\n4\n4\n" + cmd := NewMockCommand(mockOutput) + + brand, cores, pCores, eCores, err := getCPUInfo(cmd) + if err != nil { + t.Fatalf("Expected no error, got: %v", err) + } + + if brand != "Apple M2" { + t.Errorf("Expected brand 'Apple M2', got '%s'", brand) + } + if cores != 8 { + t.Errorf("Expected 8 cores, got %d", cores) + } + if pCores != 4 { + t.Errorf("Expected 4 performance cores, got %d", pCores) + } + if eCores != 4 { + t.Errorf("Expected 4 efficiency cores, got %d", eCores) + } +} + +func TestGetCPUInfoMissingCoreCount(t *testing.T) { + mockOutput := "Apple M2\n" + cmd := NewMockCommand(mockOutput) + + _, _, _, _, err := getCPUInfo(cmd) + if err == nil { + t.Fatal("Expected error with insufficient output, got nil") + } +} + +func TestGetCPUInfoInvalidCoreCount(t *testing.T) { + mockOutput := "Apple M2\ninvalid\n4\n4\n" + cmd := NewMockCommand(mockOutput) + + _, _, _, _, err := getCPUInfo(cmd) + if err == nil { + t.Fatal("Expected error with invalid core count, got nil") + } +} + +func TestFromBrandString(t *testing.T) { + tests := []struct { + brand string + expected AppleChip + }{ + {"Apple M1", M1}, + {"Apple M1 Pro", M1Pro}, + {"Apple M1 Max", M1Max}, + {"Apple M1 Ultra", M1Ultra}, + {"Apple M2", M2}, + {"Apple M2 Pro", M2Pro}, + {"Apple M2 Max", M2Max}, + {"Apple M2 Ultra", M2Ultra}, + {"Apple M3", M3}, + {"Apple M3 Pro", M3Pro}, + {"Apple M3 Max", M3Max}, + {"Intel Core i7", Unknown}, + } + + for _, test := range tests { + result := fromBrandString(test.brand) + if result != test.expected { + t.Errorf("For brand '%s', expected %v, got %v", test.brand, test.expected, result) + } + } +} + +func TestChipGetSpecs(t *testing.T) { + tests := []struct { + chip AppleChip + expected ChipSpecs + }{ + {M1, ChipSpecs{CPUTDP: 20, GPUTDP: 20, CPUBW: 70, GPUBW: 70}}, + {M1Pro, ChipSpecs{CPUTDP: 30, GPUTDP: 30, CPUBW: 200, GPUBW: 200}}, + {M2, ChipSpecs{CPUTDP: 25, GPUTDP: 15, CPUBW: 100, GPUBW: 100}}, + {Unknown, ChipSpecs{CPUTDP: 0, GPUTDP: 0, CPUBW: 0, GPUBW: 0}}, + } + + for _, test := range tests { + result := test.chip.getSpecs() + if result != test.expected { + t.Errorf("For chip %v, expected %+v, got %+v", test.chip, test.expected, result) + } + } +} + +func TestNewSocInfoWithCommand(t *testing.T) { + sysctlOutput := "Apple M2\n8\n4\n4\n" + + profilerOutput := `Graphics/Displays: + Apple M2: + Total Number of Cores: 10` + + cmd := &MockCommandMultiple{ + outputs: map[string]string{ + "/usr/sbin/sysctl": sysctlOutput, + "/usr/sbin/system_profiler": profilerOutput, + }, + } + + socInfo, err := NewSocInfoWithCommand(cmd) + if err != nil { + t.Fatalf("Expected no error, got: %v", err) + } + + if socInfo.CPUBrandName != "Apple M2" { + t.Errorf("Expected CPU brand 'Apple M2', got '%s'", socInfo.CPUBrandName) + } + if socInfo.NumCPUCores != 8 { + t.Errorf("Expected 8 CPU cores, got %d", socInfo.NumCPUCores) + } + if socInfo.NumGPUCores != 10 { + t.Errorf("Expected 10 GPU cores, got %d", socInfo.NumGPUCores) + } + if socInfo.CPUMaxPower == nil || *socInfo.CPUMaxPower != 25 { + t.Errorf("Expected CPU max power 25W, got %v", socInfo.CPUMaxPower) + } +} + +type MockCommandMultiple struct { + outputs map[string]string + err error +} + +func (m *MockCommandMultiple) Execute(binary string, args ...string) ([]byte, error) { + if m.err != nil { + return nil, m.err + } + + output, exists := m.outputs[binary] + if !exists { + return nil, errors.New("binary not found in mock") + } + + return []byte(output), nil +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml deleted file mode 100644 index a978b3e..0000000 --- a/rust-toolchain.toml +++ /dev/null @@ -1,3 +0,0 @@ -[toolchain] -channel = "1.89" -components = ["rustfmt", "clippy", "rust-analyzer"] diff --git a/src/apple_silicon/Cargo.lock b/src/apple_silicon/Cargo.lock deleted file mode 100644 index 1ee0f1d..0000000 --- a/src/apple_silicon/Cargo.lock +++ /dev/null @@ -1,65 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "apple_silicon" -version = "0.1.0" -dependencies = [ - "thiserror", -] - -[[package]] -name = "proc-macro2" -version = "1.0.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "syn" -version = "2.0.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/src/apple_silicon/Cargo.toml b/src/apple_silicon/Cargo.toml deleted file mode 100644 index 65dcf5e..0000000 --- a/src/apple_silicon/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "apple_silicon" -version = "0.1.0" -edition = "2021" -description = "A common line tool for Apple Silicon" - -license = "MIT" -authors = ["Franck Cuny <franck@fcuny.net>"] -repository = "https://github.com/fcuny/apple_silicon" -homepage = "https://github.com/fcuny/apple_silicon" -categories = ["command-line-utilities"] - -[[bin]] -name = "apple_silicon" -path = "src/bin/apple_silicon.rs" - -[dependencies] -thiserror = "2.0.11" diff --git a/src/apple_silicon/README.md b/src/apple_silicon/README.md deleted file mode 100644 index 7d83327..0000000 --- a/src/apple_silicon/README.md +++ /dev/null @@ -1 +0,0 @@ -A command line utility to report information about Apple Silicon (inspired by [`asitop`](https://github.com/tlkh/asitop/tree/74ebe2cbc23d5b1eec874aebb1b9bacfe0e670cd)). diff --git a/src/apple_silicon/src/bin/apple_silicon.rs b/src/apple_silicon/src/bin/apple_silicon.rs deleted file mode 100644 index 0f71eeb..0000000 --- a/src/apple_silicon/src/bin/apple_silicon.rs +++ /dev/null @@ -1,12 +0,0 @@ -use apple_silicon::soc::SocInfo; - -fn main() { - let cpu_info = SocInfo::new().unwrap(); - println!( - "our CPU is an {}, and we have {} CPU cores, and {} GPU cores. The TDP is {}.", - cpu_info.cpu_brand_name, - cpu_info.num_cpu_cores, - cpu_info.num_gpu_cores, - cpu_info.cpu_max_power.unwrap(), - ); -} diff --git a/src/apple_silicon/src/error.rs b/src/apple_silicon/src/error.rs deleted file mode 100644 index a70b9b5..0000000 --- a/src/apple_silicon/src/error.rs +++ /dev/null @@ -1,23 +0,0 @@ -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error("socinfo parsing error: `{0}`")] - Parse(String), - - #[error("I/O error: `{source}`")] - Io { - #[from] - source: std::io::Error, - }, - - #[error("utf8 conversion error: `{source}`")] - Utf8Conversion { - #[from] - source: std::string::FromUtf8Error, - }, - - #[error("integer parsing error: `{source}`")] - ParseInt { - #[from] - source: std::num::ParseIntError, - }, -} diff --git a/src/apple_silicon/src/lib.rs b/src/apple_silicon/src/lib.rs deleted file mode 100644 index 74bd62c..0000000 --- a/src/apple_silicon/src/lib.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod error; -pub mod soc; diff --git a/src/apple_silicon/src/soc.rs b/src/apple_silicon/src/soc.rs deleted file mode 100644 index 0e2bf5c..0000000 --- a/src/apple_silicon/src/soc.rs +++ /dev/null @@ -1,302 +0,0 @@ -use crate::error::Error; - -use std::process::{Command, Output}; - -pub type Result<T> = std::result::Result<T, Error>; -pub type Watts = u32; -pub type Bandwidth = u32; -pub type CoreCount = u16; - -/// Information about the Silicon chip -pub struct SocInfo { - /// The CPU brand name string - pub cpu_brand_name: String, - /// Number of CPU cores - pub num_cpu_cores: CoreCount, - /// Number of GPU cores - pub num_gpu_cores: CoreCount, - /// Maximum CPU power in watts (if available) - pub cpu_max_power: Option<Watts>, - /// Maximum GPU power in watts (if available) - pub gpu_max_power: Option<Watts>, - /// Maximum CPU bandwidth in GB/s (if available) - pub cpu_max_bw: Option<Bandwidth>, - /// Maximum GPU bandwidth in GB/s (if available) - pub gpu_max_bw: Option<Bandwidth>, - /// Number of efficiency cores - pub e_core_count: CoreCount, - /// Number of performance cores - pub p_core_count: CoreCount, -} - -#[derive(Debug, PartialEq)] -enum AppleChip { - M1, - M1Pro, - M1Max, - M1Ultra, - M2, - M2Pro, - M2Max, - M2Ultra, - M3, - M3Pro, - M3Max, - Unknown, -} - -struct ChipSpecs { - cpu_tdp: Watts, - gpu_tdp: Watts, - cpu_bw: Bandwidth, - gpu_bw: Bandwidth, -} - -impl AppleChip { - fn from_brand_string(brand: &str) -> Self { - match brand { - s if s.contains("M1 Pro") => AppleChip::M1Pro, - s if s.contains("M1 Max") => AppleChip::M1Max, - s if s.contains("M1 Ultra") => AppleChip::M1Ultra, - s if s.contains("M1") => AppleChip::M1, - s if s.contains("M2 Pro") => AppleChip::M2Pro, - s if s.contains("M2 Max") => AppleChip::M2Max, - s if s.contains("M2 Ultra") => AppleChip::M2Ultra, - s if s.contains("M2") => AppleChip::M2, - s if s.contains("M3 Pro") => AppleChip::M3Pro, - s if s.contains("M3 Max") => AppleChip::M3Max, - s if s.contains("M3") => AppleChip::M3, - _ => AppleChip::Unknown, - } - } - - fn get_specs(&self) -> ChipSpecs { - match self { - AppleChip::M1 => ChipSpecs { - cpu_tdp: 20, - gpu_tdp: 20, - cpu_bw: 70, - gpu_bw: 70, - }, - AppleChip::M1Pro => ChipSpecs { - cpu_tdp: 30, - gpu_tdp: 30, - cpu_bw: 200, - gpu_bw: 200, - }, - AppleChip::M1Max => ChipSpecs { - cpu_tdp: 30, - gpu_tdp: 60, - cpu_bw: 250, - gpu_bw: 400, - }, - AppleChip::M1Ultra => ChipSpecs { - cpu_tdp: 60, - gpu_tdp: 120, - cpu_bw: 500, - gpu_bw: 800, - }, - AppleChip::M2 => ChipSpecs { - cpu_tdp: 25, - gpu_tdp: 15, - cpu_bw: 100, - gpu_bw: 100, - }, - AppleChip::M2Pro => ChipSpecs { - cpu_tdp: 30, - gpu_tdp: 35, - cpu_bw: 0, - gpu_bw: 0, - }, - AppleChip::M2Max => ChipSpecs { - cpu_tdp: 30, - gpu_tdp: 40, - cpu_bw: 0, - gpu_bw: 0, - }, - // Add more variants as needed - _ => ChipSpecs { - cpu_tdp: 0, - gpu_tdp: 0, - cpu_bw: 0, - gpu_bw: 0, - }, - } - } -} - -impl SocInfo { - pub fn new() -> Result<SocInfo> { - let (cpu_brand_name, num_cpu_cores, e_core_count, p_core_count) = cpu_info(&RealCommand)?; - let num_gpu_cores = gpu_info(&RealCommand)?; - - let chip = AppleChip::from_brand_string(&cpu_brand_name); - let specs = chip.get_specs(); - - Ok(SocInfo { - cpu_brand_name, - num_cpu_cores, - num_gpu_cores, - cpu_max_power: Some(specs.cpu_tdp), - gpu_max_power: Some(specs.gpu_tdp), - cpu_max_bw: Some(specs.cpu_bw), - gpu_max_bw: Some(specs.gpu_bw), - e_core_count, - p_core_count, - }) - } -} - -// https://github.com/tlkh/asitop/blob/74ebe2cbc23d5b1eec874aebb1b9bacfe0e670cd/asitop/utils.py#L94 -const SYSCTL_PATH: &str = "/usr/sbin/sysctl"; - -fn cpu_info(cmd: &impl SystemCommand) -> Result<(String, u16, u16, u16)> { - let binary = SYSCTL_PATH; - let args = &[ - // don't display the variable name - "-n", - "machdep.cpu.brand_string", - "machdep.cpu.core_count", - "hw.perflevel0.logicalcpu", - "hw.perflevel1.logicalcpu", - ]; - - let output = cmd.execute(binary, args)?; - let buffer = String::from_utf8(output.stdout)?; - - let mut iter = buffer.split('\n'); - let cpu_brand_name = match iter.next() { - Some(s) => s.to_string(), - None => return Err(Error::Parse(buffer.to_string())), - }; - - let num_cpu_cores = match iter.next() { - Some(s) => s.parse::<u16>()?, - None => return Err(Error::Parse(buffer.to_string())), - }; - - let num_performance_cores = match iter.next() { - Some(s) => s.parse::<u16>()?, - None => return Err(Error::Parse(buffer.to_string())), - }; - - let num_efficiency_cores = match iter.next() { - Some(s) => s.parse::<u16>()?, - None => return Err(Error::Parse(buffer.to_string())), - }; - - Ok(( - cpu_brand_name, - num_cpu_cores, - num_performance_cores, - num_efficiency_cores, - )) -} - -// https://github.com/tlkh/asitop/blob/74ebe2cbc23d5b1eec874aebb1b9bacfe0e670cd/asitop/utils.py#L120 -fn gpu_info(cmd: &impl SystemCommand) -> Result<u16> { - let binary = "/usr/sbin/system_profiler"; - let args = &["-detailLevel", "basic", "SPDisplaysDataType"]; - - let output = cmd.execute(binary, args)?; - let buffer = String::from_utf8(output.stdout)?; - - let num_gpu_cores_line = buffer - .lines() - .find(|&line| line.trim_start().starts_with("Total Number of Cores")); - - let num_gpu_cores = match num_gpu_cores_line { - Some(s) => match s.split(": ").last() { - Some(s) => s.parse::<u16>()?, - None => return Err(Error::Parse(buffer.to_string())), - }, - None => return Err(Error::Parse(buffer.to_string())), - }; - - Ok(num_gpu_cores) -} - -/// Trait for system command execution -pub trait SystemCommand { - fn execute(&self, binary: &str, args: &[&str]) -> Result<Output>; -} - -/// Real command executor -pub struct RealCommand; - -impl SystemCommand for RealCommand { - fn execute(&self, binary: &str, args: &[&str]) -> Result<Output> { - Ok(Command::new(binary).args(args).output()?) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::os::unix::process::ExitStatusExt; - - struct MockCommand { - output: Vec<u8>, - } - - impl MockCommand { - fn new(output: &str) -> Self { - Self { - output: output.as_bytes().to_vec(), - } - } - } - - impl SystemCommand for MockCommand { - fn execute(&self, _binary: &str, _args: &[&str]) -> Result<Output> { - Ok(Output { - status: std::process::ExitStatus::from_raw(0), - stdout: self.output.clone(), - stderr: Vec::new(), - }) - } - } - - #[test] - fn test_gpu_info() { - let mock_output = r#"Graphics/Displays: - Apple M2: - Total Number of Cores: 10"#; - let cmd = MockCommand::new(mock_output); - - let result = gpu_info(&cmd); - assert_eq!(result.unwrap(), 10); - } - - #[test] - fn test_cpu_info_success() { - let mock_output = "Apple M2\n8\n4\n4\n"; - let cmd = MockCommand::new(mock_output); - - let result = cpu_info(&cmd); - assert!(result.is_ok()); - let (brand, cores, p_cores, e_cores) = result.unwrap(); - assert_eq!(brand, "Apple M2"); - assert_eq!(cores, 8); - assert_eq!(p_cores, 4); - assert_eq!(e_cores, 4); - } - - #[test] - fn test_cpu_info_missing_core_count() { - let mock_output = "Apple M2\n"; - let cmd = MockCommand::new(mock_output); - - let result = cpu_info(&cmd); - assert!(matches!(result, Err(Error::ParseInt { .. }))); - } - - #[test] - fn test_cpu_info_invalid_core_count() { - let mock_output = "Apple M2\ninvalid\n"; - let cmd = MockCommand::new(mock_output); - - let result = cpu_info(&cmd); - assert!(matches!(result, Err(Error::ParseInt { .. }))); - } -} diff --git a/treefmt.nix b/treefmt.nix index b2e04da..f4b9728 100644 --- a/treefmt.nix +++ b/treefmt.nix @@ -24,9 +24,6 @@ programs.actionlint.enable = true; # Markdown programs.mdformat.enable = true; - # Rust - programs.rustfmt.enable = true; - programs.taplo.enable = true; # Nix programs.nixfmt = { enable = true; |
