mirror of
https://github.com/neondatabase/neon.git
synced 2026-05-31 12:00:42 +00:00
Migrates the remaining crates to edition 2024. We like to stay on the latest edition if possible. There is no functional changes, however some code changes had to be done to accommodate the edition's breaking changes. Like the previous migration PRs, this is comprised of three commits: * the first does the edition update and makes `cargo check`/`cargo clippy` pass. we had to update bindgen to make its output [satisfy the requirements of edition 2024](https://doc.rust-lang.org/edition-guide/rust-2024/unsafe-extern.html) * the second commit does a `cargo fmt` for the new style edition. * the third commit reorders imports as a one-off change. As before, it is entirely optional. Part of #10918
88 lines
2.3 KiB
Rust
88 lines
2.3 KiB
Rust
//! A serde::Deserialize type for percentages.
|
|
//!
|
|
//! See [`Percent`] for details.
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
/// If the value is not an integer between 0 and 100,
|
|
/// deserialization fails with a descriptive error.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
|
#[serde(transparent)]
|
|
pub struct Percent(#[serde(deserialize_with = "deserialize_pct_0_to_100")] u8);
|
|
|
|
impl Percent {
|
|
pub const fn new(pct: u8) -> Option<Self> {
|
|
if pct <= 100 { Some(Percent(pct)) } else { None }
|
|
}
|
|
|
|
pub fn get(&self) -> u8 {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
fn deserialize_pct_0_to_100<'de, D>(deserializer: D) -> Result<u8, D::Error>
|
|
where
|
|
D: serde::de::Deserializer<'de>,
|
|
{
|
|
let v: u8 = serde::de::Deserialize::deserialize(deserializer)?;
|
|
if v > 100 {
|
|
return Err(serde::de::Error::custom(
|
|
"must be an integer between 0 and 100",
|
|
));
|
|
}
|
|
Ok(v)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::Percent;
|
|
|
|
#[derive(serde::Deserialize, serde::Serialize, Debug, PartialEq, Eq)]
|
|
struct Foo {
|
|
bar: Percent,
|
|
}
|
|
|
|
#[test]
|
|
fn basics() {
|
|
let input = r#"{ "bar": 50 }"#;
|
|
let foo: Foo = serde_json::from_str(input).unwrap();
|
|
assert_eq!(foo.bar.get(), 50);
|
|
}
|
|
#[test]
|
|
fn null_handling() {
|
|
let input = r#"{ "bar": null }"#;
|
|
let res: Result<Foo, _> = serde_json::from_str(input);
|
|
assert!(res.is_err());
|
|
}
|
|
#[test]
|
|
fn zero() {
|
|
let input = r#"{ "bar": 0 }"#;
|
|
let foo: Foo = serde_json::from_str(input).unwrap();
|
|
assert_eq!(foo.bar.get(), 0);
|
|
}
|
|
#[test]
|
|
fn out_of_range_above() {
|
|
let input = r#"{ "bar": 101 }"#;
|
|
let res: Result<Foo, _> = serde_json::from_str(input);
|
|
assert!(res.is_err());
|
|
}
|
|
#[test]
|
|
fn out_of_range_below() {
|
|
let input = r#"{ "bar": -1 }"#;
|
|
let res: Result<Foo, _> = serde_json::from_str(input);
|
|
assert!(res.is_err());
|
|
}
|
|
#[test]
|
|
fn float() {
|
|
let input = r#"{ "bar": 50.5 }"#;
|
|
let res: Result<Foo, _> = serde_json::from_str(input);
|
|
assert!(res.is_err());
|
|
}
|
|
#[test]
|
|
fn string() {
|
|
let input = r#"{ "bar": "50 %" }"#;
|
|
let res: Result<Foo, _> = serde_json::from_str(input);
|
|
assert!(res.is_err());
|
|
}
|
|
}
|