public inbox for pdm-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: pdm-devel@lists.proxmox.com
Subject: [PATCH proxmox v3 1/2] add proxmox-const-utils crate, factor out checks from proxmox-schema
Date: Mon, 14 Sep 2026 14:30:44 +0200	[thread overview]
Message-ID: <20260914123243.3216993-2-d.csapak@proxmox.com> (raw)
In-Reply-To: <20260914123243.3216993-1-d.csapak@proxmox.com>

We want to do some const fn checks in multiple crates, and
proxmox-schema already contained the one we need, so factor it out.

For convenience also add a simple `byte_string_eq`. Also add some basic
tests.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 Cargo.toml                               |  2 +
 proxmox-const-utils/Cargo.toml           | 13 +++++
 proxmox-const-utils/debian/changelog     |  5 ++
 proxmox-const-utils/debian/control       | 30 +++++++++++
 proxmox-const-utils/debian/copyright     | 18 +++++++
 proxmox-const-utils/debian/debcargo.toml |  7 +++
 proxmox-const-utils/src/lib.rs           | 66 ++++++++++++++++++++++++
 proxmox-schema/Cargo.toml                |  1 +
 proxmox-schema/src/const_test_utils.rs   | 25 ---------
 proxmox-schema/src/lib.rs                |  2 -
 proxmox-schema/src/schema.rs             | 10 ++--
 11 files changed, 147 insertions(+), 32 deletions(-)
 create mode 100644 proxmox-const-utils/Cargo.toml
 create mode 100644 proxmox-const-utils/debian/changelog
 create mode 100644 proxmox-const-utils/debian/control
 create mode 100644 proxmox-const-utils/debian/copyright
 create mode 100644 proxmox-const-utils/debian/debcargo.toml
 create mode 100644 proxmox-const-utils/src/lib.rs
 delete mode 100644 proxmox-schema/src/const_test_utils.rs

