rust库-ouroboros中文文档

news/2024/9/12 21:22:45/文章来源:https://www.cnblogs.com/cnyuyang/p/18372742

文档原文:https://docs.rs/ouroboros/latest/ouroboros/attr.self_referencing.html

属性宏ouroboros::self_referencing

#[self_referencing]

此宏用于将常规结构转换为自引用结构。举个例子:

use ouroboros::self_referencing;#[self_referencing]
struct MyStruct {int_data: i32,float_data: f32,#[borrows(int_data)]// `this这个生命周期是由#[self_referending]宏创建的// 并且应该用在所有由#[borrows]宏标记的引用上int_reference: &'this i32,#[borrows(mut float_data)]float_reference: &'this mut f32,
}fn main() {// 构建器由#[self_referending]宏创建// 并用于创建结构体let mut my_value = MyStructBuilder {int_data: 42,float_data: 3.14,// 注意构造器中的字段名称// 是struct +'_builder'结构中的字段名// 即:{field_name}_builder// 为字段赋值的闭包将被传递// 对#[borrows]宏中定义的字段的引用int_reference_builder: |int_data: &i32| int_data,float_reference_builder: |float_data: &mut f32| float_data,}.build();// 不能直接访问原始结构体中的字段// 构造器创建的访问器调用的方法为 borrow_{field_name}()// 打印 42println!("{:?}", my_value.borrow_int_data());// 打印 3.14println!("{:?}", my_value.borrow_float_reference());// 设置float_data值为84.0my_value.with_mut(|fields| {**fields.float_reference = (**fields.int_reference as f32) * 2.0;});// 我们可以持有这个引用...let int_ref = *my_value.borrow_int_reference();println!("{:?}", *int_ref);// 只要结构体还活着drop(my_value);// 下面的使用是会报错的// println!("{:?}", *int_ref);
}

通过RustRover观察创建出来的结构体包装出了以下方法:

返回值类型为:

为了解释这个crate的特点和局限性,一些定义是必要的:

