惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MyScale Blog
MyScale Blog
P
Privacy International News Feed
Hugging Face - Blog
Hugging Face - Blog
U
Unit 42
博客园 - 叶小钗
月光博客
月光博客
Microsoft Security Blog
Microsoft Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
The Cloudflare Blog
Project Zero
Project Zero
Cisco Talos Blog
Cisco Talos Blog
The Hacker News
The Hacker News
T
Tor Project blog
阮一峰的网络日志
阮一峰的网络日志
Google DeepMind News
Google DeepMind News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Help Net Security
Help Net Security
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Security Latest
Security Latest
I
Intezer
L
LINUX DO - 最新话题
Blog — PlanetScale
Blog — PlanetScale
T
The Exploit Database - CXSecurity.com
Hacker News - Newest:
Hacker News - Newest: "LLM"
酷 壳 – CoolShell
酷 壳 – CoolShell
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Webroot Blog
Webroot Blog
WordPress大学
WordPress大学
A
About on SuperTechFans
P
Proofpoint News Feed
T
Tailwind CSS Blog
I
InfoQ
The Register - Security
The Register - Security
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
AWS News Blog
AWS News Blog
博客园 - Franky
Simon Willison's Weblog
Simon Willison's Weblog
Last Week in AI
Last Week in AI
博客园 - 聂微东
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google Online Security Blog
Google Online Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Attack and Defense Labs
Attack and Defense Labs
T
Tenable Blog
大猫的无限游戏
大猫的无限游戏
K
Kaspersky official blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
W
WeLiveSecurity
S
Security @ Cisco Blogs
MongoDB | Blog
MongoDB | Blog

Yesterday17's Blog