diff --git a/Cargo.toml b/Cargo.toml
index f631b404..ba29c8bb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,6 +13,7 @@ members = [
     "proxmox-client",
     "proxmox-compression",
     "proxmox-config-digest",
+    "proxmox-const-utils",
     "proxmox-daemon",
     "proxmox-deb-version",
     "proxmox-disks",
@@ -166,6 +167,7 @@ proxmox-auth-api = { version = "1.0.5", path = "proxmox-auth-api" }
 proxmox-async = { version = "0.5.0", path = "proxmox-async" }
 proxmox-base64 = {  version = "1.0.0", path = "proxmox-base64" }
 proxmox-compression = { version = "1.0.0", path = "proxmox-compression" }
+proxmox-const-utils = { version = "0.1.0", path = "proxmox-const-utils" }
 proxmox-daemon = { version = "1.0.0", path = "proxmox-daemon" }
 proxmox-disks = { version = "0.2.0", path = "proxmox-disks" }
 proxmox-fixed-string = { version = "0.1.0", path = "proxmox-fixed-string" }
diff --git a/proxmox-const-utils/Cargo.toml b/proxmox-const-utils/Cargo.toml
new file mode 100644
index 00000000..914c5fd3
--- /dev/null
+++ b/proxmox-const-utils/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "proxmox-const-utils"
+description = "const fn utilities used by proxmox crates"
+version = "0.1.0"
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+repository.workspace = true
+homepage.workspace = true
+exclude.workspace = true
+rust-version.workspace = true
+
+[dependencies]
diff --git a/proxmox-const-utils/debian/changelog b/proxmox-const-utils/debian/changelog
new file mode 100644
index 00000000..fc49a60f
--- /dev/null
+++ b/proxmox-const-utils/debian/changelog
@@ -0,0 +1,5 @@
+rust-proxmox-const-utils (0.1.0) trixie; urgency=medium
+
+  * initial version
+
+ -- Proxmox Support Team <support@proxmox.com>  Mon, 14 Sep 2026 13:38:43 +0200
diff --git a/proxmox-const-utils/debian/control b/proxmox-const-utils/debian/control
new file mode 100644
index 00000000..e45bf06a
--- /dev/null
+++ b/proxmox-const-utils/debian/control
@@ -0,0 +1,30 @@
+Source: rust-proxmox-const-utils
+Section: rust
+Priority: optional
+Build-Depends: debhelper-compat (= 13),
+ dh-sequence-cargo
+Build-Depends-Arch: cargo:native <!nocheck>,
+ rustc:native (>= 1.85) <!nocheck>,
+ libstd-rust-dev <!nocheck>
+Maintainer: Proxmox Support Team <support@proxmox.com>
+Standards-Version: 4.7.2
+Vcs-Git: git://git.proxmox.com/git/proxmox.git
+Vcs-Browser: https://git.proxmox.com/?p=proxmox.git
+Homepage: https://proxmox.com
+X-Cargo-Crate: proxmox-const-utils
+
+Package: librust-proxmox-const-utils-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends}
+Provides:
+ librust-proxmox-const-utils+default-dev (= ${binary:Version}),
+ librust-proxmox-const-utils-0-dev (= ${binary:Version}),
+ librust-proxmox-const-utils-0+default-dev (= ${binary:Version}),
+ librust-proxmox-const-utils-0.1-dev (= ${binary:Version}),
+ librust-proxmox-const-utils-0.1+default-dev (= ${binary:Version}),
+ librust-proxmox-const-utils-0.1.0-dev (= ${binary:Version}),
+ librust-proxmox-const-utils-0.1.0+default-dev (= ${binary:Version})
+Description: Const fn utilities used by proxmox crates - Rust source code
+ Source code for Debianized Rust crate "proxmox-const-utils"
diff --git a/proxmox-const-utils/debian/copyright b/proxmox-const-utils/debian/copyright
new file mode 100644
index 00000000..cb3e5adc
--- /dev/null
+++ b/proxmox-const-utils/debian/copyright
@@ -0,0 +1,18 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+
+Files:
+ *
+Copyright: 2025 - 2026 Proxmox Server Solutions GmbH <support@proxmox.com>
+License: AGPL-3.0-or-later
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU Affero General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option) any
+ later version.
+ .
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+ details.
+ .
+ You should have received a copy of the GNU Affero General Public License along
+ with this program. If not, see <https://www.gnu.org/licenses/>.
diff --git a/proxmox-const-utils/debian/debcargo.toml b/proxmox-const-utils/debian/debcargo.toml
new file mode 100644
index 00000000..b7864cdb
--- /dev/null
+++ b/proxmox-const-utils/debian/debcargo.toml
@@ -0,0 +1,7 @@
+overlay = "."
+crate_src_path = ".."
+maintainer = "Proxmox Support Team <support@proxmox.com>"
+
+[source]
+vcs_git = "git://git.proxmox.com/git/proxmox.git"
+vcs_browser = "https://git.proxmox.com/?p=proxmox.git"
diff --git a/proxmox-const-utils/src/lib.rs b/proxmox-const-utils/src/lib.rs
new file mode 100644
index 00000000..a4a4ceff
--- /dev/null
+++ b/proxmox-const-utils/src/lib.rs
@@ -0,0 +1,66 @@
+/// Note: this only compares *bytes* and is not strictly speaking equivalent to str::cmp!
+pub const fn byte_string_cmp(a: &[u8], b: &[u8]) -> std::cmp::Ordering {
+    use std::cmp::Ordering::*;
+
+    // const-version of `min(a.len(), b.len())` while simultaneously remembering
+    // `cmp(a.len(), b.len())`.
+    let (end, len_result) = if a.len() < b.len() {
+        (a.len(), Less)
+    } else if a.len() > b.len() {
+        (b.len(), Greater)
+    } else {
+        (a.len(), Equal)
+    };
+
+    let mut i = 0;
+    while i != end {
+        if a[i] < b[i] {
+            return Less;
+        } else if a[i] > b[i] {
+            return Greater;
+        }
+        i += 1;
+    }
+    len_result
+}
+
+/// As with [`byte_string_cmp`] this only compares bytes.
+pub const fn byte_string_eq(a: &[u8], b: &[u8]) -> bool {
+    matches!(byte_string_cmp(a, b), std::cmp::Ordering::Equal)
+}
+
+#[cfg(test)]
+mod test {
+    use crate::{byte_string_cmp, byte_string_eq};
+    use std::cmp::Ordering::{self, *};
+
+    fn str_cmp(a: &str, b: &str, res: Ordering) {
+        assert_eq!(byte_string_cmp(a.as_bytes(), b.as_bytes()), res);
+    }
+
+    fn str_eq(a: &str, b: &str, res: bool) {
+        assert_eq!(byte_string_eq(a.as_bytes(), b.as_bytes()), res);
+    }
+
+    #[test]
+    fn test_cmp() {
+        str_cmp("foo", "bar", Greater);
+        str_cmp("bar", "foo", Less);
+        str_cmp("foo", "fooo", Less);
+        str_cmp("fooo", "foo", Greater);
+        str_cmp("foo", "foo", Equal);
+        str_cmp("", "", Equal);
+        str_cmp("", "foo", Less);
+        str_cmp("foo", "", Greater);
+    }
+
+    #[test]
+    fn test_eq() {
+        str_eq("", "", true);
+        str_eq("foo", "foo", true);
+        str_eq("foo", "", false);
+        str_eq("", "foo", false);
+        str_eq("bar", "foo", false);
+        str_eq("foo", "bar", false);
+    }
+}
diff --git a/proxmox-schema/Cargo.toml b/proxmox-schema/Cargo.toml
index 79eab333..b2de56dd 100644
--- a/proxmox-schema/Cargo.toml
+++ b/proxmox-schema/Cargo.toml
@@ -24,6 +24,7 @@ libc = { workspace = true, optional = true }
 nix = { workspace = true, optional = true, features = [ "feature" ] }
 
 proxmox-api-macro = { workspace = true, optional = true }
+proxmox-const-utils.workspace = true
 
 [dev-dependencies]
 url.workspace = true
