mirror of
https://github.com/uutils/platform-info.git
synced 2026-06-10 15:48:45 -07:00
Add processor() method to UNameAPI trait (#96)
* Add processor() method to UNameAPI trait Implements processor type mapping to provide GNU coreutils-compatible processor information, addressing uutils/coreutils#8659. Changes: - Add processor() method to UNameAPI trait with comprehensive docs - Implement map_processor() helper in lib_impl for arch-to-processor mapping - Add processor field and implementation to all platform modules (Unix, Windows, unknown) - Include platform-specific tests verifying correct processor mappings - Update example code to demonstrate processor() usage - Add workspace declaration to Cargo.toml to prevent parent workspace inheritance Processor mapping behavior: - macOS: arm64 → arm - Linux: aarch64 → aarch64 (passthrough) - x86_64/amd64 → x86_64 - i386/i486/i586/i686 → i686 - ARMv6/v7/v8 variants → arm - Unknown architectures pass through unchanged (better than "unknown") This provides the foundation for uutils/coreutils to migrate from its local processor mapping implementation, consolidating platform knowledge in the appropriate abstraction layer. Ref: uutils/coreutils#8659 * docs: update README to include processor() method Add processor() to example code and expected output as requested by @sylvestre * docs: clarify processor() vs machine() difference and add comprehensive tests Address review feedback: - Remove incomplete archive.is placeholder - Add detailed documentation explaining how processor() differs from machine() - Include comparison table showing platform-specific behavior - Add comprehensive unit test for map_processor() covering all branches - Improves test coverage from 66.66% to 100% in lib_impl.rs
This commit is contained in:
@@ -29,6 +29,7 @@ fn main() {
|
||||
println!("{}", info.release().to_string_lossy());
|
||||
println!("{}", info.version().to_string_lossy());
|
||||
println!("{}", info.machine().to_string_lossy());
|
||||
println!("{}", info.processor().to_string_lossy());
|
||||
println!("{}", info.osname().to_string_lossy());
|
||||
}
|
||||
```
|
||||
@@ -41,6 +42,7 @@ hostname
|
||||
5.10.0-8-amd64
|
||||
#1 SMP Debian 5.10.46-4 (2021-08-03)
|
||||
x86_64
|
||||
x86_64
|
||||
GNU/Linux
|
||||
```
|
||||
|
||||
|
||||
@@ -14,5 +14,6 @@ fn main() {
|
||||
println!("{}", info.release().to_string_lossy());
|
||||
println!("{}", info.version().to_string_lossy());
|
||||
println!("{}", info.machine().to_string_lossy());
|
||||
println!("{}", info.processor().to_string_lossy());
|
||||
println!("{}", info.osname().to_string_lossy());
|
||||
}
|
||||
|
||||
@@ -103,6 +103,14 @@ pub trait UNameAPI {
|
||||
/// The name of the current system's hardware.
|
||||
fn machine(&self) -> &OsStr;
|
||||
|
||||
/// The processor type (architecture) of the current system.
|
||||
///
|
||||
/// Maps machine architecture strings to GNU coreutils-compatible processor types.
|
||||
/// For example, "arm64" may map to "arm", "x86_64" to "x86_64", etc.
|
||||
/// This provides more semantically meaningful processor information than the
|
||||
/// raw machine string in some contexts.
|
||||
fn processor(&self) -> &OsStr;
|
||||
|
||||
/// The name of the current OS.
|
||||
fn osname(&self) -> &OsStr;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// "plumbing" setup and connections for `lib.rs`
|
||||
|
||||
// spell-checker:ignore (jargon) armv
|
||||
|
||||
#![warn(unused_results)] // enable warnings for unused results
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
@@ -23,6 +25,45 @@ type PathStr = Path;
|
||||
#[cfg(target_os = "windows")]
|
||||
type PathString = PathBuf;
|
||||
|
||||
//=== platform-specific functions
|
||||
|
||||
// map_processor
|
||||
/// *Returns* processor type mapped from machine architecture string.
|
||||
///
|
||||
/// Provides GNU coreutils-compatible processor type mappings from machine architecture strings.
|
||||
/// This function normalizes architecture names to match the output of GNU coreutils' `uname -p`.
|
||||
///
|
||||
/// # Difference from `machine()`
|
||||
///
|
||||
/// While [`UNameAPI::machine()`] returns the raw architecture string from the OS (e.g., "arm64" on macOS),
|
||||
/// `processor()` provides a normalized, cross-platform compatible representation:
|
||||
///
|
||||
/// | Platform | machine() | processor() | Reason |
|
||||
/// |----------|-----------|-------------|--------|
|
||||
/// | macOS ARM | "arm64" | "arm" | GNU coreutils compatibility |
|
||||
/// | Linux ARM64 | "aarch64" | "aarch64" | Preserve Linux convention |
|
||||
/// | Windows x86 | "i386"-"i686" | "i686" | Normalize to common name |
|
||||
///
|
||||
/// # Architecture Mappings
|
||||
///
|
||||
/// * macOS uses "arm64" for ARM-based Macs → maps to "arm"
|
||||
/// * Linux uses "aarch64" for ARM64 → passes through as "aarch64"
|
||||
/// * Various i386/i486/i586/i686 variants → normalized to "i686"
|
||||
/// * ARMv6/v7/v8 variants → mapped to "arm"
|
||||
/// * Unknown architectures pass through unchanged (better than returning "unknown")
|
||||
///
|
||||
/// ref: <https://github.com/uutils/coreutils/issues/8659>
|
||||
pub(crate) fn map_processor(machine: &str) -> String {
|
||||
match machine {
|
||||
"arm64" => "arm".to_string(),
|
||||
"aarch64" => "aarch64".to_string(),
|
||||
"x86_64" | "amd64" => "x86_64".to_string(),
|
||||
"i386" | "i486" | "i586" | "i686" => "i686".to_string(),
|
||||
"armv7l" | "armv6l" | "armv8l" => "arm".to_string(),
|
||||
_ => machine.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
//=== platform-specific const
|
||||
|
||||
// HOST_OS_NAME * ref: [`uname` info](https://en.wikipedia.org/wiki/Uname)
|
||||
@@ -73,3 +114,28 @@ mod target;
|
||||
mod target;
|
||||
|
||||
pub use target::*;
|
||||
|
||||
//=== Tests
|
||||
|
||||
#[test]
|
||||
fn test_map_processor_mappings() {
|
||||
// ARM variants
|
||||
assert_eq!(map_processor("arm64"), "arm");
|
||||
assert_eq!(map_processor("aarch64"), "aarch64");
|
||||
assert_eq!(map_processor("armv6l"), "arm");
|
||||
assert_eq!(map_processor("armv7l"), "arm");
|
||||
assert_eq!(map_processor("armv8l"), "arm");
|
||||
|
||||
// x86 variants
|
||||
assert_eq!(map_processor("x86_64"), "x86_64");
|
||||
assert_eq!(map_processor("amd64"), "x86_64");
|
||||
assert_eq!(map_processor("i386"), "i686");
|
||||
assert_eq!(map_processor("i486"), "i686");
|
||||
assert_eq!(map_processor("i586"), "i686");
|
||||
assert_eq!(map_processor("i686"), "i686");
|
||||
|
||||
// Unknown/passthrough architectures
|
||||
assert_eq!(map_processor("riscv64"), "riscv64");
|
||||
assert_eq!(map_processor("powerpc64"), "powerpc64");
|
||||
assert_eq!(map_processor("unknown"), "unknown");
|
||||
}
|
||||
|
||||
+31
-1
@@ -40,6 +40,7 @@ pub struct PlatformInfo {
|
||||
release: OsString,
|
||||
version: OsString,
|
||||
machine: OsString,
|
||||
processor: OsString,
|
||||
osname: OsString,
|
||||
}
|
||||
|
||||
@@ -47,13 +48,16 @@ impl PlatformInfoAPI for PlatformInfo {
|
||||
// * note: this function *should* never fail
|
||||
fn new() -> Result<Self, PlatformInfoError> {
|
||||
let utsname = UTSName(utsname()?);
|
||||
let machine = oss_from_cstr(&utsname.0.machine);
|
||||
let processor = OsString::from(crate::lib_impl::map_processor(&machine.to_string_lossy()));
|
||||
Ok(Self {
|
||||
utsname,
|
||||
sysname: oss_from_cstr(&utsname.0.sysname),
|
||||
nodename: oss_from_cstr(&utsname.0.nodename),
|
||||
release: oss_from_cstr(&utsname.0.release),
|
||||
version: oss_from_cstr(&utsname.0.version),
|
||||
machine: oss_from_cstr(&utsname.0.machine),
|
||||
machine,
|
||||
processor,
|
||||
osname: OsString::from(crate::lib_impl::HOST_OS_NAME),
|
||||
})
|
||||
}
|
||||
@@ -80,6 +84,10 @@ impl UNameAPI for PlatformInfo {
|
||||
&self.machine
|
||||
}
|
||||
|
||||
fn processor(&self) -> &OsStr {
|
||||
&self.processor
|
||||
}
|
||||
|
||||
fn osname(&self) -> &OsStr {
|
||||
&self.osname
|
||||
}
|
||||
@@ -222,6 +230,28 @@ fn test_osname() {
|
||||
assert!(osname.starts_with(crate::lib_impl::HOST_OS_NAME));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_processor() {
|
||||
let info = PlatformInfo::new().unwrap();
|
||||
let processor = info.processor().to_string_lossy();
|
||||
|
||||
// Processor should not be empty
|
||||
assert!(!processor.is_empty());
|
||||
|
||||
// On common platforms, verify expected mappings
|
||||
#[cfg(all(target_arch = "aarch64", target_os = "macos"))]
|
||||
assert_eq!(processor, "arm", "macOS arm64 should map to 'arm'");
|
||||
|
||||
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
|
||||
assert_eq!(processor, "aarch64", "Linux aarch64 should pass through");
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
assert_eq!(processor, "x86_64", "x86_64 should pass through");
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
assert_eq!(processor, "i686", "x86 variants should normalize to i686");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn structure_clone() {
|
||||
let info = PlatformInfo::new().unwrap();
|
||||
|
||||
@@ -51,6 +51,10 @@ impl UNameAPI for PlatformInfo {
|
||||
&self.unknown
|
||||
}
|
||||
|
||||
fn processor(&self) -> &OsStr {
|
||||
&self.unknown
|
||||
}
|
||||
|
||||
fn osname(&self) -> &OsStr {
|
||||
&self.unknown
|
||||
}
|
||||
@@ -65,6 +69,7 @@ fn test_unknown() {
|
||||
assert_eq!(platform_info.release().to_string_lossy(), "unknown");
|
||||
assert_eq!(platform_info.version().to_string_lossy(), "unknown");
|
||||
assert_eq!(platform_info.machine().to_string_lossy(), "unknown");
|
||||
assert_eq!(platform_info.processor().to_string_lossy(), "unknown");
|
||||
assert_eq!(platform_info.osname().to_string_lossy(), "unknown");
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ pub struct PlatformInfo {
|
||||
release: OsString,
|
||||
version: OsString,
|
||||
machine: OsString,
|
||||
processor: OsString,
|
||||
osname: OsString,
|
||||
}
|
||||
|
||||
@@ -84,6 +85,7 @@ impl PlatformInfoAPI for PlatformInfo {
|
||||
let release = version_info.release.clone();
|
||||
let version = version_info.version.clone();
|
||||
let machine = determine_machine(&system_info);
|
||||
let processor = OsString::from(crate::lib_impl::map_processor(&machine.to_string_lossy()));
|
||||
let osname = determine_osname(&version_info);
|
||||
|
||||
Ok(Self {
|
||||
@@ -96,6 +98,7 @@ impl PlatformInfoAPI for PlatformInfo {
|
||||
release,
|
||||
version,
|
||||
machine,
|
||||
processor,
|
||||
osname,
|
||||
})
|
||||
}
|
||||
@@ -122,6 +125,10 @@ impl UNameAPI for PlatformInfo {
|
||||
&self.machine
|
||||
}
|
||||
|
||||
fn processor(&self) -> &OsStr {
|
||||
&self.processor
|
||||
}
|
||||
|
||||
fn osname(&self) -> &OsStr {
|
||||
&self.osname
|
||||
}
|
||||
@@ -746,6 +753,30 @@ fn test_known_winos_names() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_processor() {
|
||||
let info = PlatformInfo::new().unwrap();
|
||||
let processor = info.processor().to_string_lossy();
|
||||
|
||||
// Processor should not be empty
|
||||
assert!(!processor.is_empty());
|
||||
|
||||
// On common Windows platforms, verify expected mappings
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
assert_eq!(processor, "x86_64", "Windows x86_64 should pass through");
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
assert_eq!(processor, "i686", "Windows x86 should normalize to i686");
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
assert_eq!(
|
||||
processor, "aarch64",
|
||||
"Windows ARM64 should pass through as aarch64"
|
||||
);
|
||||
|
||||
println!("Windows processor=[{}]'{}'", processor.len(), processor);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn structure_clone() {
|
||||
let info = PlatformInfo::new().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user