使用 `pop3::POP3Stream::connect` 连接到给定 `host` 的运行时?
Using `pop3::POP3Stream::connect` to connect to runtime given `host`?
我正在尝试读取用户的输入,然后将其用作 POP3 库的 URL。将我得到的 String
转换为字符串切片时,它的寿命不够长,无法使用。这对我来说很奇怪,原因有二:
因为所有使用POP3对象的东西都在同一个块中,所以str切片的生命周期应该是整个块的生命周期,这将覆盖所有东西
我几乎尝试了所有我能想到的不同代码配置,但都无济于事,每次都出现同样的错误。
extern crate pop3;
extern crate smtp;
extern crate openssl;
extern crate libc;
use openssl::ssl::{SslContext, SslMethod};
use pop3::POP3Stream;
use pop3::POP3Result::{POP3Stat, POP3List, POP3Message};
mod readline;
use readline::*;
fn main() {
let place = match readline("URL: ") { // Problem line
Some(input) => { // Problem line
let place: &'static str = &input[..]; // Problem line
let mut email_socket = match POP3Stream::connect(place, 995, Some(SslContext::new(SslMethod::Sslv23).unwrap())) { // Problem line
Ok(s) => s,
Err(e) => panic!("{}", e)
};
match readline("Username: ") {
Some(username) => {
match readline("Password: ") {
Some(password) => { email_socket.login(&*username, &*password); },
None => println!("Please enter a password.")
}
},
None => println!("Please enter a username.")
};
let stat = email_socket.stat();
match stat {
POP3Stat {num_email,
mailbox_size} => println!("num_email: {}, mailbox_size:{}", num_email, mailbox_size),
e => println!("There was an error signing into your server."),
}
let list_all = email_socket.list(None);
match list_all {
POP3List {emails_metadata} => {
for i in emails_metadata.iter() {
println!("message_id: {}, message_size: {}", i.message_id, i.message_size);
}
},
_ => println!("There was an error listing your messages."),
}
let message_25 = email_socket.retr(25);
match message_25 {
POP3Message{raw} => {
for i in raw.iter() {
println!("{}", i);
}
},
_ => println!("There was an error getting your 25th message."),
}
email_socket.quit();
},
None => { println!("Please enter a URL for your server."); }
};
}
问题
您的问题归结为 static
的使用,因为关键字基本上是 "keep this object around forever"。这意味着 place
的生命周期毫无疑问会在 input
之后很长一段时间——永远 vs 块的范围。
fn get() -> Option<String> {
Some("hello world".to_owned())
}
fn main() {
let data = match get() {
Some(input) => { let place : &'static str = &input[..]; },
None => { }
};
}
在上面我们尝试让place
成为static
对str
的引用,换句话说;在我们计划的整个持续时间内都存在的参考。 input
另一方面,这段时间肯定不会存在,因此我们得到错误诊断。
<anon>:7:54: 7:59 error: `input` does not live long enough
<anon>:7 Some(input) => { let place : &'static str = &input[..]; },
解决方案
删除 static
的使用,实际上是说 place
的生命周期是块的生命周期(它是与 input
关联的生命周期的子集)。
fn get() -> Option<String> {
Some("hello world".to_owned())
}
fn main() {
let data = match get() {
Some(input) => { let place : &str = &input[..]; },
None => { }
};
}
进一步挖掘
事实证明,POP3Stream::connect
接受一个 &'static str
作为它的第一个参数;这是非常糟糕的设计,因为它只接受字符串文字。
impl Pop3Stream {
pub fn connect(host: &'static str, ...) -> Result<POP3Stream> {
...
}
}
但是,您可以通过故意泄露资源来解决问题——有效地使其生效 "forever"。请注意 unsafe
的用法,并记住这是——根据语言设计——被认为就是那样。
fn get () -> Option<String> {
Some("hello world".to_owned ())
}
fn connect (host : &'static str) {
/* ... */
}
fn main() {
let data = match get() {
Some(input) => {
let place : &'static str = unsafe {
use std::mem; let x = mem::transmute(&input as &str);
mem::forget (x); x
};
connect(place);
},
None => { }
};
}
我正在尝试读取用户的输入,然后将其用作 POP3 库的 URL。将我得到的 String
转换为字符串切片时,它的寿命不够长,无法使用。这对我来说很奇怪,原因有二:
因为所有使用POP3对象的东西都在同一个块中,所以str切片的生命周期应该是整个块的生命周期,这将覆盖所有东西
我几乎尝试了所有我能想到的不同代码配置,但都无济于事,每次都出现同样的错误。
extern crate pop3;
extern crate smtp;
extern crate openssl;
extern crate libc;
use openssl::ssl::{SslContext, SslMethod};
use pop3::POP3Stream;
use pop3::POP3Result::{POP3Stat, POP3List, POP3Message};
mod readline;
use readline::*;
fn main() {
let place = match readline("URL: ") { // Problem line
Some(input) => { // Problem line
let place: &'static str = &input[..]; // Problem line
let mut email_socket = match POP3Stream::connect(place, 995, Some(SslContext::new(SslMethod::Sslv23).unwrap())) { // Problem line
Ok(s) => s,
Err(e) => panic!("{}", e)
};
match readline("Username: ") {
Some(username) => {
match readline("Password: ") {
Some(password) => { email_socket.login(&*username, &*password); },
None => println!("Please enter a password.")
}
},
None => println!("Please enter a username.")
};
let stat = email_socket.stat();
match stat {
POP3Stat {num_email,
mailbox_size} => println!("num_email: {}, mailbox_size:{}", num_email, mailbox_size),
e => println!("There was an error signing into your server."),
}
let list_all = email_socket.list(None);
match list_all {
POP3List {emails_metadata} => {
for i in emails_metadata.iter() {
println!("message_id: {}, message_size: {}", i.message_id, i.message_size);
}
},
_ => println!("There was an error listing your messages."),
}
let message_25 = email_socket.retr(25);
match message_25 {
POP3Message{raw} => {
for i in raw.iter() {
println!("{}", i);
}
},
_ => println!("There was an error getting your 25th message."),
}
email_socket.quit();
},
None => { println!("Please enter a URL for your server."); }
};
}
问题
您的问题归结为 static
的使用,因为关键字基本上是 "keep this object around forever"。这意味着 place
的生命周期毫无疑问会在 input
之后很长一段时间——永远 vs 块的范围。
fn get() -> Option<String> {
Some("hello world".to_owned())
}
fn main() {
let data = match get() {
Some(input) => { let place : &'static str = &input[..]; },
None => { }
};
}
在上面我们尝试让place
成为static
对str
的引用,换句话说;在我们计划的整个持续时间内都存在的参考。 input
另一方面,这段时间肯定不会存在,因此我们得到错误诊断。
<anon>:7:54: 7:59 error: `input` does not live long enough
<anon>:7 Some(input) => { let place : &'static str = &input[..]; },
解决方案
删除 static
的使用,实际上是说 place
的生命周期是块的生命周期(它是与 input
关联的生命周期的子集)。
fn get() -> Option<String> {
Some("hello world".to_owned())
}
fn main() {
let data = match get() {
Some(input) => { let place : &str = &input[..]; },
None => { }
};
}
进一步挖掘
事实证明,POP3Stream::connect
接受一个 &'static str
作为它的第一个参数;这是非常糟糕的设计,因为它只接受字符串文字。
impl Pop3Stream {
pub fn connect(host: &'static str, ...) -> Result<POP3Stream> {
...
}
}
但是,您可以通过故意泄露资源来解决问题——有效地使其生效 "forever"。请注意 unsafe
的用法,并记住这是——根据语言设计——被认为就是那样。
fn get () -> Option<String> {
Some("hello world".to_owned ())
}
fn connect (host : &'static str) {
/* ... */
}
fn main() {
let data = match get() {
Some(input) => {
let place : &'static str = unsafe {
use std::mem; let x = mem::transmute(&input as &str);
mem::forget (x); x
};
connect(place);
},
None => { }
};
}