* [pbs-devel] [PATCH proxmox{, -api-types, -ve-rs} 0/6] Move perl deserializers from proxmox-login to proxmox-serde
@ 2025-05-13 10:14 Stefan Hanreich
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox 1/3] serde: add parsing helpers for perl Stefan Hanreich
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Stefan Hanreich @ 2025-05-13 10:14 UTC (permalink / raw)
To: pbs-devel
There are other places where we need to deal with data coming from Perl as well,
so move those helpers to a more appropriate place, where they can be re-used
across multiple crates, without having to add a dependency to proxmox-login.
proxmox-serde needs a bump, all other crates from this series depend on the
changes there.
proxmox:
Stefan Hanreich (3):
serde: add parsing helpers for perl
login: move parse module to proxmox-serde
client: move to proxmox_serde perl helpers
proxmox-client/Cargo.toml | 2 ++
proxmox-client/src/lib.rs | 4 ++--
proxmox-login/Cargo.toml | 1 +
proxmox-login/src/api.rs | 2 +-
proxmox-login/src/lib.rs | 2 --
proxmox-serde/Cargo.toml | 3 +++
proxmox-serde/src/lib.rs | 3 +++
proxmox-login/src/parse.rs => proxmox-serde/src/perl.rs | 0
8 files changed, 12 insertions(+), 5 deletions(-)
rename proxmox-login/src/parse.rs => proxmox-serde/src/perl.rs (100%)
proxmox-api-types:
Stefan Hanreich (2):
generator: use proxmox_serde for perl helpers
regenerate
Cargo.toml | 2 +-
pve-api-types/Cargo.toml | 2 +-
pve-api-types/generator-lib/Schema2Rust.pm | 26 +-
pve-api-types/src/generated/types.rs | 798 ++++++++++-----------
4 files changed, 414 insertions(+), 414 deletions(-)
proxmox-ve-rs:
Stefan Hanreich (1):
config: use proxmox_serde perl helpers
proxmox-ve-config/Cargo.toml | 1 +
proxmox-ve-config/src/firewall/bridge.rs | 3 +-
proxmox-ve-config/src/firewall/cluster.rs | 6 +-
proxmox-ve-config/src/firewall/guest.rs | 14 ++--
proxmox-ve-config/src/firewall/host.rs | 26 ++++----
proxmox-ve-config/src/firewall/parse.rs | 80 -----------------------
6 files changed, 24 insertions(+), 106 deletions(-)
Summary over all repositories:
18 files changed, 450 insertions(+), 525 deletions(-)
--
Generated by git-murpp 0.8.0
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pbs-devel] [PATCH proxmox 1/3] serde: add parsing helpers for perl
2025-05-13 10:14 [pbs-devel] [PATCH proxmox{, -api-types, -ve-rs} 0/6] Move perl deserializers from proxmox-login to proxmox-serde Stefan Hanreich
@ 2025-05-13 10:14 ` Stefan Hanreich
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox 2/3] login: move parse module to proxmox-serde Stefan Hanreich
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Stefan Hanreich @ 2025-05-13 10:14 UTC (permalink / raw)
To: pbs-devel
Those have been moved from the proxmox-login crate. This crate seems
like a more natural place for hosting helpers to parse data coming
from perl via serde.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
proxmox-serde/Cargo.toml | 3 +
proxmox-serde/src/lib.rs | 3 +
proxmox-serde/src/perl.rs | 373 ++++++++++++++++++++++++++++++++++++++
3 files changed, 379 insertions(+)
create mode 100644 proxmox-serde/src/perl.rs
diff --git a/proxmox-serde/Cargo.toml b/proxmox-serde/Cargo.toml
index aa77099a..b1edb60d 100644
--- a/proxmox-serde/Cargo.toml
+++ b/proxmox-serde/Cargo.toml
@@ -20,3 +20,6 @@ proxmox-time.workspace = true
[dev-dependencies]
serde_json.workspace = true
+
+[features]
+perl = []
diff --git a/proxmox-serde/src/lib.rs b/proxmox-serde/src/lib.rs
index c1628349..8a3d8794 100644
--- a/proxmox-serde/src/lib.rs
+++ b/proxmox-serde/src/lib.rs
@@ -8,6 +8,9 @@ pub mod serde_macros;
#[cfg(feature = "serde_json")]
pub mod json;
+#[cfg(feature = "perl")]
+pub mod perl;
+
/// Serialize Unix epoch (i64) as RFC3339.
///
/// Usage example:
diff --git a/proxmox-serde/src/perl.rs b/proxmox-serde/src/perl.rs
new file mode 100644
index 00000000..8efa86c9
--- /dev/null
+++ b/proxmox-serde/src/perl.rs
@@ -0,0 +1,373 @@
+//! Some parsing helpers for the PVE API, mainly to deal with perl's untypedness.
+
+use std::fmt;
+
+use serde::de::Unexpected;
+
+// Boolean:
+
+pub trait FromBool: Sized + Default {
+ fn from_bool(value: bool) -> Self;
+}
+
+impl FromBool for bool {
+ fn from_bool(value: bool) -> Self {
+ value
+ }
+}
+
+impl FromBool for Option<bool> {
+ fn from_bool(value: bool) -> Self {
+ Some(value)
+ }
+}
+
+pub fn deserialize_bool<'de, D, T>(deserializer: D) -> Result<T, D::Error>
+where
+ D: serde::Deserializer<'de>,
+ T: FromBool,
+{
+ deserializer.deserialize_any(BoolVisitor::<T>::new())
+}
+
+struct BoolVisitor<T>(std::marker::PhantomData<T>);
+
+impl<T> BoolVisitor<T> {
+ fn new() -> Self {
+ Self(std::marker::PhantomData)
+ }
+}
+
+impl<'de, T: FromBool> serde::de::DeserializeSeed<'de> for BoolVisitor<T> {
+ type Value = T;
+
+ fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ deserialize_bool(deserializer)
+ }
+}
+
+impl<'de, T> serde::de::Visitor<'de> for BoolVisitor<T>
+where
+ T: FromBool,
+{
+ type Value = T;
+
+ fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("a boolean-ish...")
+ }
+
+ fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ deserializer.deserialize_any(self)
+ }
+
+ fn visit_none<E>(self) -> Result<Self::Value, E> {
+ Ok(Default::default())
+ }
+
+ fn visit_bool<E: serde::de::Error>(self, value: bool) -> Result<Self::Value, E> {
+ Ok(Self::Value::from_bool(value))
+ }
+
+ fn visit_i128<E: serde::de::Error>(self, value: i128) -> Result<Self::Value, E> {
+ Ok(Self::Value::from_bool(value != 0))
+ }
+
+ fn visit_i64<E: serde::de::Error>(self, value: i64) -> Result<Self::Value, E> {
+ Ok(Self::Value::from_bool(value != 0))
+ }
+
+ fn visit_u64<E: serde::de::Error>(self, value: u64) -> Result<Self::Value, E> {
+ Ok(Self::Value::from_bool(value != 0))
+ }
+
+ fn visit_u128<E: serde::de::Error>(self, value: u128) -> Result<Self::Value, E> {
+ Ok(Self::Value::from_bool(value != 0))
+ }
+
+ fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
+ let value = if value.eq_ignore_ascii_case("true")
+ || value.eq_ignore_ascii_case("yes")
+ || value.eq_ignore_ascii_case("on")
+ || value == "1"
+ {
+ true
+ } else if value.eq_ignore_ascii_case("false")
+ || value.eq_ignore_ascii_case("no")
+ || value.eq_ignore_ascii_case("off")
+ || value == "0"
+ {
+ false
+ } else {
+ return Err(E::invalid_value(
+ serde::de::Unexpected::Str(value),
+ &"a boolean-like value",
+ ));
+ };
+ Ok(Self::Value::from_bool(value))
+ }
+}
+
+// integer helpers:
+
+macro_rules! integer_helper {
+ ($ty:ident, $deserialize_name:ident, $trait: ident, $from_name:ident, $visitor:ident) => {
+ #[doc(hidden)]
+ pub trait $trait: Sized + Default {
+ fn $from_name(value: $ty) -> Self;
+ }
+
+ impl $trait for $ty {
+ fn $from_name(value: $ty) -> Self {
+ value
+ }
+ }
+
+ impl $trait for Option<$ty> {
+ fn $from_name(value: $ty) -> Self {
+ Some(value)
+ }
+ }
+
+ pub fn $deserialize_name<'de, D, T>(deserializer: D) -> Result<T, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ T: $trait,
+ {
+ deserializer.deserialize_any($visitor::<T>::new())
+ }
+
+ struct $visitor<T>(std::marker::PhantomData<T>);
+
+ impl<T> $visitor<T> {
+ fn new() -> Self {
+ Self(std::marker::PhantomData)
+ }
+ }
+
+ impl<'de, T: $trait> serde::de::DeserializeSeed<'de> for $visitor<T> {
+ type Value = T;
+
+ fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ $deserialize_name(deserializer)
+ }
+ }
+
+ impl<'de, T> serde::de::Visitor<'de> for $visitor<T>
+ where
+ T: $trait,
+ {
+ type Value = T;
+
+ fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str(concat!("a ", stringify!($ty), "-ish..."))
+ }
+
+ fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ deserializer.deserialize_any(self)
+ }
+
+ fn visit_none<E>(self) -> Result<Self::Value, E> {
+ Ok(Default::default())
+ }
+
+ fn visit_i128<E: serde::de::Error>(self, value: i128) -> Result<Self::Value, E> {
+ $ty::try_from(value)
+ .map_err(|_| E::invalid_value(Unexpected::Other("i128"), &self))
+ .map(Self::Value::$from_name)
+ }
+
+ fn visit_i64<E: serde::de::Error>(self, value: i64) -> Result<Self::Value, E> {
+ $ty::try_from(value)
+ .map_err(|_| E::invalid_value(Unexpected::Signed(value), &self))
+ .map(Self::Value::$from_name)
+ }
+
+ fn visit_u64<E: serde::de::Error>(self, value: u64) -> Result<Self::Value, E> {
+ $ty::try_from(value)
+ .map_err(|_| E::invalid_value(Unexpected::Unsigned(value), &self))
+ .map(Self::Value::$from_name)
+ }
+
+ fn visit_u128<E: serde::de::Error>(self, value: u128) -> Result<Self::Value, E> {
+ $ty::try_from(value)
+ .map_err(|_| E::invalid_value(Unexpected::Other("u128"), &self))
+ .map(Self::Value::$from_name)
+ }
+
+ fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
+ let value = value
+ .parse()
+ .map_err(|_| E::invalid_value(Unexpected::Str(value), &self))?;
+ self.visit_i64(value)
+ }
+ }
+ };
+}
+
+integer_helper!(
+ isize,
+ deserialize_isize,
+ FromIsize,
+ from_isize,
+ IsizeVisitor
+);
+
+integer_helper!(
+ usize,
+ deserialize_usize,
+ FromUsize,
+ from_usize,
+ UsizeVisitor
+);
+
+integer_helper!(u8, deserialize_u8, FromU8, from_u8, U8Visitor);
+integer_helper!(u16, deserialize_u16, FromU16, from_u16, U16Visitor);
+integer_helper!(u32, deserialize_u32, FromU32, from_u32, U32Visitor);
+integer_helper!(u64, deserialize_u64, FromU64, from_u64, U64Visitor);
+integer_helper!(i8, deserialize_i8, FromI8, from_i8, I8Visitor);
+integer_helper!(i16, deserialize_i16, FromI16, from_i16, I16Visitor);
+integer_helper!(i32, deserialize_i32, FromI32, from_i32, I32Visitor);
+integer_helper!(i64, deserialize_i64, FromI64, from_i64, I64Visitor);
+
+// float helpers:
+
+macro_rules! float_helper {
+ ($ty:ident, $deserialize_name:ident, $visitor:ident) => {
+ pub fn $deserialize_name<'de, D, T>(deserializer: D) -> Result<T, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ T: FromF64,
+ {
+ deserializer.deserialize_any($visitor::<T>::new())
+ }
+
+ struct $visitor<T>(std::marker::PhantomData<T>);
+
+ impl<T> $visitor<T> {
+ fn new() -> Self {
+ Self(std::marker::PhantomData)
+ }
+ }
+
+ impl<'de, T: FromF64> serde::de::DeserializeSeed<'de> for $visitor<T> {
+ type Value = T;
+
+ fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ $deserialize_name(deserializer)
+ }
+ }
+
+ impl<'de, T> serde::de::Visitor<'de> for $visitor<T>
+ where
+ T: FromF64,
+ {
+ type Value = T;
+
+ fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str(concat!("a ", stringify!($ty), "-ish..."))
+ }
+
+ fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ deserializer.deserialize_any(self)
+ }
+
+ fn visit_none<E>(self) -> Result<Self::Value, E> {
+ Ok(Default::default())
+ }
+
+ fn visit_f64<E: serde::de::Error>(self, value: f64) -> Result<Self::Value, E> {
+ Ok(T::from_f64(value))
+ }
+
+ fn visit_i128<E: serde::de::Error>(self, value: i128) -> Result<Self::Value, E> {
+ let conv = value as f64;
+ if conv as i128 == value {
+ Ok(T::from_f64(conv))
+ } else {
+ Err(E::invalid_value(Unexpected::Other("i128"), &self))
+ }
+ }
+
+ fn visit_i64<E: serde::de::Error>(self, value: i64) -> Result<Self::Value, E> {
+ let conv = value as f64;
+ if conv as i64 == value {
+ Ok(T::from_f64(conv))
+ } else {
+ Err(E::invalid_value(Unexpected::Signed(value), &self))
+ }
+ }
+
+ fn visit_u128<E: serde::de::Error>(self, value: u128) -> Result<Self::Value, E> {
+ let conv = value as f64;
+ if conv as u128 == value {
+ Ok(T::from_f64(conv))
+ } else {
+ Err(E::invalid_value(Unexpected::Other("u128"), &self))
+ }
+ }
+
+ fn visit_u64<E: serde::de::Error>(self, value: u64) -> Result<Self::Value, E> {
+ let conv = value as f64;
+ if conv as u64 == value {
+ Ok(T::from_f64(conv))
+ } else {
+ Err(E::invalid_value(Unexpected::Unsigned(value), &self))
+ }
+ }
+
+ fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
+ let value = value
+ .parse()
+ .map_err(|_| E::invalid_value(Unexpected::Str(value), &self))?;
+ self.visit_f64(value)
+ }
+ }
+ };
+}
+
+#[doc(hidden)]
+pub trait FromF64: Sized + Default {
+ fn from_f64(value: f64) -> Self;
+}
+
+impl FromF64 for f32 {
+ #[inline(always)]
+ fn from_f64(f: f64) -> f32 {
+ f as f32
+ }
+}
+
+impl FromF64 for f64 {
+ #[inline(always)]
+ fn from_f64(f: f64) -> f64 {
+ f
+ }
+}
+
+impl<T: FromF64> FromF64 for Option<T> {
+ #[inline(always)]
+ fn from_f64(f: f64) -> Option<T> {
+ Some(T::from_f64(f))
+ }
+}
+
+float_helper!(f32, deserialize_f32, F32Visitor);
+float_helper!(f64, deserialize_f64, F64Visitor);
--
2.39.5
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pbs-devel] [PATCH proxmox 2/3] login: move parse module to proxmox-serde
2025-05-13 10:14 [pbs-devel] [PATCH proxmox{, -api-types, -ve-rs} 0/6] Move perl deserializers from proxmox-login to proxmox-serde Stefan Hanreich
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox 1/3] serde: add parsing helpers for perl Stefan Hanreich
@ 2025-05-13 10:14 ` Stefan Hanreich
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox 3/3] client: move to proxmox_serde perl helpers Stefan Hanreich
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Stefan Hanreich @ 2025-05-13 10:14 UTC (permalink / raw)
To: pbs-devel
Remove the parse module, that has been moved to proxmox-serde. Fix all
usages of the parse module in the process and add the new dependency.
No functional changes intended.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
proxmox-login/Cargo.toml | 1 +
proxmox-login/src/api.rs | 2 +-
proxmox-login/src/lib.rs | 2 -
proxmox-login/src/parse.rs | 373 -------------------------------------
4 files changed, 2 insertions(+), 376 deletions(-)
delete mode 100644 proxmox-login/src/parse.rs
diff --git a/proxmox-login/Cargo.toml b/proxmox-login/Cargo.toml
index 50dfe2c8..2dc28d52 100644
--- a/proxmox-login/Cargo.toml
+++ b/proxmox-login/Cargo.toml
@@ -16,6 +16,7 @@ base64.workspace = true
percent-encoding.workspace = true
serde = { workspace = true, features = [ "derive" ] }
serde_json.workspace = true
+proxmox-serde = { workspace = true, features = [ "perl" ] }
# For webauthn types
webauthn-rs = { workspace = true, optional = true }
diff --git a/proxmox-login/src/api.rs b/proxmox-login/src/api.rs
index b7107312..6023485c 100644
--- a/proxmox-login/src/api.rs
+++ b/proxmox-login/src/api.rs
@@ -11,7 +11,7 @@ pub struct CreateTicket {
/// With webauthn the format of half-authenticated tickts changed. New
/// clients should pass 1 here and not worry about the old format. The old
/// format is deprecated and will be retired with PVE-8.0
- #[serde(deserialize_with = "crate::parse::deserialize_bool")]
+ #[serde(deserialize_with = "proxmox_serde::perl::deserialize_bool")]
#[serde(default, skip_serializing_if = "Option::is_none")]
#[serde(rename = "new-format")]
pub new_format: Option<bool>,
diff --git a/proxmox-login/src/lib.rs b/proxmox-login/src/lib.rs
index e97ece7b..4482f2e4 100644
--- a/proxmox-login/src/lib.rs
+++ b/proxmox-login/src/lib.rs
@@ -5,8 +5,6 @@
use serde::{Deserialize, Serialize};
-pub mod parse;
-
pub mod api;
pub mod error;
pub mod tfa;
diff --git a/proxmox-login/src/parse.rs b/proxmox-login/src/parse.rs
deleted file mode 100644
index 8efa86c9..00000000
--- a/proxmox-login/src/parse.rs
+++ /dev/null
@@ -1,373 +0,0 @@
-//! Some parsing helpers for the PVE API, mainly to deal with perl's untypedness.
-
-use std::fmt;
-
-use serde::de::Unexpected;
-
-// Boolean:
-
-pub trait FromBool: Sized + Default {
- fn from_bool(value: bool) -> Self;
-}
-
-impl FromBool for bool {
- fn from_bool(value: bool) -> Self {
- value
- }
-}
-
-impl FromBool for Option<bool> {
- fn from_bool(value: bool) -> Self {
- Some(value)
- }
-}
-
-pub fn deserialize_bool<'de, D, T>(deserializer: D) -> Result<T, D::Error>
-where
- D: serde::Deserializer<'de>,
- T: FromBool,
-{
- deserializer.deserialize_any(BoolVisitor::<T>::new())
-}
-
-struct BoolVisitor<T>(std::marker::PhantomData<T>);
-
-impl<T> BoolVisitor<T> {
- fn new() -> Self {
- Self(std::marker::PhantomData)
- }
-}
-
-impl<'de, T: FromBool> serde::de::DeserializeSeed<'de> for BoolVisitor<T> {
- type Value = T;
-
- fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- deserialize_bool(deserializer)
- }
-}
-
-impl<'de, T> serde::de::Visitor<'de> for BoolVisitor<T>
-where
- T: FromBool,
-{
- type Value = T;
-
- fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.write_str("a boolean-ish...")
- }
-
- fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- deserializer.deserialize_any(self)
- }
-
- fn visit_none<E>(self) -> Result<Self::Value, E> {
- Ok(Default::default())
- }
-
- fn visit_bool<E: serde::de::Error>(self, value: bool) -> Result<Self::Value, E> {
- Ok(Self::Value::from_bool(value))
- }
-
- fn visit_i128<E: serde::de::Error>(self, value: i128) -> Result<Self::Value, E> {
- Ok(Self::Value::from_bool(value != 0))
- }
-
- fn visit_i64<E: serde::de::Error>(self, value: i64) -> Result<Self::Value, E> {
- Ok(Self::Value::from_bool(value != 0))
- }
-
- fn visit_u64<E: serde::de::Error>(self, value: u64) -> Result<Self::Value, E> {
- Ok(Self::Value::from_bool(value != 0))
- }
-
- fn visit_u128<E: serde::de::Error>(self, value: u128) -> Result<Self::Value, E> {
- Ok(Self::Value::from_bool(value != 0))
- }
-
- fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
- let value = if value.eq_ignore_ascii_case("true")
- || value.eq_ignore_ascii_case("yes")
- || value.eq_ignore_ascii_case("on")
- || value == "1"
- {
- true
- } else if value.eq_ignore_ascii_case("false")
- || value.eq_ignore_ascii_case("no")
- || value.eq_ignore_ascii_case("off")
- || value == "0"
- {
- false
- } else {
- return Err(E::invalid_value(
- serde::de::Unexpected::Str(value),
- &"a boolean-like value",
- ));
- };
- Ok(Self::Value::from_bool(value))
- }
-}
-
-// integer helpers:
-
-macro_rules! integer_helper {
- ($ty:ident, $deserialize_name:ident, $trait: ident, $from_name:ident, $visitor:ident) => {
- #[doc(hidden)]
- pub trait $trait: Sized + Default {
- fn $from_name(value: $ty) -> Self;
- }
-
- impl $trait for $ty {
- fn $from_name(value: $ty) -> Self {
- value
- }
- }
-
- impl $trait for Option<$ty> {
- fn $from_name(value: $ty) -> Self {
- Some(value)
- }
- }
-
- pub fn $deserialize_name<'de, D, T>(deserializer: D) -> Result<T, D::Error>
- where
- D: serde::Deserializer<'de>,
- T: $trait,
- {
- deserializer.deserialize_any($visitor::<T>::new())
- }
-
- struct $visitor<T>(std::marker::PhantomData<T>);
-
- impl<T> $visitor<T> {
- fn new() -> Self {
- Self(std::marker::PhantomData)
- }
- }
-
- impl<'de, T: $trait> serde::de::DeserializeSeed<'de> for $visitor<T> {
- type Value = T;
-
- fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- $deserialize_name(deserializer)
- }
- }
-
- impl<'de, T> serde::de::Visitor<'de> for $visitor<T>
- where
- T: $trait,
- {
- type Value = T;
-
- fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.write_str(concat!("a ", stringify!($ty), "-ish..."))
- }
-
- fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- deserializer.deserialize_any(self)
- }
-
- fn visit_none<E>(self) -> Result<Self::Value, E> {
- Ok(Default::default())
- }
-
- fn visit_i128<E: serde::de::Error>(self, value: i128) -> Result<Self::Value, E> {
- $ty::try_from(value)
- .map_err(|_| E::invalid_value(Unexpected::Other("i128"), &self))
- .map(Self::Value::$from_name)
- }
-
- fn visit_i64<E: serde::de::Error>(self, value: i64) -> Result<Self::Value, E> {
- $ty::try_from(value)
- .map_err(|_| E::invalid_value(Unexpected::Signed(value), &self))
- .map(Self::Value::$from_name)
- }
-
- fn visit_u64<E: serde::de::Error>(self, value: u64) -> Result<Self::Value, E> {
- $ty::try_from(value)
- .map_err(|_| E::invalid_value(Unexpected::Unsigned(value), &self))
- .map(Self::Value::$from_name)
- }
-
- fn visit_u128<E: serde::de::Error>(self, value: u128) -> Result<Self::Value, E> {
- $ty::try_from(value)
- .map_err(|_| E::invalid_value(Unexpected::Other("u128"), &self))
- .map(Self::Value::$from_name)
- }
-
- fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
- let value = value
- .parse()
- .map_err(|_| E::invalid_value(Unexpected::Str(value), &self))?;
- self.visit_i64(value)
- }
- }
- };
-}
-
-integer_helper!(
- isize,
- deserialize_isize,
- FromIsize,
- from_isize,
- IsizeVisitor
-);
-
-integer_helper!(
- usize,
- deserialize_usize,
- FromUsize,
- from_usize,
- UsizeVisitor
-);
-
-integer_helper!(u8, deserialize_u8, FromU8, from_u8, U8Visitor);
-integer_helper!(u16, deserialize_u16, FromU16, from_u16, U16Visitor);
-integer_helper!(u32, deserialize_u32, FromU32, from_u32, U32Visitor);
-integer_helper!(u64, deserialize_u64, FromU64, from_u64, U64Visitor);
-integer_helper!(i8, deserialize_i8, FromI8, from_i8, I8Visitor);
-integer_helper!(i16, deserialize_i16, FromI16, from_i16, I16Visitor);
-integer_helper!(i32, deserialize_i32, FromI32, from_i32, I32Visitor);
-integer_helper!(i64, deserialize_i64, FromI64, from_i64, I64Visitor);
-
-// float helpers:
-
-macro_rules! float_helper {
- ($ty:ident, $deserialize_name:ident, $visitor:ident) => {
- pub fn $deserialize_name<'de, D, T>(deserializer: D) -> Result<T, D::Error>
- where
- D: serde::Deserializer<'de>,
- T: FromF64,
- {
- deserializer.deserialize_any($visitor::<T>::new())
- }
-
- struct $visitor<T>(std::marker::PhantomData<T>);
-
- impl<T> $visitor<T> {
- fn new() -> Self {
- Self(std::marker::PhantomData)
- }
- }
-
- impl<'de, T: FromF64> serde::de::DeserializeSeed<'de> for $visitor<T> {
- type Value = T;
-
- fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- $deserialize_name(deserializer)
- }
- }
-
- impl<'de, T> serde::de::Visitor<'de> for $visitor<T>
- where
- T: FromF64,
- {
- type Value = T;
-
- fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.write_str(concat!("a ", stringify!($ty), "-ish..."))
- }
-
- fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- deserializer.deserialize_any(self)
- }
-
- fn visit_none<E>(self) -> Result<Self::Value, E> {
- Ok(Default::default())
- }
-
- fn visit_f64<E: serde::de::Error>(self, value: f64) -> Result<Self::Value, E> {
- Ok(T::from_f64(value))
- }
-
- fn visit_i128<E: serde::de::Error>(self, value: i128) -> Result<Self::Value, E> {
- let conv = value as f64;
- if conv as i128 == value {
- Ok(T::from_f64(conv))
- } else {
- Err(E::invalid_value(Unexpected::Other("i128"), &self))
- }
- }
-
- fn visit_i64<E: serde::de::Error>(self, value: i64) -> Result<Self::Value, E> {
- let conv = value as f64;
- if conv as i64 == value {
- Ok(T::from_f64(conv))
- } else {
- Err(E::invalid_value(Unexpected::Signed(value), &self))
- }
- }
-
- fn visit_u128<E: serde::de::Error>(self, value: u128) -> Result<Self::Value, E> {
- let conv = value as f64;
- if conv as u128 == value {
- Ok(T::from_f64(conv))
- } else {
- Err(E::invalid_value(Unexpected::Other("u128"), &self))
- }
- }
-
- fn visit_u64<E: serde::de::Error>(self, value: u64) -> Result<Self::Value, E> {
- let conv = value as f64;
- if conv as u64 == value {
- Ok(T::from_f64(conv))
- } else {
- Err(E::invalid_value(Unexpected::Unsigned(value), &self))
- }
- }
-
- fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
- let value = value
- .parse()
- .map_err(|_| E::invalid_value(Unexpected::Str(value), &self))?;
- self.visit_f64(value)
- }
- }
- };
-}
-
-#[doc(hidden)]
-pub trait FromF64: Sized + Default {
- fn from_f64(value: f64) -> Self;
-}
-
-impl FromF64 for f32 {
- #[inline(always)]
- fn from_f64(f: f64) -> f32 {
- f as f32
- }
-}
-
-impl FromF64 for f64 {
- #[inline(always)]
- fn from_f64(f: f64) -> f64 {
- f
- }
-}
-
-impl<T: FromF64> FromF64 for Option<T> {
- #[inline(always)]
- fn from_f64(f: f64) -> Option<T> {
- Some(T::from_f64(f))
- }
-}
-
-float_helper!(f32, deserialize_f32, F32Visitor);
-float_helper!(f64, deserialize_f64, F64Visitor);
--
2.39.5
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pbs-devel] [PATCH proxmox 3/3] client: move to proxmox_serde perl helpers
2025-05-13 10:14 [pbs-devel] [PATCH proxmox{, -api-types, -ve-rs} 0/6] Move perl deserializers from proxmox-login to proxmox-serde Stefan Hanreich
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox 1/3] serde: add parsing helpers for perl Stefan Hanreich
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox 2/3] login: move parse module to proxmox-serde Stefan Hanreich
@ 2025-05-13 10:14 ` Stefan Hanreich
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox-api-types 1/2] generator: use proxmox_serde for " Stefan Hanreich
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox-ve-rs 1/1] config: use proxmox_serde " Stefan Hanreich
4 siblings, 0 replies; 7+ messages in thread
From: Stefan Hanreich @ 2025-05-13 10:14 UTC (permalink / raw)
To: pbs-devel
The perl helpers have been moved to proxmox_serde from proxmox_login,
so fix all occurences using the proxmox_login crate.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
proxmox-client/Cargo.toml | 2 ++
proxmox-client/src/lib.rs | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/proxmox-client/Cargo.toml b/proxmox-client/Cargo.toml
index c2682e77..b15c9faa 100644
--- a/proxmox-client/Cargo.toml
+++ b/proxmox-client/Cargo.toml
@@ -27,6 +27,8 @@ proxmox-login = { workspace = true, features = [ "http" ] }
proxmox-http = { workspace = true, optional = true, features = [ "client" ] }
hyper = { workspace = true, optional = true }
+proxmox-serde = { workspace = true, features = [ "perl" ] }
+
[dev-dependencies]
serde_plain.workspace = true
diff --git a/proxmox-client/src/lib.rs b/proxmox-client/src/lib.rs
index e802f4ce..f1df1e1d 100644
--- a/proxmox-client/src/lib.rs
+++ b/proxmox-client/src/lib.rs
@@ -173,10 +173,10 @@ pub struct ApiResponseData<T> {
#[derive(serde::Deserialize)]
struct RawApiResponse<T> {
- #[serde(default, deserialize_with = "proxmox_login::parse::deserialize_u16")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_u16")]
status: Option<u16>,
message: Option<String>,
- #[serde(default, deserialize_with = "proxmox_login::parse::deserialize_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
success: Option<bool>,
data: Option<T>,
--
2.39.5
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pbs-devel] [PATCH proxmox-api-types 1/2] generator: use proxmox_serde for perl helpers
2025-05-13 10:14 [pbs-devel] [PATCH proxmox{, -api-types, -ve-rs} 0/6] Move perl deserializers from proxmox-login to proxmox-serde Stefan Hanreich
` (2 preceding siblings ...)
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox 3/3] client: move to proxmox_serde perl helpers Stefan Hanreich
@ 2025-05-13 10:14 ` Stefan Hanreich
2025-05-13 11:44 ` Stefan Hanreich
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox-ve-rs 1/1] config: use proxmox_serde " Stefan Hanreich
4 siblings, 1 reply; 7+ messages in thread
From: Stefan Hanreich @ 2025-05-13 10:14 UTC (permalink / raw)
To: pbs-devel
The helpers for parsing perl values have been moved to proxmox_serde,
update all references to proxmox_login. No functional changes.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
Cargo.toml | 2 +-
pve-api-types/Cargo.toml | 2 +-
pve-api-types/generator-lib/Schema2Rust.pm | 26 +++++++++++-----------
3 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
index 1bbdd01..1e119d3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,7 +22,7 @@ serde_plain = "1"
serde_json = "1"
proxmox-api-macro = "1.3"
-proxmox-login = "0.2"
+proxmox-serde = "0.1.2"
proxmox-schema = "4"
proxmox-client = "0.5"
diff --git a/pve-api-types/Cargo.toml b/pve-api-types/Cargo.toml
index 73cd3ef..e388cac 100644
--- a/pve-api-types/Cargo.toml
+++ b/pve-api-types/Cargo.toml
@@ -18,7 +18,7 @@ serde_json.workspace = true
serde_plain.workspace = true
#
proxmox-api-macro.workspace = true
-proxmox-login.workspace = true
+proxmox-serde = { workspace = true, features = [ "perl" ] }
proxmox-schema = { workspace = true, features = [ "api-types", "api-macro" ] }
# For the client feature:
diff --git a/pve-api-types/generator-lib/Schema2Rust.pm b/pve-api-types/generator-lib/Schema2Rust.pm
index 009cf13..99a8fd6 100644
--- a/pve-api-types/generator-lib/Schema2Rust.pm
+++ b/pve-api-types/generator-lib/Schema2Rust.pm
@@ -1127,18 +1127,18 @@ my sub array_type : prototype($$$) {
}
my %serde_num = (
- usize => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_usize")]',
- isize => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_isize")]',
- u8 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_u8")]',
- u16 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_u16")]',
- u32 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_u32")]',
- u64 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_u64")]',
- i8 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_i8")]',
- i16 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_i16")]',
- i32 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_i32")]',
- i64 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_i64")]',
- f32 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_f32")]',
- f64 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_f64")]',
+ usize => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_usize")]',
+ isize => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_isize")]',
+ u8 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_u8")]',
+ u16 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_u16")]',
+ u32 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_u32")]',
+ u64 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_u64")]',
+ i8 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_i8")]',
+ i16 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_i16")]',
+ i32 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_i32")]',
+ i64 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_i64")]',
+ f32 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_f32")]',
+ f64 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_f64")]',
);
sub handle_def : prototype($$$) {
@@ -1169,7 +1169,7 @@ sub handle_def : prototype($$$) {
} elsif ($type eq 'boolean') {
$def->{type} = 'bool';
push $def->{attrs}->@*,
- "#[serde(deserialize_with = \"proxmox_login::parse::deserialize_bool\")]";
+ "#[serde(deserialize_with = \"proxmox_serde::perl::deserialize_bool\")]";
$def->{api}->{default} = bool(delete $schema->{default});
} elsif ($type eq 'number') {
$def->{api}->{default} = delete $schema->{default};
--
2.39.5
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pbs-devel] [PATCH proxmox-ve-rs 1/1] config: use proxmox_serde perl helpers
2025-05-13 10:14 [pbs-devel] [PATCH proxmox{, -api-types, -ve-rs} 0/6] Move perl deserializers from proxmox-login to proxmox-serde Stefan Hanreich
` (3 preceding siblings ...)
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox-api-types 1/2] generator: use proxmox_serde for " Stefan Hanreich
@ 2025-05-13 10:14 ` Stefan Hanreich
4 siblings, 0 replies; 7+ messages in thread
From: Stefan Hanreich @ 2025-05-13 10:14 UTC (permalink / raw)
To: pbs-devel
proxmox_serde provides helpers for parsing optional numbers / booleans
coming from perl, so move to using them instead of implementing our
own versions here. No functional changes intended.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
proxmox-ve-config/Cargo.toml | 1 +
proxmox-ve-config/src/firewall/bridge.rs | 3 +-
proxmox-ve-config/src/firewall/cluster.rs | 6 +-
proxmox-ve-config/src/firewall/guest.rs | 14 ++--
proxmox-ve-config/src/firewall/host.rs | 26 ++++----
proxmox-ve-config/src/firewall/parse.rs | 80 -----------------------
6 files changed, 24 insertions(+), 106 deletions(-)
diff --git a/proxmox-ve-config/Cargo.toml b/proxmox-ve-config/Cargo.toml
index 6c7a47e..e998b45 100644
--- a/proxmox-ve-config/Cargo.toml
+++ b/proxmox-ve-config/Cargo.toml
@@ -16,6 +16,7 @@ serde = { version = "1", features = [ "derive" ] }
serde_json = "1"
serde_plain = "1"
serde_with = "3"
+proxmox-serde = { version = "0.1.2", features = [ "perl" ]}
proxmox-schema = "4"
proxmox-sys = "0.6.4"
diff --git a/proxmox-ve-config/src/firewall/bridge.rs b/proxmox-ve-config/src/firewall/bridge.rs
index 4acb6fa..6dea60e 100644
--- a/proxmox-ve-config/src/firewall/bridge.rs
+++ b/proxmox-ve-config/src/firewall/bridge.rs
@@ -3,7 +3,6 @@ use std::io;
use anyhow::Error;
use serde::Deserialize;
-use crate::firewall::parse::serde_option_bool;
use crate::firewall::types::log::LogLevel;
use crate::firewall::types::rule::{Direction, Verdict};
@@ -55,7 +54,7 @@ impl Config {
#[derive(Debug, Default, Deserialize)]
#[cfg_attr(test, derive(Eq, PartialEq))]
pub struct Options {
- #[serde(default, with = "serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
enable: Option<bool>,
policy_forward: Option<Verdict>,
diff --git a/proxmox-ve-config/src/firewall/cluster.rs b/proxmox-ve-config/src/firewall/cluster.rs
index ce3dd53..a775cd9 100644
--- a/proxmox-ve-config/src/firewall/cluster.rs
+++ b/proxmox-ve-config/src/firewall/cluster.rs
@@ -10,7 +10,7 @@ use crate::firewall::types::log::LogRateLimit;
use crate::firewall::types::rule::{Direction, Verdict};
use crate::firewall::types::{Alias, Group, Rule};
-use crate::firewall::parse::{serde_option_bool, serde_option_log_ratelimit};
+use crate::firewall::parse::serde_option_log_ratelimit;
#[derive(Debug, Default)]
pub struct Config {
@@ -118,10 +118,10 @@ impl Config {
#[derive(Debug, Default, Deserialize)]
#[cfg_attr(test, derive(Eq, PartialEq))]
pub struct Options {
- #[serde(default, with = "serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
enable: Option<bool>,
- #[serde(default, with = "serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
ebtables: Option<bool>,
#[serde(default, with = "serde_option_log_ratelimit")]
diff --git a/proxmox-ve-config/src/firewall/guest.rs b/proxmox-ve-config/src/firewall/guest.rs
index 23eaa4e..4428a75 100644
--- a/proxmox-ve-config/src/firewall/guest.rs
+++ b/proxmox-ve-config/src/firewall/guest.rs
@@ -13,8 +13,6 @@ use crate::firewall::types::Ipset;
use anyhow::{bail, Error};
use serde::Deserialize;
-use crate::firewall::parse::serde_option_bool;
-
/// default return value for [`Config::is_enabled()`]
pub const GUEST_ENABLED_DEFAULT: bool = false;
/// default return value for [`Config::allow_ndp()`]
@@ -37,25 +35,25 @@ pub const GUEST_POLICY_FORWARD_DEFAULT: Verdict = Verdict::Accept;
#[derive(Debug, Default, Deserialize)]
#[cfg_attr(test, derive(Eq, PartialEq))]
pub struct Options {
- #[serde(default, with = "serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
dhcp: Option<bool>,
- #[serde(default, with = "serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
enable: Option<bool>,
- #[serde(default, with = "serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
ipfilter: Option<bool>,
- #[serde(default, with = "serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
ndp: Option<bool>,
- #[serde(default, with = "serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
radv: Option<bool>,
log_level_in: Option<LogLevel>,
log_level_out: Option<LogLevel>,
- #[serde(default, with = "serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
macfilter: Option<bool>,
#[serde(rename = "policy_in")]
diff --git a/proxmox-ve-config/src/firewall/host.rs b/proxmox-ve-config/src/firewall/host.rs
index 394896c..f7b02f9 100644
--- a/proxmox-ve-config/src/firewall/host.rs
+++ b/proxmox-ve-config/src/firewall/host.rs
@@ -36,49 +36,49 @@ pub const HOST_LOG_INVALID_CONNTRACK: bool = false;
#[derive(Debug, Default, Deserialize)]
#[cfg_attr(test, derive(Eq, PartialEq))]
pub struct Options {
- #[serde(default, with = "parse::serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
enable: Option<bool>,
- #[serde(default, with = "parse::serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
nftables: Option<bool>,
log_level_in: Option<LogLevel>,
log_level_out: Option<LogLevel>,
log_level_forward: Option<LogLevel>,
- #[serde(default, with = "parse::serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
log_nf_conntrack: Option<bool>,
- #[serde(default, with = "parse::serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
ndp: Option<bool>,
- #[serde(default, with = "parse::serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
nf_conntrack_allow_invalid: Option<bool>,
// is Option<Vec<>> for easier deserialization
#[serde(default, with = "parse::serde_option_conntrack_helpers")]
nf_conntrack_helpers: Option<Vec<String>>,
- #[serde(default, with = "parse::serde_option_number")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_i64")]
nf_conntrack_max: Option<i64>,
- #[serde(default, with = "parse::serde_option_number")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_i64")]
nf_conntrack_tcp_timeout_established: Option<i64>,
- #[serde(default, with = "parse::serde_option_number")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_i64")]
nf_conntrack_tcp_timeout_syn_recv: Option<i64>,
- #[serde(default, with = "parse::serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
nosmurfs: Option<bool>,
- #[serde(default, with = "parse::serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
protection_synflood: Option<bool>,
- #[serde(default, with = "parse::serde_option_number")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_i64")]
protection_synflood_burst: Option<i64>,
- #[serde(default, with = "parse::serde_option_number")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_i64")]
protection_synflood_rate: Option<i64>,
smurf_log_level: Option<LogLevel>,
tcp_flags_log_level: Option<LogLevel>,
- #[serde(default, with = "parse::serde_option_bool")]
+ #[serde(default, deserialize_with = "proxmox_serde::perl::deserialize_bool")]
tcpflags: Option<bool>,
}
diff --git a/proxmox-ve-config/src/firewall/parse.rs b/proxmox-ve-config/src/firewall/parse.rs
index 8cf4757..7fd5c84 100644
--- a/proxmox-ve-config/src/firewall/parse.rs
+++ b/proxmox-ve-config/src/firewall/parse.rs
@@ -148,86 +148,6 @@ pub fn parse_named_section_tail<'a>(
})
}
-// parses a number from a string OR number
-pub mod serde_option_number {
- use std::fmt;
-
- use serde::de::{Deserializer, Error, Visitor};
-
- pub fn deserialize<'de, D: Deserializer<'de>>(
- deserializer: D,
- ) -> Result<Option<i64>, D::Error> {
- struct V;
-
- impl<'de> Visitor<'de> for V {
- type Value = Option<i64>;
-
- fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.write_str("a numerical value")
- }
-
- fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
- v.parse().map_err(E::custom).map(Some)
- }
-
- fn visit_none<E: Error>(self) -> Result<Self::Value, E> {
- Ok(None)
- }
-
- fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
- where
- D: Deserializer<'de>,
- {
- deserializer.deserialize_any(self)
- }
- }
-
- deserializer.deserialize_any(V)
- }
-}
-
-// parses a bool from a string OR bool
-pub mod serde_option_bool {
- use std::fmt;
-
- use serde::de::{Deserializer, Error, Visitor};
-
- pub fn deserialize<'de, D: Deserializer<'de>>(
- deserializer: D,
- ) -> Result<Option<bool>, D::Error> {
- struct V;
-
- impl<'de> Visitor<'de> for V {
- type Value = Option<bool>;
-
- fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.write_str("a boolean-like value")
- }
-
- fn visit_bool<E: Error>(self, v: bool) -> Result<Self::Value, E> {
- Ok(Some(v))
- }
-
- fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
- super::parse_bool(v).map_err(E::custom).map(Some)
- }
-
- fn visit_none<E: Error>(self) -> Result<Self::Value, E> {
- Ok(None)
- }
-
- fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
- where
- D: Deserializer<'de>,
- {
- deserializer.deserialize_any(self)
- }
- }
-
- deserializer.deserialize_any(V)
- }
-}
-
// parses a comma_separated list of strings
pub mod serde_option_conntrack_helpers {
use std::fmt;
--
2.39.5
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [pbs-devel] [PATCH proxmox-api-types 1/2] generator: use proxmox_serde for perl helpers
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox-api-types 1/2] generator: use proxmox_serde for " Stefan Hanreich
@ 2025-05-13 11:44 ` Stefan Hanreich
0 siblings, 0 replies; 7+ messages in thread
From: Stefan Hanreich @ 2025-05-13 11:44 UTC (permalink / raw)
To: pbs-devel
Since the patch #2 didn't go through due to size:
pve-api-types would need to be re-generated after this patch.
On 5/13/25 12:14, Stefan Hanreich wrote:
> The helpers for parsing perl values have been moved to proxmox_serde,
> update all references to proxmox_login. No functional changes.
>
> Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
> ---
> Cargo.toml | 2 +-
> pve-api-types/Cargo.toml | 2 +-
> pve-api-types/generator-lib/Schema2Rust.pm | 26 +++++++++++-----------
> 3 files changed, 15 insertions(+), 15 deletions(-)
>
> diff --git a/Cargo.toml b/Cargo.toml
> index 1bbdd01..1e119d3 100644
> --- a/Cargo.toml
> +++ b/Cargo.toml
> @@ -22,7 +22,7 @@ serde_plain = "1"
> serde_json = "1"
>
> proxmox-api-macro = "1.3"
> -proxmox-login = "0.2"
> +proxmox-serde = "0.1.2"
> proxmox-schema = "4"
>
> proxmox-client = "0.5"
> diff --git a/pve-api-types/Cargo.toml b/pve-api-types/Cargo.toml
> index 73cd3ef..e388cac 100644
> --- a/pve-api-types/Cargo.toml
> +++ b/pve-api-types/Cargo.toml
> @@ -18,7 +18,7 @@ serde_json.workspace = true
> serde_plain.workspace = true
> #
> proxmox-api-macro.workspace = true
> -proxmox-login.workspace = true
> +proxmox-serde = { workspace = true, features = [ "perl" ] }
> proxmox-schema = { workspace = true, features = [ "api-types", "api-macro" ] }
>
> # For the client feature:
> diff --git a/pve-api-types/generator-lib/Schema2Rust.pm b/pve-api-types/generator-lib/Schema2Rust.pm
> index 009cf13..99a8fd6 100644
> --- a/pve-api-types/generator-lib/Schema2Rust.pm
> +++ b/pve-api-types/generator-lib/Schema2Rust.pm
> @@ -1127,18 +1127,18 @@ my sub array_type : prototype($$$) {
> }
>
> my %serde_num = (
> - usize => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_usize")]',
> - isize => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_isize")]',
> - u8 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_u8")]',
> - u16 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_u16")]',
> - u32 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_u32")]',
> - u64 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_u64")]',
> - i8 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_i8")]',
> - i16 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_i16")]',
> - i32 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_i32")]',
> - i64 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_i64")]',
> - f32 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_f32")]',
> - f64 => '#[serde(deserialize_with = "proxmox_login::parse::deserialize_f64")]',
> + usize => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_usize")]',
> + isize => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_isize")]',
> + u8 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_u8")]',
> + u16 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_u16")]',
> + u32 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_u32")]',
> + u64 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_u64")]',
> + i8 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_i8")]',
> + i16 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_i16")]',
> + i32 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_i32")]',
> + i64 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_i64")]',
> + f32 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_f32")]',
> + f64 => '#[serde(deserialize_with = "proxmox_serde::perl::deserialize_f64")]',
> );
>
> sub handle_def : prototype($$$) {
> @@ -1169,7 +1169,7 @@ sub handle_def : prototype($$$) {
> } elsif ($type eq 'boolean') {
> $def->{type} = 'bool';
> push $def->{attrs}->@*,
> - "#[serde(deserialize_with = \"proxmox_login::parse::deserialize_bool\")]";
> + "#[serde(deserialize_with = \"proxmox_serde::perl::deserialize_bool\")]";
> $def->{api}->{default} = bool(delete $schema->{default});
> } elsif ($type eq 'number') {
> $def->{api}->{default} = delete $schema->{default};
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-05-13 11:43 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-05-13 10:14 [pbs-devel] [PATCH proxmox{, -api-types, -ve-rs} 0/6] Move perl deserializers from proxmox-login to proxmox-serde Stefan Hanreich
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox 1/3] serde: add parsing helpers for perl Stefan Hanreich
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox 2/3] login: move parse module to proxmox-serde Stefan Hanreich
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox 3/3] client: move to proxmox_serde perl helpers Stefan Hanreich
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox-api-types 1/2] generator: use proxmox_serde for " Stefan Hanreich
2025-05-13 11:44 ` Stefan Hanreich
2025-05-13 10:14 ` [pbs-devel] [PATCH proxmox-ve-rs 1/1] config: use proxmox_serde " Stefan Hanreich
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal