我有一个match语句,返回一个&str:

match k {
    SP_KEY_1 => "KEY_1",
    SP_KEY_2 => "KEY_2",
    SP_KEY_3 => "KEY_3",
    SP_KEY_4 => "KEY_4",
    SP_KEY_5 => "KEY_5",
    SP_KEY_6 => "KEY_6",
    _ => (k as char), // I want to convert this to &str
}.as_bytes()

我试着先把一个char转换成一个字符串,然后从中取一部分:

&(k as char).to_string()[..]

但这给了我一生的错误:

error[E0597]: borrowed value does not live long enough

说明(k as char).to_string()是一个临时值,从我可以看出,这是有道理的to_string()返回一个克隆.

我可以在上面的每&str个文本中添加.to_string(),以使返回值为String,但这似乎既难看(大量重复代码),又可能效率低下,因为to_string()克隆了原始字符串片段.

具体的问题是如何将char变成&str,但更广泛的问题是,有没有更好的解决方案,在这种情况下通常会做什么.

推荐答案

只要不需要从函数返回&str,就可以使用char::encode_utf8完全避免堆分配:

const SP_KEY_1: u8 = 0;
const SP_KEY_2: u8 = 1;
const SP_KEY_3: u8 = 2;
const SP_KEY_4: u8 = 3;
const SP_KEY_5: u8 = 4;
const SP_KEY_6: u8 = 5;

fn main() {
    let k = 42u8;

    let mut tmp = [0; 4];

    let s = match k {
        SP_KEY_1 => "KEY_1",
        SP_KEY_2 => "KEY_2",
        SP_KEY_3 => "KEY_3",
        SP_KEY_4 => "KEY_4",
        SP_KEY_5 => "KEY_5",
        SP_KEY_6 => "KEY_6",
        _ => (k as char).encode_utf8(&mut tmp),
    };

    println!("{}", s);
}

如果你需要更多的控制,这可以与关闭相结合:

fn adapt<F, B>(k: u8, f: F) -> B
where
    for<'a> F: FnOnce(&'a str) -> B,
{
    let mut tmp = [0; 4];

    let s = match k {
        SP_KEY_1 => "KEY_1",
        SP_KEY_2 => "KEY_2",
        SP_KEY_3 => "KEY_3",
        SP_KEY_4 => "KEY_4",
        SP_KEY_5 => "KEY_5",
        SP_KEY_6 => "KEY_6",
        _ => (k as char).encode_utf8(&mut tmp),
    };

    f(s)
}

fn main() {
    adapt(0, |s| println!("{}", s));
    let owned = adapt(0, |s| s.to_owned());
}

或者存储在 struct 中以提供一点抽象:

#[derive(Debug, Default)]
struct Foo {
    tmp: [u8; 4],
}

impl Foo {
    fn adapt(&mut self, k: u8) -> &str {
        match k {
            SP_KEY_1 => "KEY_1",
            SP_KEY_2 => "KEY_2",
            SP_KEY_3 => "KEY_3",
            SP_KEY_4 => "KEY_4",
            SP_KEY_5 => "KEY_5",
            SP_KEY_6 => "KEY_6",
            _ => (k as char).encode_utf8(&mut self.tmp),
        }
    }
}

fn main() {
    let mut foo = Foo::default();
    {
        let s = foo.adapt(0);
    }
    {
        let s = foo.adapt(42);
    }
}

Rust相关问答推荐

无需通过ASIO输入音频,并使用cpal进行反馈示例

泛型属性比较

在Rust中赋值变量有运行时开销吗?

有没有办法在Rust中配置常量变量的值?

如何在AVX2中对齐/旋转256位向量?

什么是`&;[][..]`铁 rust 里的刻薄?

Windows 上 ndarray-linalg 与 mkl-stats 的链接时间错误

Rust 中的复合 `HashSet` 操作或如何在 Rust 中获得 `HashSet` 的显式差异/并集

`UnsafeCell` 在没有锁定的情况下跨线程共享 - 这可能会导致 UB,对吗?

存储返回 impl Trait 作为特征对象的函数

Sized问题的动态调度迭代器Rust

在发布中包含 Rust DLL

如何从 rust 中的同一父目录导入文件

Rust:`sort_by` 多个条件,冗长的模式匹配

Rust Serde 为 Option:: 创建反序列化器

如何在 Rust 中将 bson::Bson 转换为 Vec

更好的方法来模式匹配带有 Rust 的窥视孔装配说明窗口?

判断 is_ok 后重用结果

如何在不设置精度的情况下打印浮点数时保持尾随零?

为什么 `ref` 会导致此示例*取消引用*一个字段?