From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id A7A849567C for ; Wed, 18 Jan 2023 13:22:02 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 8BF511FB5D for ; Wed, 18 Jan 2023 13:21:32 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS for ; Wed, 18 Jan 2023 13:21:31 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id B6B514508E for ; Wed, 18 Jan 2023 13:21:31 +0100 (CET) Date: Wed, 18 Jan 2023 13:21:30 +0100 From: Wolfgang Bumiller To: Lukas Wagner Cc: pbs-devel@lists.proxmox.com Message-ID: <20230118122130.d4gl3ytyv3muacrs@casey.proxmox.com> References: <20230117142037.847150-1-l.wagner@proxmox.com> <20230117142037.847150-4-l.wagner@proxmox.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20230117142037.847150-4-l.wagner@proxmox.com> X-SPAM-LEVEL: Spam detection results: 0 AWL 0.206 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% 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: Re: [pbs-devel] [PATCH proxmox-ldap 3/6] add helpers for constructing LDAP filters X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 18 Jan 2023 12:22:02 -0000 On Tue, Jan 17, 2023 at 03:20:34PM +0100, Lukas Wagner wrote: > Signed-off-by: Lukas Wagner > --- > src/lib.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 70 insertions(+) > > diff --git a/src/lib.rs b/src/lib.rs > index 48eb863..40c4f6d 100644 > --- a/src/lib.rs > +++ b/src/lib.rs > @@ -226,3 +226,73 @@ impl LdapConnection { > bail!("user not found") > } > } > + > +#[allow(dead_code)] > +enum FilterElement { Your only user of this is short-lived and can easily just borrow the strings. I think we should give this a lifetime and use a str ref instead of strings. > + And(Vec), > + Or(Vec), > + Condition(String, String), > + Not(Box), > + Verbatim(String), > +} > + > +impl ToString for FilterElement { Is there a particular reason to implement `ToString` instead of `Display`? If not, a `Display` implementation would need much fewer temporary allocated strings as it would just keep appending to the same `fmt::Formatter`. > + fn to_string(&self) -> String { > + fn children_to_string(children: &[FilterElement]) -> String { > + children.iter().fold(String::new(), |mut acc, v| { > + acc.push_str(&v.to_string()); > + acc > + }) > + } > + > + match self { > + FilterElement::And(children) => { > + format!("(&{})", children_to_string(children)) > + } > + FilterElement::Or(children) => { > + format!("(|{})", children_to_string(children)) > + } > + FilterElement::Not(element) => { > + format!("(!{})", element.to_string()) > + } > + FilterElement::Condition(attr, value) => { > + format!("({attr}={value})") > + } > + FilterElement::Verbatim(verbatim) => verbatim.clone(), > + } > + } > +} > + > +#[cfg(test)] > +mod tests { > + use super::FilterElement::*; > + > + #[test] > + fn test_filter_elements_to_string() { > + assert_eq!( > + "(uid=john)", > + Condition("uid".into(), "john".into()).to_string() > + ); > + assert_eq!( > + "(!(uid=john))", > + Not(Box::new(Condition("uid".into(), "john".into()))).to_string() > + ); > + > + assert_eq!("(foo=bar)", Verbatim("(foo=bar)".into()).to_string()); > + > + let filter_string = And(vec![ > + Condition("givenname".into(), "john".into()), > + Condition("sn".into(), "doe".into()), > + Or(vec![ > + Condition("email".into(), "john@foo".into()), > + Condition("email".into(), "john@bar".into()), > + ]), > + ]) > + .to_string(); > + > + assert_eq!( > + "(&(givenname=john)(sn=doe)(|(email=john@foo)(email=john@bar)))".to_owned(), ^ The `.to_owned()` is not needed there. > + filter_string > + ); > + } > +} > -- > 2.30.2