Initial Dever 0.0.1

This commit is contained in:
Codex committed 2026-11-03 03:32:07 +00:00
commit 81233d098c
1479 files changed
+163782

No files matched your search

+120
View File
@@ -0,0 +1,120 @@
//! PostgreSQL 文档规定的 NUMERIC 分组字节;预期值独立于编码实现。
use super::*;
#[test]
fn numeric_encoding_matches_protocol_words() {
for (text, precision, scale, words) in [
("0", 5, 2, vec![0, 0, 0, 2]),
("-12.34", 5, 2, vec![2, 0, 0x4000, 2, 12, 3400]),
("0.00001", 5, 5, vec![1, -2, 0, 5, 1000]),
("10000", 5, 0, vec![1, 1, 0, 0, 1]),
("12345678.9012", 12, 4, vec![3, 1, 0, 4, 1234, 5678, 9012]),
(
"9999999999999999999999999999999999",
34,
0,
vec![
9, 8, 0, 0, 99, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999,
],
),
] {
let value = Decimal::parse(text).unwrap();
let expected = words
.into_iter()
.flat_map(i16::to_be_bytes)
.collect::<Vec<_>>();
let mut output = BytesMut::new();
encode(value, precision, scale, &mut output).unwrap();
assert_eq!(output.as_ref(), expected, "{text}");
assert_eq!(decode(&output).unwrap(), value);
}
}
#[test]
fn native_numeric_preserves_decimal_extremes_and_zero() {
for text in [
"0",
"-0",
"0E-6176",
"1E-6176",
"1E6111",
"-123.456",
"1.0000",
"9.999999999999999999999999999999999E6144",
] {
let value = Decimal::parse(text).unwrap();
let mut output = BytesMut::new();
encode_native(value, &mut output);
assert_eq!(decode(&output).unwrap(), value, "{text}");
}
for (text, precision, scale) in [("1.001", 5, 2), ("1000", 5, 2), ("1", 35, 0), ("1", 2, 3)] {
assert!(
encode(
Decimal::parse(text).unwrap(),
precision,
scale,
&mut BytesMut::new()
)
.is_err()
);
}
}
#[test]
fn numeric_decode_rejects_malformed_or_inexact_values() {
for words in [
vec![1, 0, 0, 0],
vec![-1, 0, 0, 0],
vec![1, 0, 0, 0, 10000],
vec![0, 0, 0xc000_u16 as i16, 0],
vec![0, 0, 0, -1],
vec![1, 1537, 0, 0, 1],
vec![1, -1545, 0, 0, 1],
vec![
9, 8, 0, 0, 999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999,
],
] {
let bytes = words
.into_iter()
.flat_map(i16::to_be_bytes)
.collect::<Vec<_>>();
assert!(decode(&bytes).is_err(), "{bytes:?}");
}
}
#[test]
#[ignore = "explicit release performance probe"]
fn numeric_decode_cost() {
use std::{hint::black_box, time::Instant};
println!("\ncase,sample,iterations,elapsed_ns,checksum");
for (name, text) in [
("zero", "0"),
("fraction", "-1234567890123456789012345.123456789"),
("exponent", "9.999999999999999999999999999999999E6144"),
] {
let value = Decimal::parse(text).unwrap();
let mut encoded = BytesMut::new();
encode_native(value, &mut encoded);
let expected = decode(&encoded).unwrap();
assert_eq!(expected, value);
for _ in 0..100 {
black_box(decode(&encoded).unwrap());
}
for sample in 0..15 {
let started = Instant::now();
let mut decoded = Decimal::ZERO;
for _ in 0..100_000 {
decoded = black_box(decode(black_box(&encoded)).unwrap());
}
let elapsed = started.elapsed().as_nanos();
assert_eq!(decoded, expected);
let checksum: u64 = decoded
.to_be_bytes()
.iter()
.map(|byte| u64::from(*byte))
.sum();
println!("numeric_decode_{name},{sample},100000,{elapsed},{checksum}");
}
}
}