[pve-devel] [PATCH proxmox master stable-2 1/2] apt: repos: extend `Codename` by `Unknown` variant

Christian Ebner c.ebner at proxmox.com
Mon Feb 5 18:08:26 CET 2024


Instead of returning an Option for the Codename variant, with None for
unknowns, extend the enum by an Unknown variant with additional internal
type to avoid misuse of this variant.

Co-authored-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
Signed-off-by: Christian Ebner <c.ebner at proxmox.com>
---
 proxmox-apt/src/repositories/file.rs    | 12 +++--
 proxmox-apt/src/repositories/release.rs | 61 +++++++++++++++----------
 2 files changed, 46 insertions(+), 27 deletions(-)

diff --git a/proxmox-apt/src/repositories/file.rs b/proxmox-apt/src/repositories/file.rs
index b4c6b08..b8a2c7f 100644
--- a/proxmox-apt/src/repositories/file.rs
+++ b/proxmox-apt/src/repositories/file.rs
@@ -405,10 +405,14 @@ impl APTRepositoryFile {
                     add_info("warning", message_old(base_suite));
                 }
 
-                if Some(codename) == current_codename.next() {
-                    add_info("ignore-pre-upgrade-warning", message_new(base_suite));
-                } else if codename > current_codename {
-                    add_info("warning", message_new(base_suite));
+                match current_codename.next() {
+                    name if name == codename => {
+                        add_info("ignore-pre-upgrade-warning", message_new(base_suite));
+                    }
+                    DebianCodename::Unknown(_, _) if codename > current_codename => {
+                        add_info("warning", message_new(base_suite));
+                    }
+                    _ => {}
                 }
 
                 if let Some(require_suffix) = require_suffix {
diff --git a/proxmox-apt/src/repositories/release.rs b/proxmox-apt/src/repositories/release.rs
index da391e5..508a9e0 100644
--- a/proxmox-apt/src/repositories/release.rs
+++ b/proxmox-apt/src/repositories/release.rs
@@ -3,8 +3,17 @@ use std::io::{BufRead, BufReader};
 
 use anyhow::{bail, format_err, Error};
 
+mod private {
+    // public types in private modules are unnamable by external users, this is similar to the
+    // "sealed trait" pattern
+    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
+    pub struct Internal;
+}
+use private::Internal;
+
 /// The code names of Debian releases. Does not include `sid`.
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+#[repr(u8)]
 pub enum DebianCodename {
     Lenny = 5,
     Squeeze,
@@ -15,13 +24,37 @@ pub enum DebianCodename {
     Bullseye,
     Bookworm,
     Trixie,
+    Unknown(u8, Internal),
 }
 
 impl DebianCodename {
-    pub fn next(&self) -> Option<Self> {
-        match (*self as u8 + 1).try_into() {
-            Ok(codename) => Some(codename),
-            Err(_) => None,
+    pub fn value(&self) -> u8 {
+        match self {
+            Self::Unknown(number, _) => *number,
+            // see 'arbitrary_enum_discriminant' feature for why this is safe:
+            // https://rust-lang.github.io/rfcs/2363-arbitrary-enum-discriminant.html
+            other => unsafe { *(other as *const Self as *const u8) },
+        }
+    }
+
+    pub fn next(&self) -> Self {
+        (self.value() + 1).into()
+    }
+}
+
+impl From<u8> for DebianCodename {
+    fn from(number: u8) -> Self {
+        match number {
+            5 => Self::Lenny,
+            6 => Self::Squeeze,
+            7 => Self::Wheezy,
+            8 => Self::Jessie,
+            9 => Self::Stretch,
+            10 => Self::Buster,
+            11 => Self::Bullseye,
+            12 => Self::Bookworm,
+            13 => Self::Trixie,
+            number => Self::Unknown(number, Internal),
         }
     }
 }
@@ -45,25 +78,6 @@ impl TryFrom<&str> for DebianCodename {
     }
 }
 
-impl TryFrom<u8> for DebianCodename {
-    type Error = Error;
-
-    fn try_from(number: u8) -> Result<Self, Error> {
-        match number {
-            5 => Ok(DebianCodename::Lenny),
-            6 => Ok(DebianCodename::Squeeze),
-            7 => Ok(DebianCodename::Wheezy),
-            8 => Ok(DebianCodename::Jessie),
-            9 => Ok(DebianCodename::Stretch),
-            10 => Ok(DebianCodename::Buster),
-            11 => Ok(DebianCodename::Bullseye),
-            12 => Ok(DebianCodename::Bookworm),
-            13 => Ok(DebianCodename::Trixie),
-            _ => bail!("unknown Debian release number '{}'", number),
-        }
-    }
-}
-
 impl Display for DebianCodename {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match self {
@@ -76,6 +90,7 @@ impl Display for DebianCodename {
             DebianCodename::Bullseye => write!(f, "bullseye"),
             DebianCodename::Bookworm => write!(f, "bookworm"),
             DebianCodename::Trixie => write!(f, "trixie"),
+            DebianCodename::Unknown(number, _) => write!(f, "unknown"),
         }
     }
 }
-- 
2.30.2





More information about the pve-devel mailing list