不清楚如何正确定义结构的生命周期
Not clear how to correctly define lifetime for struct
我有 TCP 客户端,它处理一些处理程序。我需要在它们之间共享数据,所以我为这种情况实现了 Session
结构:
struct Session<'a> {
pub session_key: Option<&'a Vec<u8>>,
pub username: Option<&'a str>,
pub password: Option<&'a str>,
}
impl Session {
pub fn new() -> Self {
Self {
session_key: None,
username: None,
password: None,
}
}
}
我添加了引用访问以允许借用数据。
但是,当我尝试在我的代码中使用这个结构时,出现了与生命周期相关的错误:
implicit elided lifetime not allowed here
或
cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
这是minimal sandbox implementation。
以防万一这是我的示例代码(大部分与我的真实应用程序相似):
// data which store values that I need to share between handlers
struct Session<'a> {
pub session_key: Option<&'a Vec<u8>>,
pub username: Option<&'a str>,
pub password: Option<&'a str>,
}
// not sure if this correct to set &None below, where to put the lifetime here ?
impl Session {
pub fn new() -> Self {
Self {
session_key: None,
username: None,
password: None,
}
}
}
// what handler return
pub enum HandlerResponse {
Packet(Vec<u8>),
Void,
}
// handler params
pub struct HandlerInput<'a> {
session: &'a mut Session<'a>,
data: Option<Vec<u8>>
}
pub struct Client<'a> {
stream: Option<TcpStream>,
buffer: [u8; 4096],
session: Session<'a>,
}
// public methods
impl<'a> Client<'a> {
pub fn new() -> Self {
Self {
stream: None,
buffer: [0u8; 4096],
session: Session::new(),
}
}
pub fn connect(&mut self, host: &str, port: i16) {
let addr = format!("{}:{}", host, port);
match TcpStream::connect(&addr) {
Ok(stream) => {
self.stream = Some(stream);
println!("Connected to {}", addr);
},
_ => {
println!("Cannot connect");
},
}
}
pub fn handle_connection(
&mut self,
handlers: Vec<fn(HandlerInput
) -> Result<u8, Error>>) {
for handler in handlers {
self.process(handler);
}
}
}
// private methods
impl<'a> Client<'a> {
fn process<F>(&mut self, handler: F)
where
F: Fn(HandlerInput) -> Result<HandlerResponse, Error>
{
let response: Result<HandlerResponse, Error> = match self.handle_read() {
Ok(server_response) => handler(HandlerInput {
session: &mut self.session,
data: Some(server_response),
}),
_ => handler(HandlerInput {
session: &mut self.session,
data: None,
})
};
match response.unwrap() {
HandlerResponse::Packet(data) => {
self.handle_write(data).unwrap();
},
HandlerResponse::Void => {},
}
}
fn handle_write(&mut self, packet: Vec<u8>) -> Result<(), Error> {
let mut stream = self.stream.as_ref().unwrap();
match stream.write(&packet) {
Ok(_) => Ok(()),
_ => Err(Error::new(ErrorKind::Other, "Write error")),
}
}
fn handle_read(&mut self) -> Result<Vec<u8>, Error> {
let mut stream = self.stream.as_ref().unwrap();
let mut buffer = self.buffer.as_mut();
match stream.read(&mut buffer) {
Ok(bytes_count) => {
return Ok(buffer[ .. bytes_count].to_vec());
},
_ => Err(Error::new(ErrorKind::Other, "Read error")),
}
}
}
当我将生命周期放在 Client
结构上,然后将生命周期放在 &'a mut self
上时,我得到一个错误:
cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
你能在这里解释一下如何修复生命周期吗?
更新:
我需要在 Session
中引用,因为我想在处理程序中使用会话的值,如果我不使用引用,我会收到错误消息:
move occurs because input.session.session_key
has type Option<Vec<u8>>
, which does not implement the Copy
trait
代码我是怎么用的 Session
:
fn handler(input: HandlerInput) {
let hasher = Sha1::new();
let digest = hasher
.chain(input.session.username.unwrap())
.chain(input.session.session_key.unwrap())
.finalize();
}
有时我还需要修改处理程序中的输入,例如:
let mut session = input.session;
session.session_key = Some(srp_client.session_key());
我可以看到两个问题:
- 您的简短示例代码缺少生命周期注释
- 你的较长代码是借用几乎不可能实现的实现,因此我怀疑这个问题是XY-problem。
快速修复您的短代码示例
您的 impl
缺少生命周期:
pub struct Session<'a> {
pub session_key: Option<&'a Vec<u8>>,
pub username: Option<&'a str>,
pub password: Option<&'a str>,
}
impl<'a> Session<'a> {
pub fn new() -> Self {
Self {
session_key: None,
username: None,
password: None,
}
}
}
您可能真正想要的
所以我的问题是,为什么首先要为 Session
使用借用?
从技术上讲,您只需要 HandlerInput
中的参考。然后,两个处理程序看到相同的 Session
对象进行修改。
use std::io::{Error, ErrorKind, Read, Write};
use std::net::TcpStream;
// data which store values that I need to share between handlers
struct Session {
pub session_key: Option<Vec<u8>>,
pub username: Option<String>,
pub password: Option<String>,
}
// not sure if this correct to set &None below, where to put the lifetime here ?
impl Session {
pub fn new() -> Self {
Self {
session_key: None,
username: None,
password: None,
}
}
}
// what handler return
pub enum HandlerResponse {
Packet(Vec<u8>),
Void,
}
// handler params
pub struct HandlerInput<'a> {
session: &'a mut Session,
data: Option<Vec<u8>>,
}
pub struct Client {
stream: Option<TcpStream>,
buffer: [u8; 4096],
session: Session,
}
// public methods
impl Client {
pub fn new() -> Self {
Self {
stream: None,
buffer: [0u8; 4096],
session: Session::new(),
}
}
pub fn connect(&mut self, host: &str, port: i16) {
let addr = format!("{}:{}", host, port);
match TcpStream::connect(&addr) {
Ok(stream) => {
self.stream = Some(stream);
println!("Connected to {}", addr);
}
_ => {
println!("Cannot connect");
}
}
}
pub fn handle_connection(
&mut self,
handlers: Vec<fn(HandlerInput) -> Result<HandlerResponse, Error>>,
) {
for handler in handlers {
self.process(handler);
}
}
}
// private methods
impl Client {
fn process<F>(&mut self, handler: F)
where
F: Fn(HandlerInput) -> Result<HandlerResponse, Error>,
{
let response: Result<HandlerResponse, Error> = match self.handle_read() {
Ok(server_response) => handler(HandlerInput {
session: &mut self.session,
data: Some(server_response),
}),
_ => handler(HandlerInput {
session: &mut self.session,
data: None,
}),
};
match response.unwrap() {
HandlerResponse::Packet(data) => {
self.handle_write(data).unwrap();
}
HandlerResponse::Void => {}
}
}
fn handle_write(&mut self, packet: Vec<u8>) -> Result<(), Error> {
let mut stream = self.stream.as_ref().unwrap();
match stream.write(&packet) {
Ok(_) => Ok(()),
_ => Err(Error::new(ErrorKind::Other, "Write error")),
}
}
fn handle_read(&mut self) -> Result<Vec<u8>, Error> {
let mut stream = self.stream.as_ref().unwrap();
let mut buffer = self.buffer.as_mut();
match stream.read(&mut buffer) {
Ok(bytes_count) => {
return Ok(buffer[..bytes_count].to_vec());
}
_ => Err(Error::new(ErrorKind::Other, "Read error")),
}
}
}
fn handler1(input: HandlerInput) -> Result<HandlerResponse, Error> {
Ok(HandlerResponse::Void)
}
fn handler2(input: HandlerInput) -> Result<HandlerResponse, Error> {
Ok(HandlerResponse::Void)
}
fn main() {
let mut client = Client::new();
client.connect("127.0.0.1", 8080);
client.handle_connection(vec![handler1, handler2]);
}
编译正常,应该可以工作。
我有 TCP 客户端,它处理一些处理程序。我需要在它们之间共享数据,所以我为这种情况实现了 Session
结构:
struct Session<'a> {
pub session_key: Option<&'a Vec<u8>>,
pub username: Option<&'a str>,
pub password: Option<&'a str>,
}
impl Session {
pub fn new() -> Self {
Self {
session_key: None,
username: None,
password: None,
}
}
}
我添加了引用访问以允许借用数据。 但是,当我尝试在我的代码中使用这个结构时,出现了与生命周期相关的错误:
implicit elided lifetime not allowed here
或
cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
这是minimal sandbox implementation。
以防万一这是我的示例代码(大部分与我的真实应用程序相似):
// data which store values that I need to share between handlers
struct Session<'a> {
pub session_key: Option<&'a Vec<u8>>,
pub username: Option<&'a str>,
pub password: Option<&'a str>,
}
// not sure if this correct to set &None below, where to put the lifetime here ?
impl Session {
pub fn new() -> Self {
Self {
session_key: None,
username: None,
password: None,
}
}
}
// what handler return
pub enum HandlerResponse {
Packet(Vec<u8>),
Void,
}
// handler params
pub struct HandlerInput<'a> {
session: &'a mut Session<'a>,
data: Option<Vec<u8>>
}
pub struct Client<'a> {
stream: Option<TcpStream>,
buffer: [u8; 4096],
session: Session<'a>,
}
// public methods
impl<'a> Client<'a> {
pub fn new() -> Self {
Self {
stream: None,
buffer: [0u8; 4096],
session: Session::new(),
}
}
pub fn connect(&mut self, host: &str, port: i16) {
let addr = format!("{}:{}", host, port);
match TcpStream::connect(&addr) {
Ok(stream) => {
self.stream = Some(stream);
println!("Connected to {}", addr);
},
_ => {
println!("Cannot connect");
},
}
}
pub fn handle_connection(
&mut self,
handlers: Vec<fn(HandlerInput
) -> Result<u8, Error>>) {
for handler in handlers {
self.process(handler);
}
}
}
// private methods
impl<'a> Client<'a> {
fn process<F>(&mut self, handler: F)
where
F: Fn(HandlerInput) -> Result<HandlerResponse, Error>
{
let response: Result<HandlerResponse, Error> = match self.handle_read() {
Ok(server_response) => handler(HandlerInput {
session: &mut self.session,
data: Some(server_response),
}),
_ => handler(HandlerInput {
session: &mut self.session,
data: None,
})
};
match response.unwrap() {
HandlerResponse::Packet(data) => {
self.handle_write(data).unwrap();
},
HandlerResponse::Void => {},
}
}
fn handle_write(&mut self, packet: Vec<u8>) -> Result<(), Error> {
let mut stream = self.stream.as_ref().unwrap();
match stream.write(&packet) {
Ok(_) => Ok(()),
_ => Err(Error::new(ErrorKind::Other, "Write error")),
}
}
fn handle_read(&mut self) -> Result<Vec<u8>, Error> {
let mut stream = self.stream.as_ref().unwrap();
let mut buffer = self.buffer.as_mut();
match stream.read(&mut buffer) {
Ok(bytes_count) => {
return Ok(buffer[ .. bytes_count].to_vec());
},
_ => Err(Error::new(ErrorKind::Other, "Read error")),
}
}
}
当我将生命周期放在 Client
结构上,然后将生命周期放在 &'a mut self
上时,我得到一个错误:
cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
你能在这里解释一下如何修复生命周期吗?
更新:
我需要在 Session
中引用,因为我想在处理程序中使用会话的值,如果我不使用引用,我会收到错误消息:
move occurs because
input.session.session_key
has typeOption<Vec<u8>>
, which does not implement theCopy
trait
代码我是怎么用的 Session
:
fn handler(input: HandlerInput) {
let hasher = Sha1::new();
let digest = hasher
.chain(input.session.username.unwrap())
.chain(input.session.session_key.unwrap())
.finalize();
}
有时我还需要修改处理程序中的输入,例如:
let mut session = input.session;
session.session_key = Some(srp_client.session_key());
我可以看到两个问题:
- 您的简短示例代码缺少生命周期注释
- 你的较长代码是借用几乎不可能实现的实现,因此我怀疑这个问题是XY-problem。
快速修复您的短代码示例
您的 impl
缺少生命周期:
pub struct Session<'a> {
pub session_key: Option<&'a Vec<u8>>,
pub username: Option<&'a str>,
pub password: Option<&'a str>,
}
impl<'a> Session<'a> {
pub fn new() -> Self {
Self {
session_key: None,
username: None,
password: None,
}
}
}
您可能真正想要的
所以我的问题是,为什么首先要为 Session
使用借用?
从技术上讲,您只需要 HandlerInput
中的参考。然后,两个处理程序看到相同的 Session
对象进行修改。
use std::io::{Error, ErrorKind, Read, Write};
use std::net::TcpStream;
// data which store values that I need to share between handlers
struct Session {
pub session_key: Option<Vec<u8>>,
pub username: Option<String>,
pub password: Option<String>,
}
// not sure if this correct to set &None below, where to put the lifetime here ?
impl Session {
pub fn new() -> Self {
Self {
session_key: None,
username: None,
password: None,
}
}
}
// what handler return
pub enum HandlerResponse {
Packet(Vec<u8>),
Void,
}
// handler params
pub struct HandlerInput<'a> {
session: &'a mut Session,
data: Option<Vec<u8>>,
}
pub struct Client {
stream: Option<TcpStream>,
buffer: [u8; 4096],
session: Session,
}
// public methods
impl Client {
pub fn new() -> Self {
Self {
stream: None,
buffer: [0u8; 4096],
session: Session::new(),
}
}
pub fn connect(&mut self, host: &str, port: i16) {
let addr = format!("{}:{}", host, port);
match TcpStream::connect(&addr) {
Ok(stream) => {
self.stream = Some(stream);
println!("Connected to {}", addr);
}
_ => {
println!("Cannot connect");
}
}
}
pub fn handle_connection(
&mut self,
handlers: Vec<fn(HandlerInput) -> Result<HandlerResponse, Error>>,
) {
for handler in handlers {
self.process(handler);
}
}
}
// private methods
impl Client {
fn process<F>(&mut self, handler: F)
where
F: Fn(HandlerInput) -> Result<HandlerResponse, Error>,
{
let response: Result<HandlerResponse, Error> = match self.handle_read() {
Ok(server_response) => handler(HandlerInput {
session: &mut self.session,
data: Some(server_response),
}),
_ => handler(HandlerInput {
session: &mut self.session,
data: None,
}),
};
match response.unwrap() {
HandlerResponse::Packet(data) => {
self.handle_write(data).unwrap();
}
HandlerResponse::Void => {}
}
}
fn handle_write(&mut self, packet: Vec<u8>) -> Result<(), Error> {
let mut stream = self.stream.as_ref().unwrap();
match stream.write(&packet) {
Ok(_) => Ok(()),
_ => Err(Error::new(ErrorKind::Other, "Write error")),
}
}
fn handle_read(&mut self) -> Result<Vec<u8>, Error> {
let mut stream = self.stream.as_ref().unwrap();
let mut buffer = self.buffer.as_mut();
match stream.read(&mut buffer) {
Ok(bytes_count) => {
return Ok(buffer[..bytes_count].to_vec());
}
_ => Err(Error::new(ErrorKind::Other, "Read error")),
}
}
}
fn handler1(input: HandlerInput) -> Result<HandlerResponse, Error> {
Ok(HandlerResponse::Void)
}
fn handler2(input: HandlerInput) -> Result<HandlerResponse, Error> {
Ok(HandlerResponse::Void)
}
fn main() {
let mut client = Client::new();
client.connect("127.0.0.1", 8080);
client.handle_connection(vec![handler1, handler2]);
}
编译正常,应该可以工作。