【rust/egui】(三)看看template的app.rs:序列化、持久化存储

这篇具有很好参考价值的文章主要介绍了【rust/egui】(三)看看template的app.rs:序列化、持久化存储。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

说在前面

  • rust新手,egui没啥找到啥教程,这里自己记录下学习过程
  • 环境:windows11 22H2
  • rust版本:rustc 1.71.1
  • egui版本:0.22.0
  • eframe版本:0.22.0
  • 上一篇:这里

serde

  • app.rs中首先定义了我们的TemplateApp结构体
    /// 继承序列化以及反序列化 用于存储一些状态数据
    #[derive(serde::Deserialize, serde::Serialize)]
    #[serde(default)] // 在反序列化时,缺少的字段会使用Default特征对应的值进行初始化
    pub struct TemplateApp {
        // Example stuff:
        label: String,
    
        // 声明该字段跳过序列化
        #[serde(skip)]
        value: f32,
    }
    // 为TemplateApp实现Default特征
    impl Default for TemplateApp {
        fn default() -> Self {
            Self {
                // Example stuff:
                label: "Hello World!".to_owned(),
                value: 2.7,
            }
        }
    }
    
  • 在定义TemplateApp时,我们让其继承了serde::Deserialize, serde::Serializeserde是rust中用于序列化和反序列化(serialize and deserialize)一个框架。详细见这里
  • eframe中,我们使用的是ron提供的序列化实现,与json类似,但并不一致,例如以下是一个ron序列化的结果:
    Scene( // class name is optional
        materials: { // this is a map
            "metal": (
                reflectivity: 1.0,
            ),
            "plastic": (
                reflectivity: 0.5,
            ),
        },
        entities: [ // this is an array
            (
                name: "hero",
                material: "metal",
            ),
            (
                name: "monster",
                material: "plastic",
            ),
        ],
    )
    
    详细请参考https://github.com/ron-rs/ron
  • 看一个简单的ron序列化例子
    use serde::{Deserialize, Serialize};
    
    #[derive(Debug, Deserialize, Serialize)]
    struct MyStruct {
        boolean: bool,
        float: f32,
    }
    
    impl MyStruct {
        fn new() -> Self {
            return ron::from_str("(boolean: true, float: 1.23)").unwrap();
        }
    }
    
    fn main() {
        let x = MyStruct::new();
        println!("RON: {}", ron::to_string(&x).unwrap());
    }
    // output:
    // RON: (boolean:true,float:1.23)
    
  • 关于更深层次的内容这里就不再展开了 (咱也展开不下去)

