我如何 return 来自 String.split().collect() 的数据?
How do I return data from String.split().collect()?
最近我一直在尝试开发《超级星际迷航》游戏的 Rust 版本。但是,我 运行 在加载保存的游戏时遇到了一个小问题。
为了加载游戏,我将保存文件读入一个字符串,将其拆分为 Vec<&str> at(以 \0x1e 作为分隔符),然后在两个结果上使用 serde_json::from_str用于获取我的游戏数据对象的元素(一个用于企业,另一个用于宇宙)。
不幸的是,当我尝试 return 它们时,出现以下错误:
57 | return Some((ent, uni))
| ^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
据我所知,这是因为来自 .split.collect() 的数据是所谓的“临时数据”。
如何使 return 结构成为可能?
编辑:这是 github 存储库:https://github.com/thescribe11/Rust-SST
我的代码:
use crate::structs::{Enterprise, Universe};
use std::fs::{File};
use std::io::{Read, Write, stdin, stdout};
use serde_json::{to_string, from_str};
<snip>
pub fn get_config_from_file<'a> () -> Option<(Enterprise, Universe<'a>)>{
//! Thaw a game.
//!
//! The .sst file type is as follows:
//! <json data for Enterprise object>[=13=]x1e<json data for Universe object>
let mut save_file: File;
loop {
let temp = File::open(input("Save file: "));
match temp {
Ok(p) => {save_file = p; break;},
Err(e) => {println!("Unable to find save file.\n"); continue;}
};
}
let pass = input("Password: ");
let mut enc_data = String::new();
match save_file.read_to_string(&mut enc_data) {
Ok(_) => {},
Err(_) => {println!("\nERROR: The save file is corrupted."); return None}
}
let mut ent: Enterprise; let mut uni: Universe;
let raw_parts: Vec<&str> = enc_data.split("[=13=]x1e").collect();
ent = match serde_json::from_str(raw_parts[0]) {
Ok(data) => {data},
Err(_) => {println!("\nERROR: The save file is corrupted."); return None}
};
uni = match serde_json::from_str(raw_parts[1]) {
Ok(data) => data,
Err(_) => {println!("\nERROR: The save file is corrupted."); return None}
};
return Some((ent, uni))
}
我将删除与问题无关的所有内容,从而大大简化您的代码:
use serde::{Deserialize};
#[derive(Debug, Deserialize)]
pub struct Universe<'a> {
#[serde(borrow)]
player_name: Vec<&'a str>,
}
pub fn get_config_from_file<'a> () -> Option<Universe<'a>> {
let raw: String = "some_data".to_string();
let uni: Universe = serde_json::from_str(&raw).unwrap();
return Some(uni);
}
这仍然给出以下错误信息:
error[E0515]: cannot return value referencing local variable `raw`
--> src/lib.rs:12:12
|
11 | let uni: Universe = serde_json::from_str(&raw).unwrap();
| ---- `raw` is borrowed here
12 | return Some(uni);
| ^^^^^^^^^ returns a value referencing data owned by the current function
这里有什么问题?
uni.player_name
是包含 &str
的 Vec
。这个 &str
借用(意思是:是对 raw
的引用——但是 raw
在 get_config_from_file
的末尾超出范围,所以 uni
不能活得比那更长。但是,您尝试 return uni
,这将使它比 get_config_from_file
的末尾存活得更长——Rust 编译器会检测到此问题并通过无法编译您的代码来防止它。
解决此问题的最简单方法是不使用 &str
,而是使用 String
。因为这意味着 'a
生命周期现在未被使用,所以您也需要将其删除。此外,您需要删除 #[serde(borrow)]
– 重点在于代码不应再借用,因此该属性现在是错误的。
代码现在看起来像这样(并且可以编译):
use serde::{Deserialize};
#[derive(Debug, Deserialize)]
pub struct Universe {
player_name: Vec<String>,
}
pub fn get_config_from_file () -> Option<Universe> {
let raw: String = "some_data".to_string();
let uni: Universe = serde_json::from_str(&raw).unwrap();
return Some(uni);
}
最近我一直在尝试开发《超级星际迷航》游戏的 Rust 版本。但是,我 运行 在加载保存的游戏时遇到了一个小问题。
为了加载游戏,我将保存文件读入一个字符串,将其拆分为 Vec<&str> at(以 \0x1e 作为分隔符),然后在两个结果上使用 serde_json::from_str用于获取我的游戏数据对象的元素(一个用于企业,另一个用于宇宙)。
不幸的是,当我尝试 return 它们时,出现以下错误:
57 | return Some((ent, uni))
| ^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
据我所知,这是因为来自 .split.collect() 的数据是所谓的“临时数据”。
如何使 return 结构成为可能?
编辑:这是 github 存储库:https://github.com/thescribe11/Rust-SST
我的代码:
use crate::structs::{Enterprise, Universe};
use std::fs::{File};
use std::io::{Read, Write, stdin, stdout};
use serde_json::{to_string, from_str};
<snip>
pub fn get_config_from_file<'a> () -> Option<(Enterprise, Universe<'a>)>{
//! Thaw a game.
//!
//! The .sst file type is as follows:
//! <json data for Enterprise object>[=13=]x1e<json data for Universe object>
let mut save_file: File;
loop {
let temp = File::open(input("Save file: "));
match temp {
Ok(p) => {save_file = p; break;},
Err(e) => {println!("Unable to find save file.\n"); continue;}
};
}
let pass = input("Password: ");
let mut enc_data = String::new();
match save_file.read_to_string(&mut enc_data) {
Ok(_) => {},
Err(_) => {println!("\nERROR: The save file is corrupted."); return None}
}
let mut ent: Enterprise; let mut uni: Universe;
let raw_parts: Vec<&str> = enc_data.split("[=13=]x1e").collect();
ent = match serde_json::from_str(raw_parts[0]) {
Ok(data) => {data},
Err(_) => {println!("\nERROR: The save file is corrupted."); return None}
};
uni = match serde_json::from_str(raw_parts[1]) {
Ok(data) => data,
Err(_) => {println!("\nERROR: The save file is corrupted."); return None}
};
return Some((ent, uni))
}
我将删除与问题无关的所有内容,从而大大简化您的代码:
use serde::{Deserialize};
#[derive(Debug, Deserialize)]
pub struct Universe<'a> {
#[serde(borrow)]
player_name: Vec<&'a str>,
}
pub fn get_config_from_file<'a> () -> Option<Universe<'a>> {
let raw: String = "some_data".to_string();
let uni: Universe = serde_json::from_str(&raw).unwrap();
return Some(uni);
}
这仍然给出以下错误信息:
error[E0515]: cannot return value referencing local variable `raw`
--> src/lib.rs:12:12
|
11 | let uni: Universe = serde_json::from_str(&raw).unwrap();
| ---- `raw` is borrowed here
12 | return Some(uni);
| ^^^^^^^^^ returns a value referencing data owned by the current function
这里有什么问题?
uni.player_name
是包含 &str
的 Vec
。这个 &str
借用(意思是:是对 raw
的引用——但是 raw
在 get_config_from_file
的末尾超出范围,所以 uni
不能活得比那更长。但是,您尝试 return uni
,这将使它比 get_config_from_file
的末尾存活得更长——Rust 编译器会检测到此问题并通过无法编译您的代码来防止它。
解决此问题的最简单方法是不使用 &str
,而是使用 String
。因为这意味着 'a
生命周期现在未被使用,所以您也需要将其删除。此外,您需要删除 #[serde(borrow)]
– 重点在于代码不应再借用,因此该属性现在是错误的。
代码现在看起来像这样(并且可以编译):
use serde::{Deserialize};
#[derive(Debug, Deserialize)]
pub struct Universe {
player_name: Vec<String>,
}
pub fn get_config_from_file () -> Option<Universe> {
let raw: String = "some_data".to_string();
let uni: Universe = serde_json::from_str(&raw).unwrap();
return Some(uni);
}