使用 AsRef 返回包含在输入包装器类型中的引用
Returning reference contained in an input wrapper type using AsRef
我有一个围绕 &str
的包装器来保持不变性。当我尝试 return 一个新的包装器时,它基本上将参数包装的相同数据包装到一个函数中
(playground),我收到“无法 return 值引用函数参数 s
”
struct MyStrWrapper<'a> {
raw: &'a str,
}
impl AsRef<str> for MyStrWrapper<'_> {
fn as_ref(&self) -> &str {
&self.raw
}
}
fn my_function<'inp>(s: MyStrWrapper<'inp>) -> MyStrWrapper<'inp> {
MyStrWrapper {
raw: &s.as_ref()[1..],
}
}
索引与错误无关,但当我使用 s.raw
而不是通过 as_ref()
直接访问成员时它起作用了。有没有什么好的方法可以避免 raw
对 my_function
可见?
如果主要要求不是使内部 raw
字段对 my_function
可见,并且您可以在包装内部 [=15= 之前使用原始 MyStrWrapper
实例] 在一个新实例中,那么我建议使用 From
特性在 MyStrWrapper
和 &str
之间进行转换,并在 my_function
的实现中使用它。示例:
struct MyStrWrapper<'a> {
raw: &'a str,
}
impl<'a> From<MyStrWrapper<'a>> for &'a str {
fn from(item: MyStrWrapper<'a>) -> Self {
item.raw
}
}
fn my_function<'inp>(s: MyStrWrapper<'inp>) -> MyStrWrapper<'inp> {
// convert MyStrWrapper into &str without exposing "raw" field to function
let inner_str = s.into();
// do whatever you need to do with inner_str here
// re-wrap inner_str here
MyStrWrapper {
raw: inner_str,
}
}
fn main() {
let s = MyStrWrapper {
raw: "Hello, world!",
};
my_function(s);
}
如果你真的想从 my_function
中隐藏 raw
你也可以在另一个方向上实现转换,&str
到 MyStrWrapper
使用 TryFrom
特征,因为如果不满足不变量,转换可能会失败。更新示例:
use std::convert::TryInto;
use std::convert::TryFrom;
struct MyStrWrapper<'a> {
raw: &'a str,
}
impl<'a> From<MyStrWrapper<'a>> for &'a str {
fn from(item: MyStrWrapper<'a>) -> Self {
item.raw
}
}
#[derive(Debug)]
enum MyInvariant {
FailureReason
}
impl<'a> TryFrom<&'a str> for MyStrWrapper<'a> {
type Error = MyInvariant;
fn try_from(item: &'a str) -> Result<Self, Self::Error> {
// check invariant on item
// if fails return Err(MyInvariant::FailureReason)
// else
Ok(MyStrWrapper {
raw: item
})
}
}
fn my_function<'inp>(s: MyStrWrapper<'inp>) -> MyStrWrapper<'inp> {
// convert MyStrWrapper into &str without exposing "raw" field to function
let inner_str: &str = s.into();
// do whatever you need to do with inner_str here
// re-wrap inner_str here
inner_str.try_into().unwrap()
}
fn main() {
let s = MyStrWrapper {
raw: "Hello, world!",
};
my_function(s);
}
您可以将 s
作为具有相同生命周期 (Playground) 的参考传递:
fn my_function<'inp>(s: &'inp MyStrWrapper<'inp>) -> MyStrWrapper<'inp>
然后参考调用:
my_function(&s);
我有一个围绕 &str
的包装器来保持不变性。当我尝试 return 一个新的包装器时,它基本上将参数包装的相同数据包装到一个函数中
(playground),我收到“无法 return 值引用函数参数 s
”
struct MyStrWrapper<'a> {
raw: &'a str,
}
impl AsRef<str> for MyStrWrapper<'_> {
fn as_ref(&self) -> &str {
&self.raw
}
}
fn my_function<'inp>(s: MyStrWrapper<'inp>) -> MyStrWrapper<'inp> {
MyStrWrapper {
raw: &s.as_ref()[1..],
}
}
索引与错误无关,但当我使用 s.raw
而不是通过 as_ref()
直接访问成员时它起作用了。有没有什么好的方法可以避免 raw
对 my_function
可见?
如果主要要求不是使内部 raw
字段对 my_function
可见,并且您可以在包装内部 [=15= 之前使用原始 MyStrWrapper
实例] 在一个新实例中,那么我建议使用 From
特性在 MyStrWrapper
和 &str
之间进行转换,并在 my_function
的实现中使用它。示例:
struct MyStrWrapper<'a> {
raw: &'a str,
}
impl<'a> From<MyStrWrapper<'a>> for &'a str {
fn from(item: MyStrWrapper<'a>) -> Self {
item.raw
}
}
fn my_function<'inp>(s: MyStrWrapper<'inp>) -> MyStrWrapper<'inp> {
// convert MyStrWrapper into &str without exposing "raw" field to function
let inner_str = s.into();
// do whatever you need to do with inner_str here
// re-wrap inner_str here
MyStrWrapper {
raw: inner_str,
}
}
fn main() {
let s = MyStrWrapper {
raw: "Hello, world!",
};
my_function(s);
}
如果你真的想从 my_function
中隐藏 raw
你也可以在另一个方向上实现转换,&str
到 MyStrWrapper
使用 TryFrom
特征,因为如果不满足不变量,转换可能会失败。更新示例:
use std::convert::TryInto;
use std::convert::TryFrom;
struct MyStrWrapper<'a> {
raw: &'a str,
}
impl<'a> From<MyStrWrapper<'a>> for &'a str {
fn from(item: MyStrWrapper<'a>) -> Self {
item.raw
}
}
#[derive(Debug)]
enum MyInvariant {
FailureReason
}
impl<'a> TryFrom<&'a str> for MyStrWrapper<'a> {
type Error = MyInvariant;
fn try_from(item: &'a str) -> Result<Self, Self::Error> {
// check invariant on item
// if fails return Err(MyInvariant::FailureReason)
// else
Ok(MyStrWrapper {
raw: item
})
}
}
fn my_function<'inp>(s: MyStrWrapper<'inp>) -> MyStrWrapper<'inp> {
// convert MyStrWrapper into &str without exposing "raw" field to function
let inner_str: &str = s.into();
// do whatever you need to do with inner_str here
// re-wrap inner_str here
inner_str.try_into().unwrap()
}
fn main() {
let s = MyStrWrapper {
raw: "Hello, world!",
};
my_function(s);
}
您可以将 s
作为具有相同生命周期 (Playground) 的参考传递:
fn my_function<'inp>(s: &'inp MyStrWrapper<'inp>) -> MyStrWrapper<'inp>
然后参考调用:
my_function(&s);