diff --git a/proxmox-schema/src/const_test_utils.rs b/proxmox-schema/src/const_test_utils.rs
deleted file mode 100644
index 3613ac35..00000000
--- a/proxmox-schema/src/const_test_utils.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-/// Note: this only compares *bytes* and is not strictly speaking equivalent to str::cmp!
-pub const fn byte_string_cmp(a: &[u8], b: &[u8]) -> std::cmp::Ordering {
-    use std::cmp::Ordering::*;
-
-    // const-version of `min(a.len(), b.len())` while simultaneously remembering
-    // `cmp(a.len(), b.len())`.
-    let (end, len_result) = if a.len() < b.len() {
-        (a.len(), Less)
-    } else if a.len() > b.len() {
-        (b.len(), Greater)
-    } else {
-        (a.len(), Equal)
-    };
-
-    let mut i = 0;
-    while i != end {
-        if a[i] < b[i] {
-            return Less;
-        } else if a[i] > b[i] {
-            return Greater;
-        }
-        i += 1;
-    }
-    len_result
-}
diff --git a/proxmox-schema/src/lib.rs b/proxmox-schema/src/lib.rs
index 727822f0..5175280c 100644
--- a/proxmox-schema/src/lib.rs
+++ b/proxmox-schema/src/lib.rs
@@ -36,5 +36,3 @@ pub mod upid;
 
 #[cfg(feature = "api-types")]
 pub mod api_types;
-
-pub(crate) mod const_test_utils;
diff --git a/proxmox-schema/src/schema.rs b/proxmox-schema/src/schema.rs
index 378c6290..97e502a7 100644
--- a/proxmox-schema/src/schema.rs
+++ b/proxmox-schema/src/schema.rs
@@ -655,7 +655,7 @@ const fn assert_properties_sorted(properties: SchemaPropertyMap) {
     while i != properties.len() {
         let cur = properties[i].0;
         if let Some(prev) = prev {
-            match crate::const_test_utils::byte_string_cmp(prev.as_bytes(), cur.as_bytes()) {
+            match proxmox_const_utils::byte_string_cmp(prev.as_bytes(), cur.as_bytes()) {
                 Ordering::Greater => panic!("object schema properties must be sorted"),
                 Ordering::Equal => panic!("duplicate object schema properties not allowed"),
                 Ordering::Less => (),
@@ -672,7 +672,7 @@ const fn property_map_contains(properties: SchemaPropertyMap, needle: &'static s
     let mut i = 0;
     while i != properties.len() {
         if let Ordering::Equal =
-            crate::const_test_utils::byte_string_cmp(properties[i].0.as_bytes(), needle.as_bytes())
+            proxmox_const_utils::byte_string_cmp(properties[i].0.as_bytes(), needle.as_bytes())
         {
             return true;
         }
@@ -688,7 +688,7 @@ const fn assert_key_not_alias(key: &str, aliases: PropertyAliasMap) {
     while i != aliases.len() {
         let (alias, _) = aliases[i];
         if let Ordering::Equal =
-            crate::const_test_utils::byte_string_cmp(alias.as_bytes(), key.as_bytes())
+            proxmox_const_utils::byte_string_cmp(alias.as_bytes(), key.as_bytes())
         {
             panic!("key must reference a canonical property, not an alias");
         }
@@ -704,7 +704,7 @@ const fn assert_property_aliases_valid(aliases: PropertyAliasMap, properties: Sc
     while i != aliases.len() {
         let (alias, target) = aliases[i];
         if let Some(prev) = prev {
-            match crate::const_test_utils::byte_string_cmp(prev.as_bytes(), alias.as_bytes()) {
+            match proxmox_const_utils::byte_string_cmp(prev.as_bytes(), alias.as_bytes()) {
                 Ordering::Greater => panic!("property aliases must be sorted by alias name"),
                 Ordering::Equal => panic!("duplicate property alias not allowed"),
                 Ordering::Less => (),
@@ -1050,7 +1050,7 @@ const fn assert_one_of_list_is_sorted(list: &[(&str, &Schema)]) {
     while i != list.len() {
         let cur = list[i].0;
         if let Some(prev) = prev {
-            match crate::const_test_utils::byte_string_cmp(prev.as_bytes(), cur.as_bytes()) {
+            match proxmox_const_utils::byte_string_cmp(prev.as_bytes(), cur.as_bytes()) {
                 Ordering::Greater => panic!("oneOf variant list must be sorted"),
                 Ordering::Equal => panic!("multiple variants of the same type"),
                 Ordering::Less => (),
-- 
2.47.3





  reply	other threads:[~2026-09-14 12:32 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-14 12:30 [PATCH proxmox v3 0/2] check privilege paths during compilation Dominik Csapak
2026-09-14 12:30 ` Dominik Csapak [this message]
2026-09-14 12:30 ` [PATCH proxmox v3 2/2] router: compile time check privilege path parameters for existence Dominik Csapak

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260914123243.3216993-2-d.csapak@proxmox.com \
    --to=d.csapak@proxmox.com \
    --cc=pdm-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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