Repository: GuillaumeGomez/sysinfo (language: rust)

Issue:
brand() returns empty on iOS device
**Describe the bug**

I am running it on an iPhone 15 pro. I'm on:
```
sysinfo = "0.32.0"
```

**To Reproduce**
Try fetch the `brand()` on iOS device like iPhone 15 pro. For example my code snippet here returns empty:

```
    // Get processor details
    let cpu_name = sys
        .cpus()
        .first()
        .and_then(|cpu| {
            if cpu.brand().is_empty() {
                Some("Unknown CPU name".to_string())
            } else {
                Some(cpu.brand().to_string())
            }
        })
        .ok_or_else(|| eyre::eyre!("Failed to retrieve CPU name"))?;
```



Discussion / hints:
I don't have an iphone so I can't fix this bug myself. The code to retrieve the brand of a CPU is [here](https://github.com/GuillaumeGomez/sysinfo/blob/master/src/unix/apple/cpu.rs#L399). From what [I can see](https://stackoverflow.com/questions/49199189/cpu-run-time-feature-detection-on-ios-api), there seems to be no way to query this information on iOS.
> I don't have an iphone so I can't fix this bug myself. The code to retrieve the brand of a CPU is [here](https://github.com/GuillaumeGomez/sysinfo/blob/master/src/unix/apple/cpu.rs#L399). From what [I can see](https://stackoverflow.com/questions/49199189/cpu-run-time-feature-detection-on-ios-api), there seems to be no way to query this information on iOS.

is there anything i can do to help, or run some diagnostics against my iphone? otherwise i can close the issue. i just assumed it worked on `iOS` because i saw `iOS` was supported under the `sysinfo` docs; but i understand iOS may not allow access into this. 
You have as much information as I do. So feel free to search around. If you find a fix, please send a PR. :)
adding some more info here. it seems like we cannot fetch the cpu brand() but we may be able to get the device type: and because iOS devices don't have an interchangeable CPU, we can just maintain a mapping of iOS devices to their processors, something like:

```rust
func getCPUModel(for identifier: String) -> String? {
    let mapping: [String: String] = [
        "iPhone14,2": "A16 Bionic",
        "iPhone13,2": "A15 Bionic",
        "iPad13,4": "M1",
        // Add more mappings as needed
    ]
    return mapping[identifier]
}

func getCPUName() -> String? {
    var size = 0
    sysctlbyname("hw.machine", nil, &size, nil, 0)
    var machine = [CChar](repeating: 0, count: size)
    sysctlbyname("hw.machine", &machine, &size, nil, 0)
    let identifier = String(cString: machine)
    return getCPUModel(for: identifier)
}

if let cpuName = getCPUName() {
    print("CPU Name: \(cpuName)")
} else {
    print("Unknown CPU Model")
}
```
Oh nice. A PR with this add would be greatly appreciated. :)

Fix patch:
diff --git a/src/unix/apple/cpu.rs b/src/unix/apple/cpu.rs
index 419c37e34..6f587a45f 100644
--- a/src/unix/apple/cpu.rs
+++ b/src/unix/apple/cpu.rs
@@ -407,7 +407,57 @@ pub(crate) fn get_vendor_id_and_brand() -> (String, String) {
         vendor = "Apple".to_string();
     }
 
-    (vendor, get_sysctl_str(b"machdep.cpu.brand_string\0"))
+    let brand = get_sysctl_str(b"machdep.cpu.brand_string\0");
+    if !brand.is_empty() {
+        return (vendor, brand);
+    }
+    let full_brand = get_sysctl_str(b"hw.machine\0");
+    // This is a fallback when the `sysctl` to get the CPU brand returns an empty string.
+    let mut iter = full_brand.split(',');
+    let brand = match (iter.next().unwrap_or(""), iter.next()) {
+        ("iPhone1", Some("1" | "2")) => "S5L8900",
+        ("iPhone2", Some("1")) => "S5L8920",
+        ("iPhone3", Some("1" | "2" | "3")) => "A4",
+        ("iPhone4", Some("1" | "2")) => "A5",
+        ("iPhone5", Some("1" | "2")) => "A6",
+        ("iPhone5", Some("3" | "4")) => "A6",
+        ("iPhone6", Some("1" | "2")) => "A7",
+        ("iPhone7", Some("1" | "2")) => "A8",
+        ("iPhone8", Some("1" | "2" | "4")) => "A9",
+        ("iPhone9", Some("1" | "2" | "3" | "4")) => "A10 Fusion",
+        ("iPhone10", Some("1" | "2" | "3" | "4" | "5" | "6")) => "A11 Bionic",
+        ("iPhone11", Some("1" | "2" | "4" | "6" | "8")) => "A12 Bionic",
+        ("iPhone12", Some("1" | "3" | "5" | "8")) => "A13 Bionic",
+        ("iPhone13", Some("1" | "2" | "3" | "4")) => "A14 Bionic",
+        ("iPhone14", Some("1" | "2" | "3" | "4" | "5" | "6" | "7" | "8")) => "A15 Bionic",
+        ("iPhone15", Some("2" | "3" | "4" | "5")) => "A16 Bionic",
+        ("iPhone16", Some("1" | "2")) => "A17 Pro",
+        ("iPhone17", Some("1" | "2")) => "A18 Pro",
+        ("iPhone17", Some("3" | "4")) => "A18",
+        ("iPad1", Some("1" | "2")) => "A4",
+        ("iPad2", Some("1" | "2" | "3" | "4" | "5" | "6" | "7")) => "A5",
+        ("iPad3", Some("1" | "2" | "3")) => "A5X",
+        ("iPad3", Some("4" | "5" | "6")) => "A6X",
+        ("iPad4", Some("1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9")) => "A7",
+        ("iPad5", Some("1" | "2")) => "A8",
+        ("iPad5", Some("3" | "4")) => "A8X",
+        ("iPad6", Some("3" | "4" | "7" | "8")) => "A9X",
+        ("iPad6", Some("11" | "12")) => "A9",
+        ("iPad7", Some("1" | "2" | "3" | "4")) => "A10X Fusion",
+        ("iPad7", Some("5" | "6" | "11" | "12")) => "A10 Fusion",
+        ("iPad8", Some("1" | "2" | "3" | "4" | "5" | "6" | "7" | "8")) => "A12X Bionic",
+        ("iPad8", Some("9" | "10" | "11" | "12")) => "A12Z Bionic",
+        ("iPad11", Some("1" | "2" | "3" | "4" | "6" | "7")) => "A12 Bionic",
+        ("iPad12", Some("1" | "2")) => "A13 Bionic",
+        ("iPad13", Some("1" | "2" | "18" | "19")) => "A14 Bionic",
+        ("iPad13", Some("4" | "5" | "6" | "7" | "8" | "9" | "10" | "11" | "16" | "17")) => "M1",
+        ("iPad14", Some("1" | "2")) => "A15 Bionic",
+        ("iPad14", Some("3" | "4" | "5" | "6" | "10" | "11")) => "M2",
+        ("iPad14", Some("8" | "9")) => "M1",
+        ("iPad16", Some("3" | "4" | "5" | "6")) => "M3",
+        _ => "unknown",
+    };
+    (vendor, brand.to_string())
 }
 
 #[cfg(test)]


Test patch: