From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 0185E1FF16E for ; Mon, 14 Apr 2025 14:01:02 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id E6279319C0; Mon, 14 Apr 2025 14:01:00 +0200 (CEST) From: Gabriel Goller To: pdm-devel@lists.proxmox.com Date: Mon, 14 Apr 2025 14:00:45 +0200 Message-Id: <20250414120046.486853-4-g.goller@proxmox.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250414120046.486853-1-g.goller@proxmox.com> References: <20250414120046.486853-1-g.goller@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL -0.021 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pdm-devel] [PATCH proxmox 3/3] section-config: add lookup and convert_to_typed_array helpers X-BeenThere: pdm-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Datacenter Manager development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox Datacenter Manager development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pdm-devel-bounces@lists.proxmox.com Sender: "pdm-devel" These helpers exist on the untyped SectionConfigData struct, but not on the typed one. To facilitate the migration to the typed SectionConfigData add these as macros. These can be used to simply lookup an item with a specific type by passing the type, e.g.: lookup!(config, "root", UserSectionConfig::User) or retrieve a vector with the sections that correspond to the passed type, e.g.: convert_to_typed_array!(config, UserSectionConfig::ApiToken) Also add some simple unit-tests to test them. Signed-off-by: Gabriel Goller --- proxmox-section-config/Cargo.toml | 3 + proxmox-section-config/src/typed.rs | 125 ++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) diff --git a/proxmox-section-config/Cargo.toml b/proxmox-section-config/Cargo.toml index 4796a6bff5e6..eb456a3bb3e6 100644 --- a/proxmox-section-config/Cargo.toml +++ b/proxmox-section-config/Cargo.toml @@ -19,3 +19,6 @@ serde_json.workspace = true proxmox-schema.workspace = true # FIXME: remove! proxmox-lang.workspace = true + +[dev-dependencies] +serde = { workspace = true, features = ["derive"] } diff --git a/proxmox-section-config/src/typed.rs b/proxmox-section-config/src/typed.rs index 14a8d87e3425..c13e2338461d 100644 --- a/proxmox-section-config/src/typed.rs +++ b/proxmox-section-config/src/typed.rs @@ -207,6 +207,37 @@ impl SectionConfigData { } } +#[macro_export] +macro_rules! lookup { + ($map:expr, $key:expr, $variant:path) => { + $map.get($key).and_then(|value| { + if let $variant(inner) = value { + Some(inner) + } else { + None + } + }) + }; +} + +#[macro_export] +macro_rules! convert_to_typed_array { + ($map:expr, $variant:path) => { + $map.values() + .filter_map(|value| { + if let $variant(inner) = value { + Some(inner) + } else { + None + } + }) + .collect::>() + }; +} + +pub use lookup; +pub use convert_to_typed_array; + impl TryFrom for SectionConfigData { @@ -367,6 +398,7 @@ mod test { use std::sync::OnceLock; use proxmox_schema::{ApiStringFormat, EnumEntry, ObjectSchema, Schema, StringSchema}; + use serde::{Deserialize, Serialize}; use crate::{SectionConfig, SectionConfigPlugin}; @@ -508,4 +540,97 @@ mod test { .expect("failed to write out section config"); assert_eq!(written, raw); } + + #[derive(Deserialize, Serialize, Debug, PartialEq, Eq, PartialOrd, Ord)] + struct User { + user_id: String, + } + + #[derive(Deserialize, Serialize, Debug, PartialEq, Eq, PartialOrd, Ord)] + struct Token { + token: String, + } + + #[derive(Deserialize, Serialize)] + enum UserSectionConfig { + #[serde(rename="user")] + User(User), + #[serde(rename="token")] + Token(Token) + } + + const USER_PROPERTIES: ObjectSchema = ObjectSchema::new( + "User", + &[ + ("user_id", false, &StringSchema::new("Some id.").schema()), + ], + ); + + const TOKEN_PROPERTIES: ObjectSchema = ObjectSchema::new( + "Token", + &[ + ("token", false, &StringSchema::new("Some token.").schema()), + ], + ); + + impl ApiSectionDataEntry for UserSectionConfig { + fn section_config() -> &'static SectionConfig { + static SC: OnceLock = OnceLock::new(); + + SC.get_or_init(|| { + let mut config = SectionConfig::new(&ID_SCHEMA); + config.register_plugin(SectionConfigPlugin::new( + "user".to_string(), + None, + &USER_PROPERTIES, + )); + config.register_plugin(SectionConfigPlugin::new( + "token".to_string(), + None, + &TOKEN_PROPERTIES, + )); + config + }) + } + + fn section_type(&self) -> &'static str { + match self { + UserSectionConfig::User(_) => "user", + UserSectionConfig::Token(_) => "token", + } + } + } + + #[test] + fn test_macros() { + let filename = "sync.cfg"; + let raw = "\ + token: first\n\ + \ttoken 1\n\ + \n\ + user: second\n\ + \tuser_id 2\n\ + \n\ + user: third\n\ + \tuser_id 4\n\ + "; + + let parsed = UserSectionConfig::section_config() + .parse(filename, raw) + .expect("failed to parse"); + let config: SectionConfigData = parsed.try_into().expect("failed to convert"); + + let token = lookup!(config, "first", UserSectionConfig::Token); + assert_eq!(token.unwrap().token, "1"); + let user = lookup!(config, "second", UserSectionConfig::User); + assert_eq!(user.unwrap().user_id, "2"); + + let mut tokens = convert_to_typed_array!(config, UserSectionConfig::Token); + tokens.sort(); + assert_eq!(tokens, vec![&Token{token: "1".to_owned()}]); + + let mut users = convert_to_typed_array!(config, UserSectionConfig::User); + users.sort(); + assert_eq!(users, vec![&User{user_id: "2".to_owned()}, &User{user_id: "4".to_owned()}]); + } } -- 2.39.5 _______________________________________________ pdm-devel mailing list pdm-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel