From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <pdm-devel-bounces@lists.proxmox.com> Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id A4CE61FF16F for <inbox@lore.proxmox.com>; Tue, 15 Apr 2025 10:40:30 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 652D62274; Tue, 15 Apr 2025 10:40:29 +0200 (CEST) Date: Tue, 15 Apr 2025 10:39:55 +0200 From: Wolfgang Bumiller <w.bumiller@proxmox.com> To: Gabriel Goller <g.goller@proxmox.com> Message-ID: <ookoafe5u5cxbrxskvs2cd4372x7iopzhms27kzb5lqkpwry3u@frdpuzgmjmrc> References: <20250414120046.486853-1-g.goller@proxmox.com> <20250414120046.486853-4-g.goller@proxmox.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20250414120046.486853-4-g.goller@proxmox.com> X-SPAM-LEVEL: Spam detection results: 0 AWL 0.080 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 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_RPBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_SAFE_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [typed.rs] Subject: Re: [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 <pdm-devel.lists.proxmox.com> List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pdm-devel>, <mailto:pdm-devel-request@lists.proxmox.com?subject=unsubscribe> List-Archive: <http://lists.proxmox.com/pipermail/pdm-devel/> List-Post: <mailto:pdm-devel@lists.proxmox.com> List-Help: <mailto:pdm-devel-request@lists.proxmox.com?subject=help> List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel>, <mailto:pdm-devel-request@lists.proxmox.com?subject=subscribe> Reply-To: Proxmox Datacenter Manager development discussion <pdm-devel@lists.proxmox.com> Cc: pdm-devel@lists.proxmox.com Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pdm-devel-bounces@lists.proxmox.com Sender: "pdm-devel" <pdm-devel-bounces@lists.proxmox.com> On Mon, Apr 14, 2025 at 02:00:45PM +0200, Gabriel Goller wrote: > These helpers exist on the untyped SectionConfigData struct, but not on > the typed one. To facilitate the migration to the typed > SectionConfigData<T> 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 <g.goller@proxmox.com> > --- > 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<T> SectionConfigData<T> { > } > } > > +#[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 > + } > + }) ^ You could shorten this by matching on the nested structure here: match $map.get($key) { Some($variant(inner)) => Some(inner), _ => 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 > + } ^ (rustfmt puts a `match` here on the `filter_map` line, so that would be much shorter ;-) ) > + }) > + .collect::<Vec<_>>() > + }; > +} > + > +pub use lookup; > +pub use convert_to_typed_array; If, for now, you intend for these to be used via the `typed` module instead of at the top level you should mark these re-exports with `#[doc(inline)]` and the macros above with `#[doc(hidden)]`. Otherwise the documentation shows them at the top level, with the ones in `typed` as re-exports. > + > impl<T: ApiSectionDataEntry + DeserializeOwned> TryFrom<RawSectionConfigData> > for SectionConfigData<T> > { > @@ -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<SectionConfig> = 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<UserSectionConfig> = 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