Rbj*_*bjz 5 string enums lifetime rust
我有一个非常赏心悦目的东西,但我担心它的含义:
#[derive(Eq, PartialEq, Debug)]
pub enum SmtpHost {
DOMAIN(String),
IPV4(Ipv4Addr),
IPV6(Ipv6Addr),
UNKNOWN { label:String, literal:String },
}
Run Code Online (Sandbox Code Playgroud)
我用 PEG 语法来填充它,&str所以所有的字符串调用看起来都是这样的 -SmtpHost::Domain(s.to_string())
我希望这些枚举成为解析器的结果,例如smtp_parser::host< 'input >(s: 'input & str) -> SmtpHost
我也尝试过 ref 方法,但是很快就开始变得笨拙:
#[derive(Eq, PartialEq, Debug)]
pub enum SmtpHost<'a > {
DOMAIN(&'a str),
IPV4(Ipv4Addr),
IPV6(Ipv6Addr),
UNKNOWN { label:&'a str, literal:&'a str },
}
Run Code Online (Sandbox Code Playgroud)
所以我要么/要么……但你更清楚。告诉我:o)
我的学习项目供参考
&str和之间的关键区别String在于所有权。String拥有,但&str借用。如果存储&str值,容器的生命周期将限于借用字符串的生命周期。
如果您的解析器生成器生成具有如下签名的解析函数:
smtp_parser::host<'a>(&'a str) -> SmtpHost<'a>
Run Code Online (Sandbox Code Playgroud)
然后,当它传递给您一个&str供您用来构造解析树/解析值时,它很可能会为您提供输入的子字符串。这意味着&str您存储在SmtpHost枚举中的生命周期必须短于原始输入字符串。事实上,你可以在签名中看到这一点;输入字符串和输出SmtpHost都有生命周期参数'a。
这意味着您的结果SmtpHost不能比用于生成它的输入寿命更长。如果输入是字符串常量 ,&'static str这可能没问题,但如果您从标准输入或读取文件中获取输入,则将无法返回超过SmtpHost输入字符串所属点的内容。
例如,假设您想声明一个解析SmtpHostfrom 标准的函数:
fn read_host<'a>() -> SmtpHost<'a> {
let mut line = String::new();
let stdin = io::stdin();
stdin.lock().read_line(&mut line).expect("Could not read line");
smtp_parser::host(&line)
}
Run Code Online (Sandbox Code Playgroud)
您会收到一条错误消息,提示“线路寿命不够长”。这是 Rust Playground 中的一个简单示例。
因此,&str当您只是从其他地方借用一个不需要比源寿命更长的值时,应该使用它。String当您需要拥有该值的所有权时,应该使用。
对于更复杂的情况,您需要拥有一个拥有的值,但希望能够在多个地方使用它,而不需要拥有它的许多副本,为此,有Rc<T>和Rc<RefCell<T>。但就你而言,听起来SmtpHost应该只拥有它存储的字符串的所有权。