-
Notifications
You must be signed in to change notification settings - Fork 0
Number Model
github-actions[bot] edited this page Aug 12, 2026
·
2 revisions
JSON 数字的保真是 NextJson 的一个显式设计目标。Number 不是裸 f64,而是
一个无损枚举。
pub enum Number {
I64(i64), // 有符号 64 位
U64(u64), // 无符号 64 位(所有非负整数都用它)
I128(i128), // 超出 i64 范围的有符号 128 位
U128(u128), // 超出 u64 范围的无符号 128 位
F64(f64), // 64 位浮点(含 -0.0 与极端值)
}Number::U64(v) 是所有非负整数的规范形式。原因是一个曾被测试抓到的相等性
撕裂:
let a: Number = 1i32.into(); // 旧实现 → Number::I64(1)
let b: Number = "1".parse()?; // 解析 → Number::U64(1)
assert_eq!(a, b); // 旧实现:不等!(撕裂)统一后 I64 只存负数,解析得到的正数与 From 构造的正数恒等。
- 解析时手写整数词法 + 溢出检测:超
u128的整数 →NumberOutOfRange错误; - 因此
Value/ 类型化解码都不会出现"大整数被悄悄转成浮点丢精度"。
f64 整数(如 64.0)在 JSON 里序列化为 64.0 而非 64——保留浮点语义,
反序列化回 f64 时不会与整数类型混淆。
n.as_i64() // 尽力转 i64(浮点截断)
n.as_u64() // 尽力转 u64
n.as_i128() // 精确:仅当值是整数且范围内
n.as_u128() // 精确:仅当值是整数且范围内
n.as_f64() // 转 f64(可能丢精度,从不失败)-
as_i128/as_u128对F64只在"有限且% 1.0 == 0.0"时成功(no_std下f64::fract()不可用,故用% 1.0判断整性); - 边界检查避免了
u64::MAX as f64这类浮点舍入导致的越界误报/漏报。
-
FormatEncoder提供write_number(&Number)(保留种类)与宽度方法write_i8..i128/write_u8..u128/write_f32/f64; - 默认宽度方法加宽到
i64/u64;二进制格式覆写为原生宽度写出(线上保留宽度, 如 postcard 的定宽整数); - 解码侧
Number是自描述格式的中间载体,非自描述格式(postcard)通过宽度读取 直接还原。
- 没有任意精度小数/大整数(
u128封顶)——这是文档明示的能力边界,超出u128的整数报错而不是用f64静默降级; - 这比 serde_json 默认的
arbitrary_precision(可选 feature)保守;serde 生态 的bigdecimal/rust_decimal走的是另一条路线。
- 线上表达:Core Contracts / Multi-Format Engine
- 安全:检查式算术见 Safety Model