定义

  • 不可变借用字段:至少被一个其他字段不可变借用的字段。
  • 可变借用字段:正好由另一个字段可变借用的字段。
  • self-referencing field:至少借用一个其他字段的字段。
  • head field:不借用任何其他字段的字段,即不自引用的字段。 这不包括具有空借用(#[borrows()])的字段
  • tail field:未被任何其他字段借用的字段。

使用

要创建自引用结构体,必须编写结构体定义并将#[self_referending]置于顶部。对于每个借用其他字段的字段,必须将#[borrows()]放在顶部,并在括号内放置它借用的字段列表。可以加上Mut前缀,以指示需要可变借用。例如,#[borrows(a, b, mut c)]表示前两个字段需要不可变地借入,第三个字段需要可变地借入。你也可以使用不带任何参数的#[borrows()]来表示一个字段,该字段最终将从结构中借入,但在第一次创建时不会借入任何东西。例如,你可以在一个字段上使用:error: Option<&'this str>

您必须遵守这些限制

  • 字段必须在第一次借用之前声明。
  • 正常的借用规则适用,例如,一个字段不能被借用两次。
  • 使用'this生存期的字段必须有一个对应的#[borrows()]注释。

违反它们将导致错误消息直接指出违反的规则。

该crate的灵活性

上面的示例使用纯引用作为结构的自引用部分,但您可以使用依赖于结构中对象生存期的任何内容。例如,您可以 做这样的事情:

use ouroboros::self_referencing;pub struct ComplexData<'a, 'b> {aref: &'a i32,bref: &'b mut i32,number: i32,
}impl<'a, 'b> ComplexData<'a, 'b> {fn new(aref: &'a i32, bref: &'b mut i32, number: i32) -> Self {Self { aref, bref, number }}/// Copies the value aref points to into what bref points to.fn transfer(&mut self) {*self.bref = *self.aref;}/// Prints the value bref points to.fn print_bref(&self) {println!("{}", *self.bref);}
}fn main() {#[self_referencing]struct DataStorage {immutable: i32,mutable: i32,#[borrows(immutable, mut mutable)]#[not_covariant]complex_data: ComplexData<'this, 'this>,}let mut data_storage = DataStorageBuilder {immutable: 10,mutable: 20,complex_data_builder: |i: &i32, m: &mut i32| ComplexData::new(i, m, 12345),}.build();data_storage.with_complex_data_mut(|data| {// Copies the value in immutable into mutable.data.transfer();// Prints 10data.print_bref();});
}

协变性

在Rust语言中,许多类型具有一种称为“协变性”的属性。实际上,这意味着像Box<&'this i32>这样的协变类型可以用作Box<&'a i32>,只要’a比’this小。由于生命周期更短,因此它不会违反原始类型指定的生命周期。这与Fn(&'this i32)不同,它不是协变的。你不能给这个函数一个生命周期短于’this的引用,因为函数需要至少与’this一样长的东西。不幸的是,从宏内部无法轻易确定一个类型是否具有协变性。因此,您可能会收到一个编译器错误,让您知道宏不确定一个特定字段是否使用了协变类型。添加#[covariant]或#[not_covariant]可以解决此问题。

这些注解控制是否为该字段生成borrow_*方法。错误地使用这些标签将导致编译错误。它们不可能被不安全地使用。

生成的项目列表

MyStruct::new(fields...) -> MyStruct

基本构造函数。它按照您在中声明的顺序接受每个字段的值。对于head字段,你只需要传入它应该有的值,它将被移动到输出中。对于自引用字段,您必须提供一个函数或闭包,它根据它借用的值来创建值。使用前面的示例#[借入(a,b,mut c)]的字段将需要一个类型为FnOnce(a: &, b: &, c: &mut _) -> _的函数。具有空借用注释(#[借入()])的字段应将其值直接传递给。使用前面的Option<&'this str>示例的字段将要求输入None。不要传递函数。不收200元。

MyStruct::new_async(fields...) -> MyStruct

MyStruct::new_async_send(fields...) -> MyStruct

MyStructBuilder

MyStructAsyncBuilder

MyStructAsyncSendBuilder

MyStruct::try_new<E>(fields...) -> Result<MyStruct, E>

MyStruct::try_new_async<E>(fields...) -> Result<MyStruct, E>

MyStruct::try_new_async_send<E>(fields...) -> Result<MyStruct, E>

MyStruct::try_new_or_recover_async<E>(fields...) -> Result<MyStruct, (E, Heads)>

MyStruct::try_new_or_recover_async_send<E>(fields...) -> Result<MyStruct, (E, Heads)>

MyStruct::with_FIELD<R>(&self, user: FnOnce(field: &FieldType) -> R) -> R

MyStruct::borrow_FIELD(&self) -> &FieldType

MyStruct::with_FIELD_mut<R>(&mut self, user: FnOnce(field: &mut FieldType) -> R) -> R

MyStruct::with<R>(&self, user: FnOnce(fields: AllFields) -> R) -> R

MyStruct::with_mut<R>(&self, user: FnOnce(fields: AllFields) -> R) -> R

MyStruct::into_heads(self) -> Heads

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/785129.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mini-lsm通关笔记Week1Day4

项目地址:https://github.com/skyzh/mini-lsm 个人实现地址:https://gitee.com/cnyuyang/mini-lsmTask 1-SST Builder在此任务中,您需要修改: src/table/builder.rs src/table.rs SST由存储在磁盘上的数据块和索引块组成。通常,数据块都是懒加载的-直到用户发出请求,它们…

高效流程办公,相信自定义流程表单开发

对于自定义流程表单开发的优势特点,可以在本文中获得详细答案。如果要将企业内部的数据做好高效管理,需要借助更优质的软件平台。低代码技术平台够灵活、更高效、易维护、可视化操作等,可以满足日益扩大的业务需求,助力企业做好数据资源管理,共同为实现流程化办公和数字化…

041、Vue3+TypeScript基础,使用pinia库来储存数据

01、输入npm install pinia 02、main.js代码如下:// 引入createApp用于创建Vue实例 import {createApp} from vue // 引入App.vue根组件 import App from ./App.vue//第一步:引入pinia import {createPinia} from piniaconst app = createApp(App);//第二步:创建pinia实例 c…

三维几何生成:多段线、圆弧

一、三维空间多段线几何 1 应用背景 ​​  opengl常用glLineWidth命令设置线宽,此线宽在透视投影中不会随着相机远近变化而缩放。项目中高版本glLineWidth命令失效,需要考虑如何快速、方便、宽度不变的多段线几何。方案a:纯shader绘制曲线,绘制到一个二维平面上,然后将平…

本地快速安装运行史上最强开源LLaMa3大模型

https://liaoxuefeng.com/blogs/all/2024-05-06-llama3/史上最强开源AI大模型——Meta的LLaMa3一经发布,各项指标全面逼近GPT-4。它提供了8B和70B两个版本,8B版本最低仅需4G显存即可运行,可以说是迄今为止能在本地运行的最强LLM。 虽然LLaMa3对中文支持不算好,但HuggingFac…

第二章 redis环境安装与配置

redis环境安装 redis的官方只提供了linux版本的redis,window系统的redis是微软团队根据官方的linux版本高仿的。 官方原版: https://redis.io/ 中文官网:http://www.redis.cn 1、下载和安装 下载地址:https://github.com/tporadowski/redis/releases使用以下命令启动redis服务…

CVSS(Common Vulnerability Scoring System)打分规则解读

CVSS(Common Vulnerability Scoring System)提供了一种根据漏洞的主要特征进行打分,反映其严重性的方法。CVSS 已成为被广泛使用的标准。 下面是CVSS 3.1版本计算器的界面截图,本文对Base Score的打分标准做解读,并提供一些建议。同时会列出每个维度选项的翻译。 Attack V…

插入排序详细解读

插入排序详细解读 图解 第一轮:从第二位置的 6 开始比较,比前面 7 小,交换位置。第二轮:第三位置的 9 比前一位置的 7 大,无需交换位置。第三轮:第四位置的 3 比前一位置的 9 小交换位置,依次往前比较。第四轮:第五位置的 1 比前一位置的 9 小,交换位置,再依次往前比…

一张图看懂SAP主要流程

一张图看懂SAP主要流程

第一章 redis简单介绍

一、引言 在Web应用发展的初期,那时关系型数据库受到了较为广泛的关注和应用,原因是因为那时候Web站点基本上访问和并发不高、交互也较少。而在后来,随着访问量的提升,使用关系型数据库的Web站点多多少少都开始在性能上出现了一些瓶颈,而瓶颈的源头一般是在磁盘的I/O上。而…

第17章_反射机制

该篇笔记,是因为想重新学一下Spring Cloud 和Spring Cloud Alibaba框架,但是b站尚硅谷的最新课程,使用SpringBoot3作为,单体服务的框架,而SpringBoot3最低要求JDK17,所以必须要学一下JDK8-JDK17之间的新特性。本来只想看,宋红康老师课程的第18章JDK8-17新特性,但是觉得…

qt静态编译 全自动编译qt静态库 qt5 windows安装qt (2024.2.23)

全自动编译qt5静态库(2024.2.23) 本教程是从无到有配置qt.io和vcpkg实现全自动编译qt5的静态库,使得您可以静态编译qt项目 0. 安装Visual Studio 2022 这个我就不多解释了,直接去官网下载社区版本,勾选使用C++的桌面开发安装好就行 1. 安装qt.io的开发环境 1.1 下载在线安装…