2026 新年解密红包 / Melody Flag | Yesterday17's Blog 谈谈 Iori 的设计思路(二):如何实现一个 Showroom 录制工具? | Yesterday17's Blog 谈谈 Iori 的设计思路(一):从 Nico Timeshift 说起 | Yesterday17's Blog Iori Minyami 0.1.0 发布 | Yesterday17's Blog 2025 新年解密红包 / Melody Flag | Yesterday17's Blog 使用 Cloudflare Warp 解决罗森票务的海外登录问题 | Yesterday17's Blog How To Blog 04: The Astro v5 Era | Yesterday17's Blog 谈谈 tokio::select! 的公平性 | Yesterday17's Blog Learning Pingora 05 - Connect with TLS | Yesterday17's Blog Leaving Bytedance | Yesterday17's Blog 大橋彩香 AsiaTour「Reflection」上海公演 个人向记录 & Repo | Yesterday17's Blog Recoving from burnout - What happened? | Yesterday17 Yubikey 重建手册 | Yesterday17's Blog How To Blog 03: Heimus | Yesterday17's Blog 🪧 Blog Migration Accouncement | Yesterday17's Blog Learn Your IDE - VSCode 是如何仅重启插件的? | Yesterday17's Blog How To Blog 02: Astro❤️Password | Yesterday17's Blog How To Blog 01: Why, How, and the Future | Yesterday17's Blog Learning Pingora 04 - Establish L4 Connection | Yesterday17's Blog Learning Pingora 03 - Upstreams and Peers | Yesterday17's Blog Learning Pingora 02 - A Simple HTTP Server | Yesterday17's Blog Learning Pingora 01 - Getting Started | Yesterday17's Blog 2024 新年解密红包 / Melody Flag | Yesterday17's Blog 向新的一年飞驰——记录 2023 | Yesterday17's Blog 「サクラノ刻」对话选摘(2) | Yesterday17's Blog PGP Key Revocation 注销声明 | Yesterday17's Blog 「サクラノ刻」对话选摘(1) | Yesterday17's Blog 2023 新年解密红包 / Melody Flag | Yesterday17's Blog 『蒼の彼方のフォーリズム』通关感想 | Yesterday17's Blog 单显卡直通教程 | Yesterday17's Blog 对博客与笔记的思考 | Yesterday17's Blog Project Anni 之旅(3)自动化 Flutter 应用 CI/CD 上架流程 | Yesterday17's Blog AsobiStage 直接播放链接 | Yesterday17 如何在后分P时代进行投稿——sswa使用详解 | Yesterday17's Blog JSON RPC 与 LSP 协议基础 | Yesterday17's Blog Grajapa Shueisha / BookEnd 加密方式调查 | Yesterday17's Blog 【2022篇+WriteUp】如何再收一个新年红包? | Yesterday17's Blog 如何将良心云的良心功能清理干净 | Yesterday17's Blog 【油猴脚本】bilibili 投稿页面返回旧版+旧版页面强制允许分P上传 | Yesterday17's Blog Cloudr1v1 授权方式分析 | Yesterday17 Typora 1.0.2 逆向实录 | Yesterday17's Blog IPv4透明代理+IPv6 Passthrough——树莓派单臂软路由折腾记 | Yesterday17's Blog Chaos; Child 汉化补丁 神秘编码探索 | Yesterday17's Blog 镣铐与舞蹈——个性与共性之迷思 | Yesterday17's Blog Go 学习笔记 02 - 找准 io 之道 | Yesterday17's Blog NAT Slipstreaming v1 原理浅析 | Yesterday17's Blog 绕过「9-nine-」的 CDKEY 验证——KrkrPlugin 正(?)向实录 | Yesterday17's Blog 静流的青春纪念册——「サクラノ刻 -櫻の森の下を歩む-」体验版感言 | Yesterday17's Blog Project Anni 之旅 01 - 从 clap-builder 到 derive | Yesterday17's Blog [Google CTF 2021] CPP WriteUp | Yesterday17's Blog 获取 アソビステージ 的实际播放链接 | Yesterday17's Blog 90 行 Rust 代码实现 AsyncTeeReader | Yesterday17's Blog 或许还算有价值一读的文章列表 | Yesterday17's Blog 从零开始的 Seedbox 之旅 | Yesterday17's Blog [随笔]技术型博客行文迷思(1) | Yesterday17's Blog 浅谈 git fetch 的工作方式 | Yesterday17's Blog 『ソーサレス*アライヴ! ~the World's End Fallen Star~』通关感想" | Yesterday17's Blog Rust std::fmt 格式语法简述 | Yesterday17's Blog 日亚修改居住国的解决方案 | Yesterday17's Blog [Windows/Linux] GC553 的 Switch 完美采集之路 | Yesterday17's Blog 【翻译】Subtyping and Variance / 子类型与变型 | Yesterday17's Blog Berd's Red Envelope 2021 WriteUp | Yesterday17's Blog 【中英对照】ALSA 音频 API 使用教程/A Tutorial on Using the ALSA Audio API | Yesterday17's Blog 从 cue_scanner.l 看 CUE Sheet 的词法单元 | Yesterday17's Blog Postman 历史记录导出的解决方案 | Yesterday17's Blog 《恋爱绮谭 不存在的夏天》通关感想 | Yesterday17's Blog [微机实验/TD-PITE] 微机接口综合实验 | Yesterday17's Blog [微机实验/TD-PITE] 键盘扫描及数码管显示实验 | Yesterday17's Blog [微机实验/TD-PITE] 数码管显示实验 | Yesterday17's Blog Airsonic Advanced+Google Drive+Caddy 部署纪实 | Yesterday17's Blog X-NUCA 2020 - hellowasm 题解 | Yesterday17's Blog [微机实验/TD-PITE] 8251 串行接口实验 | Yesterday17's Blog Node.js child_process.fork 与 env 污染 RCE | Yesterday17's Blog EP.01 「夜の向日葵」 | Yesterday17's Blog [微机实验/TD-PITE] 8254 定时/计数器实验+选做实验 | Yesterday17's Blog [JLU CTF/2020] babywasm WriteUp | Yesterday17's Blog PHP 反序列化与经典利用 | Yesterday17's Blog WebAssembly 逆向简述 | Yesterday17's Blog 『彼女、お借りします』一期完结点评 | Yesterday17's Blog [微机实验/TD-PITE] D/A 转换实验+选做实验 | Yesterday17's Blog [微机实验/TD-PITE] A/D 转换实验+选做实验 | Yesterday17's Blog 开源项目申请 JetBrains Open Source License 简单流程 | Yesterday17's Blog 微软拼音与 JetBrains 搜索快捷键冲突的解决方案 | Yesterday17's Blog [微机实验/TD-PITE] 8259 中断优先级实验+选做实验 | Yesterday17's Blog IFTTT 测试(续) | Yesterday17 IFTTT 测试 | Yesterday17's Blog [微机实验/TD-PITE] 存储器扩展实验+选做实验 | Yesterday17's Blog 新版 GCC 针对 -fdump-translation-unit 的替代方案 | Yesterday17's Blog 一次 HSTS 策略配置的排错之旅 | Yesterday17's Blog YukiNative 踩坑记——Windows 的消息队列 | Yesterday17's Blog 我是我自己——论获取 HTTPS 证书时的验证步骤 | Yesterday17's Blog 【设计文档】对 PUG 的大规模设计修订(1.1) | Yesterday17's Blog GS65 折腾记(2)加装固态,分区,Grub2 引导 Manjaro LiveCD | Yesterday17's Blog 「さくら、もゆ。」的空白字体列表——一次逆向问题定位过程实录 | Yesterday17's Blog GSuite 探索篇(1)使用 Service Account 向 Google Drive 传输文件 | Yesterday17's Blog 『サクラノ詩 -櫻の森の上を舞う-』通关感想 | Yesterday17's Blog 《ATRI -My Dear Moments-》通关感想 | Yesterday17's Blog [工具][VSCode 扩展] AegiKit——方便 Aegisub 使用的工具箱 | Yesterday17's Blog 贝塞尔曲线、字体矢量化与曲线运算 | Yesterday17's Blog NAT 类型初探 | Yesterday17's Blog
Project Anni 之旅(2)ValueAfterTable——toml-rs的实现与限制 | Yesterday17's Blog
Yesterday17 · 2021-10-20 · via Yesterday17's Blog

ToC

  • 前言
  • 了解 TOML
  • 问题所在
  • 如何解决?

前言

大家好,好久不见,我是某昨。

最近将 Anni 的元数据仓库标准更新到 1.1 时出现了问题。在 1.1 的标准中,date 字段可以通过指定 yearmonthday 表示相对模糊的专辑发售日期:

[album]

date = { year = 2021, month = 10 }

对反序列化而言,一切都没有问题,但在序列化的时候,问题出现了:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ValueAfterTable', anni-repo/src/album.rs:52:32

stack backtrace:

0: rust_begin_unwind

at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/std/src/panicking.rs:515:5

1: core::panicking::panic_fmt

at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/panicking.rs:92:14

2: core::result::unwrap_failed

at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/result.rs:1355:5

3: anni_repo::manager::RepositoryManager::add_album

4: <anni::subcommands::repo::RepoAction as anni_clap_handler::traits::Handler>::execute

5: anni_clap_handler::traits::Handler::execute

6: anni_clap_handler::traits::Handler::run

7: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll

8: tokio::runtime::enter::Enter::block_on

9: tokio::runtime::Runtime::block_on

10: anni::main

note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

可以看到,抛出的 ErrorValueAfterTable。以 ValueAfterTable 为关键词搜索,在 GitHub 上有一大堆:

那这个问题是怎么出现,又是为什么会出现呢?本期走近科学将会……

了解 TOML

想要知道 toml-rs 的问题所在,就必须了解 TOML 本身。TOML 是一门非常适合作为配置文件的语言,相比 JSON 等序列化方案的可读性要高上不少。TOML 中最复杂的结构就是 Table 了,类似 JSON 中的 Object,用于描述嵌套的层级关系。TOMLTable 有好几种写法:

# 最基本的写法

# { "table1": { "key": "value" } }

[table1]

key = "value"

# 简单的嵌套

# { "table1": { "table2": { "key": "value" } } }

[table1.table2]

key = "value"

# 在字段名上嵌套

table1.key = "value"

# 内联

table1 = { key = "value" }

问题所在

上述的这四种表示方法都可以用来表示 Table,这赋予了 TOML 更高的可读性,但同时也限制了 toml-rs 的发挥。试想以下场景:

[table]

one = 1

inner = { key = 2 }

another = 3

反序列化之后,我们得到了对应的 struct,但隐含在 inner 中的信息却丢失了——inner 应该是一个内联 Table。在序列化时,我们不知道 inner 是内联 Table 这一关键信息,尝试将所有的 Table 都序列化成:

[table]

one = 1

[table.inner]

key = 2

another = 3 #???

不难发现,another = 3 现在被分在了 [table.inner] 下,而非 [table] 下,实际的结构完全错了。这也是 toml 选择限制 table 字段必须在最后序列化的原因所在了。

如何解决?

解决这个问题有三种方案:

  1. 调整字段的顺序,让嵌套的 Table 在最后序列化
  2. 实现支持内联 Table
  3. 抛弃 serde

第一种方案是最简单的,但在这意味着字段的顺序需要改变;第二种解决方案最彻底,但需要 toml-rs 对现有架构做一定变动;第三种方案最激进,但抛弃 serde 意味着对原文件结构有着更深的了解,并且能够支持一些类似运行时的特性。

而对于 Anni——我选择把 struct 换成 string(逃