簡體   English   中英

可互換地使用str和String

[英]Using str and String interchangably

假設我正在嘗試使用&str在Rust中做一個花哨的零拷貝解析器,但有時我需要修改文本(例如實現變量替換)。 我真的想做這樣的事情:

fn main() {
    let mut v: Vec<&str> = "Hello there $world!".split_whitespace().collect();

    for t in v.iter_mut() {
        if (t.contains("$world")) {
            *t = &t.replace("$world", "Earth");
        }
    }

    println!("{:?}", &v);
}

但是當然t.replace()返回的String不夠長。 這有什么好辦法嗎? 也許有一種類型意味着“理想情況下是一個&str但必要時是一個String ”? 或者也許有一種方法可以使用生命周期注釋告訴編譯器返回的String應該保持活動直到main()結束(或者與v具有相同的生命周期)?

Rust完全以Cow (Clone On Write)類型的形式提供。

use std::borrow::Cow;

fn main() {
    let mut v: Vec<_> = "Hello there $world!".split_whitespace()
                                             .map(|s| Cow::Borrowed(s))
                                             .collect();

    for t in v.iter_mut() {
        if t.contains("$world") {
            *t.to_mut() = t.replace("$world", "Earth");
        }
    }

    println!("{:?}", &v);
}

正如@sellibitze正確指出的那樣, to_mut()創建一個新的String ,它導致堆分配存儲先前借用的值。 如果你確定你只是借用了字符串,那么你可以使用

*t = Cow::Owned(t.replace("$world", "Earth"));

如果Vec包含Cow::Owned元素,這仍然會丟棄分配。 您可以使用以下非常脆弱和不安全的代碼(它確實直接基於字節的UTF-8字符串操作,並且依賴於替換恰好是完全相同的字節數。)在for循環中。

let mut last_pos = 0; // so we don't start at the beginning every time
while let Some(pos) = t[last_pos..].find("$world") {
    let p = pos + last_pos; // find always starts at last_pos
    last_pos = pos + 5;
    unsafe {
        let s = t.to_mut().as_mut_vec(); // operating on Vec is easier
        s.remove(p); // remove $ sign
        for (c, sc) in "Earth".bytes().zip(&mut s[p..]) {
            *sc = c;
        }
    }
}

請注意,這是根據“$ world” - >“Earth”映射精確定制的。 任何其他映射都需要在不安全的代碼中仔細考慮。

std::borrow::Cow ,專門用作Cow<'a, str> ,其中'a是被解析字符串的生命周期。

use std::borrow::Cow;

fn main() {
    let mut v: Vec<Cow<'static, str>> = vec![];
    v.push("oh hai".into());
    v.push(format!("there, {}.", "Mark").into());

    println!("{:?}", v);
}

生產:

["oh hai", "there, Mark."]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM