我正在尝试根据正在编译应用程序的设备来更改应用程序的图标(我正在使用 crate 加载image) 。不幸的是,当尝试运行代码时:
let (icon_rgba, icon_width, icon_height) = {
let icon = if cfg!(target_os = "macos") {
include_bytes!("../assets/icon-macos.png")
} else {
include_bytes!("../assets/icon.png")
};
let image = image::load_from_memory(icon)
.expect("Failed to open icon path")
.into_rgba8();
let (width, height) = image.dimensions();
let rgba = image.into_raw();
(rgba, width, height)
};
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
error[E0308]: `if` and `else` have incompatible types
--> src/main.rs:6:13
|
3 | let icon = if cfg!(target_os = "macos") {
| ____________________-
4 | | include_bytes!("../assets/icon-macos.png")
| | ------------------------------- expected because of this
5 | | } else {
6 | | include_bytes!("../assets/icon.png")
| | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a fixed size of 63249 elements, found one with 471 elements
7 | | };
| |_________- `if` and `else` have incompatible types
|
= note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info)
Run Code Online (Sandbox Code Playgroud)
虽然我知道为什么会发生此错误,但有没有比下面列出的代码更好的方法来解决此问题?
let (icon_rgba, icon_width, icon_height) = {
if cfg!(target_os = "macos") {
let icon = include_bytes!("../assets/icon-macos.png");
let image = image::load_from_memory(icon)
.expect("Failed to open icon path")
.into_rgba8();
let (width, height) = image.dimensions();
let rgba = image.into_raw();
(rgba, width, height)
} else {
let icon = include_bytes!("../assets/icon.png");
let image = image::load_from_memory(icon)
.expect("Failed to open icon path")
.into_rgba8();
let (width, height) = image.dimensions();
let rgba = image.into_raw();
(rgba, width, height)
};
};
Run Code Online (Sandbox Code Playgroud)
即使在类型检查之前cfg对 s 进行评估,您的代码也无法编译。这是因为虽然编译器评估了to或,但它不会评估该块。cfg!(...)truefalseif
要让编译器有条件地仅发出一个分支,您必须使用#[cfg(...)]属性:
let (icon_rgba, icon_width, icon_height) = {
#[cfg!(target_os = "macos")]
let icon = include_bytes!("../assets/icon-macos.png");
#[cfg!(not(target_os = "macos"))]
let icon = include_bytes!("../assets/icon.png");
let image = image::load_from_memory(icon)
.expect("Failed to open icon path")
.into_rgba8();
let (width, height) = image.dimensions();
let rgba = image.into_raw();
(rgba, width, height)
};
Run Code Online (Sandbox Code Playgroud)
问题在于,编译器推断&[u8; <size_of_the_macos_png>]为 的类型,image因为这就是include_bytes!()第一个分支的 解析为的类型,当它检查它看到的第二个分支时&[u8; <size_of_the_other_png>],但这两种类型都不能强制转换为另一种类型,因此编译器会抛出错误。
幸运的是,您可以给编译器一个类型提示来使用切片,并且它很乐意强制转换为一个:
let (icon_rgba, icon_width, icon_height) = {
let icon: &[u8] = if cfg!(target_os = "macos") {
include_bytes!("../assets/icon-macos.png")
} else {
include_bytes!("../assets/icon.png")
};
let image = image::load_from_memory(icon)
.expect("Failed to open icon path")
.into_rgba8();
let (width, height) = image.dimensions();
let rgba = image.into_raw();
(rgba, width, height)
};
Run Code Online (Sandbox Code Playgroud)
您也可以 as &[u8]或.as_slice()其中一个(或两个)调用include_bytes!(),但它更详细并且有点不对称(甚至更详细),因此我更喜欢绑定上的类型提示。
| 归档时间: |
|
| 查看次数: |
180 次 |
| 最近记录: |