持久化存储

  • 有了serde之后我们可以干什么呢?让我们继续看代码:
    impl TemplateApp {
        /// 在第一帧之前调用
        pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
            // 我们也可以在这里定义我们的界面样式 使用`cc.egui_ctx.set_visuals` and `cc.egui_ctx.set_fonts`.
            
            // 加载一些应用状态(比如上一次打开了那些文件之类的) 但是我们必须启用`persistence`特性
            if let Some(storage) = cc.storage {
            	// 这里我们使用ron取出存入的状态数据 并将其反序列化成TemplateApp
                return eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default();
            }
        
            Default::default()
        }
    }
    
    impl eframe::App for TemplateApp {
        /// 在应用关闭前调用 用于存储状态
        fn save(&mut self, storage: &mut dyn eframe::Storage) {
        	// 这里我们使用ron将TemplateApp序列化 并且存入对应的文件中
            eframe::set_value(storage, eframe::APP_KEY, self);
        }
    
  • 首先我们为TemplateApp实现了new方法
  • 而在之前的main.rs中,我们可以看到该方法的调用,实际上,该函数是在eframe的各种准备工作完成后,才进行的回调
    eframe::run_native(
            "demo app",
            native_options,
            Box::new(|cc| Box::new(demo_app::TemplateApp::new(cc))),
        )
    
  • 在该函数中,我们完成了一些状态数据的还原,即读取应用上一次的工作状态,那么这些数据又是在什么时候存储下来的呢?以及存在了哪里呢?
  • 在接下来的代码中,我们实现了eframe::App特征,在save方法中,我们对状态数据进行了存储,我们可以看看eframe::set_value的具体实现:
    #[cfg(feature = "ron")]
    pub fn set_value<T: serde::Serialize>(storage: &mut dyn Storage, key: &str, value: &T) {
    	// 首先对TemplateApp进行序列化
        match ron::ser::to_string(value) {
        	// 如果序列化成功 那么进一步进行存储 这里并不会立即写文件
            Ok(string) => storage.set_string(key, string),
            // 失败则打印日志
            Err(err) => log::error!("eframe failed to encode data using ron: {}", err),
        }
    }
    
  • 我们可以运行一下应用看看效果,先修改输入:
    【rust/egui】(三)看看template的app.rs:序列化、持久化存储,Rust,rust,开发语言,后端
    关闭应用后再打开:
    【rust/egui】(三)看看template的app.rs:序列化、持久化存储,Rust,rust,开发语言,后端
    可以看到字符串确实保持一致,而数值已经变回原样了。
  • 那我们的数据到底存储在哪里呢?参照上一节的做法,将eframe的日志输出打开,可以看到存储路径打印出来了
    [2023-08-19T09:26:27Z DEBUG eframe] Using the glow renderer
    [2023-08-19T09:26:27Z DEBUG eframe::native::run] Entering the winit event loop (run_return)[2023-08-19T09:26:27Z DEBUG eframe::native::file_storage] Loading app state from "C:\\Users\\xxxx\\AppData\\Roaming\\demo app\\data\\app.ron"
  • 打开文件,可以看到存储的内容确实在,其中还存储了一些其他数据
    【rust/egui】(三)看看template的app.rs:序列化、持久化存储,Rust,rust,开发语言,后端
  • 当我们直接修改对应的数据后再打开应用,对应的数据也发生了变化:
    【rust/egui】(三)看看template的app.rs:序列化、持久化存储,Rust,rust,开发语言,后端
  • 既然是单个文件存储,那么是否会有竞争问题呢?我们打开两个应用A,B
    【rust/egui】(三)看看template的app.rs:序列化、持久化存储,Rust,rust,开发语言,后端
    A想要改字符串,B同时改了字符串和数值,B先关闭,A后关闭
    【rust/egui】(三)看看template的app.rs:序列化、持久化存储,Rust,rust,开发语言,后端
    再次打开应用,B修改的数据丢失了
    【rust/egui】(三)看看template的app.rs:序列化、持久化存储,Rust,rust,开发语言,后端
    因此在开发/使用的时候需要注意多窗口下的数据存储问题

参考

  • serde
  • serde api
  • ron

文章来源地址https://www.toymoban.com/news/detail-666937.html

到了这里,关于【rust/egui】(三)看看template的app.rs:序列化、持久化存储的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【rust/egui】(二)看看template的main函数:日志输出以及eframe run_native

    rust新手,egui没啥找到啥教程,这里自己记录下学习过程 环境:windows11 22H2 rust版本:rustc 1.71.1 egui版本:0.22.0 eframe版本:0.22.0 上一篇:这里 首先让我们看看 main.rs 中有些什么 在 eframe 中使用的日志库为 log 以及 env_logger ,其日志等级有5个: 我们可以在main函数中添加测试一

    2024年02月13日
    浏览(40)
  • rust学习-json的序列化和反序列化

    由于 serde 库默认使用 JSON 格式进行序列化和反序列化 因此程序将使用 JSON 格式对数据进行序列化和反序列化 JSON:广泛使用的 JavaScript 对象符号,用于许多 HTTP API Postcard:no_std 和嵌入式系统友好的紧凑二进制格式。 CBOR:用于小消息大小且无需版本协商的简洁二进制对象表示

    2024年02月12日
    浏览(37)
  • 【rust/egui】(一)从编译运行template开始

    rust新手,egui没啥找到啥教程,这里自己记录下学习过程 环境:windows11 22H2 rust版本:rustc 1.71.1 egui版本:0.22.0 eframe版本:0.22.0 rust windows安装参考:这里 本文默认读者已安装相关环境(git、vscode等) egui github demo online 关于 immediate mode wikipedia microsoft learn 先 clone 下这个项目(也可

    2024年02月13日
    浏览(33)
  • 【序列化与反序列化】关于序列化与反序列化MessagePack的实践

    在进行序列化操作之前,我们还对系统进行压测,通过 jvisualvm 分析cpu,线程,垃圾回收情况等;运用火焰图 async-profiler 分析系统性能,找出程序中占用CPU资源时间最长的代码块。 代码放置GitHub:https://github.com/nateshao/leetcode/tree/main/source-code/src/main/java/com/nateshao/source/code/ser

    2024年02月11日
    浏览(55)
  • 【网络】序列化反序列化

    在前文《网络编程套接字》中,我们实现了服务器与客户端之间的字符串通信,这是非常简单的通信,在实际使用的过程中,网络需要传输的不仅仅是字符串,更多的是结构化的数据(类似于 class , struct 类似的数据)。 那么我们应该怎么发送这些结构化的数据呢? 如果我们

    2024年02月05日
    浏览(42)
  • 序列化,反序列化之实例

    介绍文章 __construct() 当一个对象创建时自动调用 __destruct() 当对象被销毁时自动调用 (php绝大多数情况下会自动调用销毁对象) __sleep() 使**用serialize()函数时触发 __wakeup 使用unserialse()**函数时会自动调用 __toString 当一个对象被当作一个字符串被调用 __call() 在对象上下文中调用不

    2024年02月14日
    浏览(44)
  • 协议,序列化,反序列化,Json

    协议究竟是什么呢?首先得知道主机之间的网络通信交互的是什么数据,像平时使用聊天APP聊天可以清楚,用户看到的不仅仅是聊天的文字,还能够看到用户的头像昵称等其他属性。也就可以证明网络通信不仅仅是交互字符串那么简单。事实上网络通信还可能会通过一个结构

    2024年02月13日
    浏览(38)
  • 【网络】协议定制+序列化/反序列化

    如果光看定义很难理解序列化的意义,那么我们可以从另一个角度来推导出什么是序列化, 那么究竟序列化的目的是什么? 其实序列化最终的目的是为了对象可以 跨平台存储,和进行网络传输 。而我们进行跨平台存储和网络传输的方式就是IO,而我们的IO支持的数据格式就是

    2024年02月08日
    浏览(41)
  • Qt 对象序列化/反序列化

    阅读本文大概需要 3 分钟 日常开发过程中,避免不了对象序列化和反序列化,如果你使用 Qt 进行开发,那么有一种方法实现起来非常简单和容易。 我们知道 Qt 的元对象系统非常强大,基于此属性我们可以实现对象的序列化和反序列化操作。 比如有一个学生类,包含以下几

    2024年02月13日
    浏览(40)
  • Java序列化和反序列化

    目录 一、序列化和反序列化 二、Java序列化演示 三、反序列化漏洞 1、含义 ​序列化就是内存中的对象写入到IO流中,保存的格式可以是二进制或者文本内容。反序列化就是IO流还原成对象。 2、用途 (1)传输网络对象 (2)保存Session 1、序列化 java.io.ObjectOutputStream代表对象

    2023年04月25日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包