public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pbs-devel] [PATCH proxmox] schema: add const fn unwrap_*_schema/format methods
@ 2022-02-22  8:47 Wolfgang Bumiller
  2022-02-22  8:47 ` [pbs-devel] [PATCH backup] constify schema usage and dedup some code Wolfgang Bumiller
  2022-02-23  8:31 ` [pbs-devel] [PATCH proxmox] schema: add const fn unwrap_*_schema/format methods Thomas Lamprecht
  0 siblings, 2 replies; 3+ messages in thread
From: Wolfgang Bumiller @ 2022-02-22  8:47 UTC (permalink / raw)
  To: pbs-devel

'unwrap_' because they will panic and as `const fn` since
panic in const fn is now possible

Note that const evaluation will only be triggered when
actually used in const context, so to ensure *compile time*
checks, use something like this:

    const FOO_SCHEMA: &AllOfSchema =
        SomeType::API_SCHEMA.unwrap_all_of_schema();
    then_use(FOO_SCHEMA);

or to use the list of enum values of an enum string type
with compile time checks:

    const LIST: &'static [EnumEntry] =
        AnEnumStringType::API_SCHEMA
            .unwrap_string_schema()
            .unwrap_format()
            .unwrap_enum_format();
    for values in LIST {
        ...
    }

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
While schemas are usually unlikely to change type or lose properties
such as enum lists, for `ObjectSchema` and `AllOfSchema` this may
actually allow catching future issues at build-time...

If we want to do this, I'd prepare a similar patch set for all the
`ApiHandler::...` value extractions we do in the CLI in pbs (just look
at the output of `egrep -B1 -nr 'unreachable' ./src ./*/src` in pbs ;-) )

 proxmox-schema/src/schema.rs | 90 ++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/proxmox-schema/src/schema.rs b/proxmox-schema/src/schema.rs
index 58c6a82..0f90682 100644
--- a/proxmox-schema/src/schema.rs
+++ b/proxmox-schema/src/schema.rs
@@ -459,6 +459,14 @@ impl StringSchema {
             bail!("Expected string value.");
         }
     }
+
+    /// Get the [`format`](ApiStringFormat), panics if there is no format.
+    pub const fn unwrap_format(&self) -> &'static ApiStringFormat {
+        match self.format {
+            Some(v) => v,
+            None => panic!("unwrap_format on StringSchema without format"),
+        }
+    }
 }
 
 /// Data type to describe array of values.
@@ -950,6 +958,62 @@ impl Schema {
             _ => bail!("Got unexpected schema type."),
         }
     }
+
+    /// Gets the underlying [`BooleanSchema`], panics on different schemas.
+    pub const fn unwrap_boolean_schema(&self) -> &BooleanSchema {
+        match self {
+            Schema::Boolean(s) => s,
+            _ => panic!("unwrap_boolean_schema on different schema"),
+        }
+    }
+
+    /// Gets the underlying [`IntegerSchema`], panics on different schemas.
+    pub const fn unwrap_integer_schema(&self) -> &IntegerSchema {
+        match self {
+            Schema::Integer(s) => s,
+            _ => panic!("unwrap_integer_schema on different schema"),
+        }
+    }
+
+    /// Gets the underlying [`NumberSchema`], panics on different schemas.
+    pub const fn unwrap_number_schema(&self) -> &NumberSchema {
+        match self {
+            Schema::Number(s) => s,
+            _ => panic!("unwrap_number_schema on different schema"),
+        }
+    }
+
+    /// Gets the underlying [`StringSchema`], panics on different schemas.
+    pub const fn unwrap_string_schema(&self) -> &StringSchema {
+        match self {
+            Schema::String(s) => s,
+            _ => panic!("unwrap_string_schema on different schema"),
+        }
+    }
+
+    /// Gets the underlying [`ObjectSchema`], panics on different schemas.
+    pub const fn unwrap_object_schema(&self) -> &ObjectSchema {
+        match self {
+            Schema::Object(s) => s,
+            _ => panic!("unwrap_object_schema on different schema"),
+        }
+    }
+
+    /// Gets the underlying [`ArraySchema`], panics on different schemas.
+    pub const fn unwrap_array_schema(&self) -> &ArraySchema {
+        match self {
+            Schema::Array(s) => s,
+            _ => panic!("unwrap_array_schema on different schema"),
+        }
+    }
+
+    /// Gets the underlying [`AllOfSchema`], panics on different schemas.
+    pub const fn unwrap_all_of_schema(&self) -> &AllOfSchema {
+        match self {
+            Schema::AllOf(s) => s,
+            _ => panic!("unwrap_all_of_schema on different schema"),
+        }
+    }
 }
 
 /// A string enum entry. An enum entry must have a value and a description.
@@ -1047,6 +1111,32 @@ pub enum ApiStringFormat {
     VerifyFn(fn(&str) -> Result<(), Error>),
 }
 
+impl ApiStringFormat {
+    /// Gets the underlying [`&[EnumEntry]`](EnumEntry) list, panics on different formats.
+    pub const fn unwrap_enum_format(&self) -> &'static [EnumEntry] {
+        match self {
+            ApiStringFormat::Enum(v) => v,
+            _ => panic!("unwrap_enum_format on a different ApiStringFormat"),
+        }
+    }
+
+    /// Gets the underlying [`&ConstRegexPattern`](ConstRegexPattern), panics on different formats.
+    pub const fn unwrap_pattern_format(&self) -> &'static ConstRegexPattern {
+        match self {
+            ApiStringFormat::Pattern(v) => v,
+            _ => panic!("unwrap_pattern_format on a different ApiStringFormat"),
+        }
+    }
+
+    /// Gets the underlying property [`&Schema`](Schema), panics on different formats.
+    pub const fn unwrap_property_string_format(&self) -> &'static Schema {
+        match self {
+            ApiStringFormat::PropertyString(v) => v,
+            _ => panic!("unwrap_property_string_format on a different ApiStringFormat"),
+        }
+    }
+}
+
 impl std::fmt::Debug for ApiStringFormat {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-- 
2.30.2





^ permalink raw reply	[flat|nested] 3+ messages in thread

* [pbs-devel] [PATCH backup] constify schema usage and dedup some code
  2022-02-22  8:47 [pbs-devel] [PATCH proxmox] schema: add const fn unwrap_*_schema/format methods Wolfgang Bumiller
@ 2022-02-22  8:47 ` Wolfgang Bumiller
  2022-02-23  8:31 ` [pbs-devel] [PATCH proxmox] schema: add const fn unwrap_*_schema/format methods Thomas Lamprecht
  1 sibling, 0 replies; 3+ messages in thread
From: Wolfgang Bumiller @ 2022-02-22  8:47 UTC (permalink / raw)
  To: pbs-devel

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
 pbs-config/src/acl.rs             | 12 ++---
 pbs-config/src/datastore.rs       | 12 ++---
 pbs-config/src/domains.rs         | 12 ++---
 pbs-config/src/drive.rs           | 23 +++-----
 pbs-config/src/media_pool.rs      |  7 +--
 pbs-config/src/remote.rs          |  9 ++--
 pbs-config/src/sync.rs            | 11 ++--
 pbs-config/src/tape_job.rs        | 12 ++---
 pbs-config/src/traffic_control.rs | 10 ++--
 pbs-config/src/user.rs            | 16 +++---
 pbs-config/src/verify.rs          | 10 ++--
 src/config/acme/plugin.rs         | 16 +++---
 src/tools/systemd/config.rs       | 88 +++++++++----------------------
 13 files changed, 83 insertions(+), 155 deletions(-)

diff --git a/pbs-config/src/acl.rs b/pbs-config/src/acl.rs
index 13af45a9..28f0f686 100644
--- a/pbs-config/src/acl.rs
+++ b/pbs-config/src/acl.rs
@@ -8,7 +8,7 @@ use anyhow::{bail, Error};
 
 use lazy_static::lazy_static;
 
-use proxmox_schema::{ApiStringFormat, ApiType, Schema, StringSchema};
+use proxmox_schema::ApiType;
 
 use pbs_api_types::{Authid, Userid, Role, ROLE_NAME_NO_ACCESS};
 
@@ -20,12 +20,12 @@ lazy_static! {
     pub static ref ROLE_NAMES: HashMap<&'static str, (u64, &'static str)> = {
         let mut map = HashMap::new();
 
-        let list = match Role::API_SCHEMA {
-            Schema::String(StringSchema { format: Some(ApiStringFormat::Enum(list)), .. }) => list,
-            _ => unreachable!(),
-        };
+        const ROLE_SCHEMA_ENUM_LIST: &'static [proxmox_schema::EnumEntry] = Role::API_SCHEMA
+            .unwrap_string_schema()
+            .unwrap_format()
+            .unwrap_enum_format();
 
-        for entry in list.iter() {
+        for entry in ROLE_SCHEMA_ENUM_LIST {
             let privs: u64 = Role::from_str(entry.value).unwrap() as u64;
             map.insert(entry.value, (privs, entry.description));
         }
diff --git a/pbs-config/src/datastore.rs b/pbs-config/src/datastore.rs
index 12071a9f..dc56e0c3 100644
--- a/pbs-config/src/datastore.rs
+++ b/pbs-config/src/datastore.rs
@@ -2,7 +2,7 @@ use anyhow::{Error};
 use lazy_static::lazy_static;
 use std::collections::HashMap;
 
-use proxmox_schema::{ApiType, Schema};
+use proxmox_schema::ApiType;
 use proxmox_section_config::{SectionConfig, SectionConfigData, SectionConfigPlugin};
 
 use pbs_api_types::{DataStoreConfig, DATASTORE_SCHEMA};
@@ -14,12 +14,10 @@ lazy_static! {
 }
 
 fn init() -> SectionConfig {
-    let obj_schema = match DataStoreConfig::API_SCHEMA {
-        Schema::Object(ref obj_schema) => obj_schema,
-        _ => unreachable!(),
-    };
-
-    let plugin = SectionConfigPlugin::new("datastore".to_string(), Some(String::from("name")), obj_schema);
+    const OBJ_SCHEMA: &proxmox_schema::ObjectSchema =
+        DataStoreConfig::API_SCHEMA.unwrap_object_schema();
+    let plugin =
+        SectionConfigPlugin::new("datastore".to_string(), Some(String::from("name")), OBJ_SCHEMA);
     let mut config = SectionConfig::new(&DATASTORE_SCHEMA);
     config.register_plugin(plugin);
 
diff --git a/pbs-config/src/domains.rs b/pbs-config/src/domains.rs
index 90a83bc6..12a58048 100644
--- a/pbs-config/src/domains.rs
+++ b/pbs-config/src/domains.rs
@@ -3,7 +3,7 @@ use std::collections::HashMap;
 use anyhow::{Error};
 use lazy_static::lazy_static;
 
-use proxmox_schema::{ApiType, Schema};
+use proxmox_schema::ApiType;
 use proxmox_section_config::{SectionConfig, SectionConfigData, SectionConfigPlugin};
 
 use pbs_api_types::{OpenIdRealmConfig, REALM_ID_SCHEMA};
@@ -15,12 +15,10 @@ lazy_static! {
 
 
 fn init() -> SectionConfig {
-    let obj_schema = match OpenIdRealmConfig::API_SCHEMA {
-        Schema::Object(ref obj_schema) => obj_schema,
-        _ => unreachable!(),
-    };
-
-    let plugin = SectionConfigPlugin::new("openid".to_string(), Some(String::from("realm")), obj_schema);
+    const OBJ_SCHEMA: &proxmox_schema::ObjectSchema =
+        OpenIdRealmConfig::API_SCHEMA.unwrap_object_schema();
+    let plugin =
+        SectionConfigPlugin::new("openid".to_string(), Some(String::from("realm")), OBJ_SCHEMA);
     let mut config = SectionConfig::new(&REALM_ID_SCHEMA);
     config.register_plugin(plugin);
 
diff --git a/pbs-config/src/drive.rs b/pbs-config/src/drive.rs
index 13be8841..66aa3c78 100644
--- a/pbs-config/src/drive.rs
+++ b/pbs-config/src/drive.rs
@@ -35,25 +35,18 @@ lazy_static! {
 fn init() -> SectionConfig {
     let mut config = SectionConfig::new(&DRIVE_NAME_SCHEMA);
 
-    let obj_schema = match VirtualTapeDrive::API_SCHEMA {
-        Schema::Object(ref obj_schema) => obj_schema,
-        _ => unreachable!(),
-    };
-    let plugin = SectionConfigPlugin::new("virtual".to_string(), Some("name".to_string()), obj_schema);
+    const VIRT_SCHEMA: &ObjectSchema = VirtualTapeDrive::API_SCHEMA.unwrap_object_schema();
+    let plugin =
+        SectionConfigPlugin::new("virtual".to_string(), Some("name".to_string()), VIRT_SCHEMA);
     config.register_plugin(plugin);
 
-    let obj_schema = match LtoTapeDrive::API_SCHEMA {
-        Schema::Object(ref obj_schema) => obj_schema,
-        _ => unreachable!(),
-    };
-    let plugin = SectionConfigPlugin::new("lto".to_string(), Some("name".to_string()), obj_schema);
+    const LTO_SCHEMA: &ObjectSchema = LtoTapeDrive::API_SCHEMA.unwrap_object_schema();
+    let plugin = SectionConfigPlugin::new("lto".to_string(), Some("name".to_string()), LTO_SCHEMA);
     config.register_plugin(plugin);
 
-    let obj_schema = match ScsiTapeChanger::API_SCHEMA {
-        Schema::Object(ref obj_schema) => obj_schema,
-        _ => unreachable!(),
-    };
-    let plugin = SectionConfigPlugin::new("changer".to_string(), Some("name".to_string()), obj_schema);
+    const CHANGER_SCHEMA: &ObjectSchema = ScsiTapeChanger::API_SCHEMA.unwrap_object_schema();
+    let plugin =
+        SectionConfigPlugin::new("changer".to_string(), Some("name".to_string()), CHANGER_SCHEMA);
     config.register_plugin(plugin);
     config
 }
diff --git a/pbs-config/src/media_pool.rs b/pbs-config/src/media_pool.rs
index 35a2924e..40403d27 100644
--- a/pbs-config/src/media_pool.rs
+++ b/pbs-config/src/media_pool.rs
@@ -26,11 +26,8 @@ lazy_static! {
 fn init() -> SectionConfig {
     let mut config = SectionConfig::new(&MEDIA_POOL_NAME_SCHEMA);
 
-    let obj_schema = match MediaPoolConfig::API_SCHEMA {
-        Schema::Object(ref obj_schema) => obj_schema,
-        _ => unreachable!(),
-    };
-    let plugin = SectionConfigPlugin::new("pool".to_string(), Some("name".to_string()), obj_schema);
+    const OBJ_SCHEMA: &ObjectSchema = MediaPoolConfig::API_SCHEMA.unwrap_object_schema();
+    let plugin = SectionConfigPlugin::new("pool".to_string(), Some("name".to_string()), OBJ_SCHEMA);
     config.register_plugin(plugin);
 
     config
diff --git a/pbs-config/src/remote.rs b/pbs-config/src/remote.rs
index 921410e2..81da3574 100644
--- a/pbs-config/src/remote.rs
+++ b/pbs-config/src/remote.rs
@@ -15,12 +15,9 @@ lazy_static! {
 }
 
 fn init() -> SectionConfig {
-    let obj_schema = match Remote::API_SCHEMA {
-        Schema::AllOf(ref allof_schema) => allof_schema,
-        _ => unreachable!(),
-    };
-
-    let plugin = SectionConfigPlugin::new("remote".to_string(), Some("name".to_string()), obj_schema);
+    const OBJ_SCHEMA: &proxmox_schema::AllOfSchema = Remote::API_SCHEMA.unwrap_all_of_schema();
+    let plugin =
+        SectionConfigPlugin::new("remote".to_string(), Some("name".to_string()), OBJ_SCHEMA);
     let mut config = SectionConfig::new(&REMOTE_ID_SCHEMA);
     config.register_plugin(plugin);
 
diff --git a/pbs-config/src/sync.rs b/pbs-config/src/sync.rs
index f515613f..a9e137b6 100644
--- a/pbs-config/src/sync.rs
+++ b/pbs-config/src/sync.rs
@@ -3,7 +3,7 @@ use std::collections::HashMap;
 use anyhow::Error;
 use lazy_static::lazy_static;
 
-use proxmox_schema::{ApiType, Schema};
+use proxmox_schema::ApiType;
 use proxmox_section_config::{SectionConfig, SectionConfigData, SectionConfigPlugin};
 
 use pbs_api_types::{JOB_ID_SCHEMA, SyncJobConfig};
@@ -16,12 +16,9 @@ lazy_static! {
 
 
 fn init() -> SectionConfig {
-    let obj_schema = match SyncJobConfig::API_SCHEMA {
-        Schema::AllOf(ref allof_schema) => allof_schema,
-        _ => unreachable!(),
-    };
-
-    let plugin = SectionConfigPlugin::new("sync".to_string(), Some(String::from("id")), obj_schema);
+    const OBJ_SCHEMA: &proxmox_schema::AllOfSchema =
+        SyncJobConfig::API_SCHEMA.unwrap_all_of_schema();
+    let plugin = SectionConfigPlugin::new("sync".to_string(), Some(String::from("id")), OBJ_SCHEMA);
     let mut config = SectionConfig::new(&JOB_ID_SCHEMA);
     config.register_plugin(plugin);
 
diff --git a/pbs-config/src/tape_job.rs b/pbs-config/src/tape_job.rs
index 992d4382..f208f7a1 100644
--- a/pbs-config/src/tape_job.rs
+++ b/pbs-config/src/tape_job.rs
@@ -2,7 +2,7 @@ use anyhow::{Error};
 use lazy_static::lazy_static;
 use std::collections::HashMap;
 
-use proxmox_schema::{Schema, ApiType};
+use proxmox_schema::ApiType;
 use proxmox_section_config::{SectionConfig, SectionConfigData, SectionConfigPlugin};
 
 use pbs_api_types::{TapeBackupJobConfig, JOB_ID_SCHEMA};
@@ -14,12 +14,10 @@ lazy_static! {
 }
 
 fn init() -> SectionConfig {
-    let obj_schema = match TapeBackupJobConfig::API_SCHEMA {
-        Schema::AllOf(ref allof_schema) => allof_schema,
-        _ => unreachable!(),
-    };
-
-    let plugin = SectionConfigPlugin::new("backup".to_string(), Some(String::from("id")), obj_schema);
+    const OBJ_SCHEMA: &proxmox_schema::AllOfSchema =
+        TapeBackupJobConfig::API_SCHEMA.unwrap_all_of_schema();
+    let plugin =
+        SectionConfigPlugin::new("backup".to_string(), Some(String::from("id")), OBJ_SCHEMA);
     let mut config = SectionConfig::new(&JOB_ID_SCHEMA);
     config.register_plugin(plugin);
 
diff --git a/pbs-config/src/traffic_control.rs b/pbs-config/src/traffic_control.rs
index 860d0fb7..98b6a544 100644
--- a/pbs-config/src/traffic_control.rs
+++ b/pbs-config/src/traffic_control.rs
@@ -4,7 +4,7 @@ use std::collections::HashMap;
 use anyhow::Error;
 use lazy_static::lazy_static;
 
-use proxmox_schema::{ApiType, Schema};
+use proxmox_schema::ApiType;
 
 use pbs_api_types::{TrafficControlRule, TRAFFIC_CONTROL_ID_SCHEMA};
 
@@ -21,11 +21,9 @@ lazy_static! {
 fn init() -> SectionConfig {
     let mut config = SectionConfig::new(&TRAFFIC_CONTROL_ID_SCHEMA);
 
-    let obj_schema = match TrafficControlRule::API_SCHEMA {
-        Schema::AllOf(ref allof_schema) => allof_schema,
-        _ => unreachable!(),
-    };
-    let plugin = SectionConfigPlugin::new("rule".to_string(), Some("name".to_string()), obj_schema);
+    const OBJ_SCHEMA: &proxmox_schema::AllOfSchema =
+        TrafficControlRule::API_SCHEMA.unwrap_all_of_schema();
+    let plugin = SectionConfigPlugin::new("rule".to_string(), Some("name".to_string()), OBJ_SCHEMA);
     config.register_plugin(plugin);
 
     config
diff --git a/pbs-config/src/user.rs b/pbs-config/src/user.rs
index f62d45db..a69865a9 100644
--- a/pbs-config/src/user.rs
+++ b/pbs-config/src/user.rs
@@ -22,18 +22,14 @@ lazy_static! {
 fn init() -> SectionConfig {
     let mut config = SectionConfig::new(&Authid::API_SCHEMA);
 
-    let user_schema = match User::API_SCHEMA {
-        Schema::Object(ref user_schema) => user_schema,
-        _ => unreachable!(),
-    };
-    let user_plugin = SectionConfigPlugin::new("user".to_string(), Some("userid".to_string()), user_schema);
+    const USER_SCHEMA: &ObjectSchema = User::API_SCHEMA.unwrap_object_schema();
+    let user_plugin =
+        SectionConfigPlugin::new("user".to_string(), Some("userid".to_string()), USER_SCHEMA);
     config.register_plugin(user_plugin);
 
-    let token_schema = match ApiToken::API_SCHEMA {
-        Schema::Object(ref token_schema) => token_schema,
-        _ => unreachable!(),
-    };
-    let token_plugin = SectionConfigPlugin::new("token".to_string(), Some("tokenid".to_string()), token_schema);
+    const TOKEN_SCHEMA: &ObjectSchema = ApiToken::API_SCHEMA.unwrap_object_schema();
+    let token_plugin =
+        SectionConfigPlugin::new("token".to_string(), Some("tokenid".to_string()), TOKEN_SCHEMA);
     config.register_plugin(token_plugin);
 
     config
diff --git a/pbs-config/src/verify.rs b/pbs-config/src/verify.rs
index b6c70caa..efe22996 100644
--- a/pbs-config/src/verify.rs
+++ b/pbs-config/src/verify.rs
@@ -15,12 +15,10 @@ lazy_static! {
 }
 
 fn init() -> SectionConfig {
-    let obj_schema = match VerificationJobConfig::API_SCHEMA {
-        Schema::Object(ref obj_schema) => obj_schema,
-        _ => unreachable!(),
-    };
-
-    let plugin = SectionConfigPlugin::new("verification".to_string(), Some(String::from("id")), obj_schema);
+    const OBJ_SCHEMA: &proxmox_schema::ObjectSchema =
+        VerificationJobConfig::API_SCHEMA.unwrap_object_schema();
+    let plugin =
+        SectionConfigPlugin::new("verification".to_string(), Some(String::from("id")), OBJ_SCHEMA);
     let mut config = SectionConfig::new(&JOB_ID_SCHEMA);
     config.register_plugin(plugin);
 
diff --git a/src/config/acme/plugin.rs b/src/config/acme/plugin.rs
index 5decc154..1788267f 100644
--- a/src/config/acme/plugin.rs
+++ b/src/config/acme/plugin.rs
@@ -107,25 +107,21 @@ impl DnsPlugin {
 fn init() -> SectionConfig {
     let mut config = SectionConfig::new(&PLUGIN_ID_SCHEMA);
 
-    let standalone_schema = match &StandalonePlugin::API_SCHEMA {
-        Schema::Object(schema) => schema,
-        _ => unreachable!(),
-    };
+    const STANDALONE_SCHEMA: &proxmox_schema::ObjectSchema =
+        StandalonePlugin::API_SCHEMA.unwrap_object_schema();
     let standalone_plugin = SectionConfigPlugin::new(
         "standalone".to_string(),
         Some("id".to_string()),
-        standalone_schema,
+        STANDALONE_SCHEMA,
     );
     config.register_plugin(standalone_plugin);
 
-    let dns_challenge_schema = match DnsPlugin::API_SCHEMA {
-        Schema::AllOf(ref schema) => schema,
-        _ => unreachable!(),
-    };
+    const DNS_CHALLENGE_SCHEMA: &proxmox_schema::AllOfSchema =
+        DnsPlugin::API_SCHEMA.unwrap_all_of_schema();
     let dns_challenge_plugin = SectionConfigPlugin::new(
         "dns".to_string(),
         Some("id".to_string()),
-        dns_challenge_schema,
+        DNS_CHALLENGE_SCHEMA,
     );
     config.register_plugin(dns_challenge_plugin);
 
diff --git a/src/tools/systemd/config.rs b/src/tools/systemd/config.rs
index 95c1a942..8dae1bf5 100644
--- a/src/tools/systemd/config.rs
+++ b/src/tools/systemd/config.rs
@@ -15,31 +15,25 @@ lazy_static! {
     pub static ref MOUNT_CONFIG: SectionConfig = init_mount();
 }
 
+fn register_unit_section(config: &mut SectionConfig) {
+    const UNIT_SCHEMA: &ObjectSchema = SystemdUnitSection::API_SCHEMA.unwrap_object_schema();
+    config.register_plugin(SectionConfigPlugin::new("Unit".to_string(), None, UNIT_SCHEMA));
+}
+
+fn register_install_section(config: &mut SectionConfig) {
+    const INSTALL_SCHEMA: &ObjectSchema = SystemdInstallSection::API_SCHEMA.unwrap_object_schema();
+    config.register_plugin(SectionConfigPlugin::new("Install".to_string(), None, INSTALL_SCHEMA));
+}
+
 fn init_service() -> SectionConfig {
 
     let mut config = SectionConfig::with_systemd_syntax(&SYSTEMD_SECTION_NAME_SCHEMA);
 
-    match SystemdUnitSection::API_SCHEMA {
-        Schema::Object(ref obj_schema) =>  {
-            let plugin = SectionConfigPlugin::new("Unit".to_string(), None, obj_schema);
-            config.register_plugin(plugin);
-        }
-        _ => unreachable!(),
-    };
-    match SystemdInstallSection::API_SCHEMA {
-        Schema::Object(ref obj_schema) =>  {
-            let plugin = SectionConfigPlugin::new("Install".to_string(), None, obj_schema);
-            config.register_plugin(plugin);
-        }
-        _ => unreachable!(),
-    };
-    match SystemdServiceSection::API_SCHEMA {
-        Schema::Object(ref obj_schema) =>  {
-            let plugin = SectionConfigPlugin::new("Service".to_string(), None, obj_schema);
-            config.register_plugin(plugin);
-        }
-        _ => unreachable!(),
-    };
+    register_unit_section(&mut config);
+    register_install_section(&mut config);
+
+    const SERVICE_SCHEMA: &ObjectSchema = SystemdServiceSection::API_SCHEMA.unwrap_object_schema();
+    config.register_plugin(SectionConfigPlugin::new("Service".to_string(), None, SERVICE_SCHEMA));
 
     config
 }
@@ -48,27 +42,11 @@ fn init_timer() -> SectionConfig {
 
     let mut config = SectionConfig::with_systemd_syntax(&SYSTEMD_SECTION_NAME_SCHEMA);
 
-    match SystemdUnitSection::API_SCHEMA {
-        Schema::Object(ref obj_schema) =>  {
-            let plugin = SectionConfigPlugin::new("Unit".to_string(), None, obj_schema);
-            config.register_plugin(plugin);
-        }
-        _ => unreachable!(),
-    };
-    match SystemdInstallSection::API_SCHEMA {
-        Schema::Object(ref obj_schema) =>  {
-            let plugin = SectionConfigPlugin::new("Install".to_string(), None, obj_schema);
-            config.register_plugin(plugin);
-        }
-        _ => unreachable!(),
-    };
-    match SystemdTimerSection::API_SCHEMA {
-        Schema::Object(ref obj_schema) =>  {
-            let plugin = SectionConfigPlugin::new("Timer".to_string(), None, obj_schema);
-            config.register_plugin(plugin);
-        }
-        _ => unreachable!(),
-    };
+    register_unit_section(&mut config);
+    register_install_section(&mut config);
+
+    const TIMER_SCHEMA: &ObjectSchema = SystemdTimerSection::API_SCHEMA.unwrap_object_schema();
+    config.register_plugin(SectionConfigPlugin::new("Timer".to_string(), None, TIMER_SCHEMA));
 
     config
 }
@@ -77,27 +55,11 @@ fn init_mount() -> SectionConfig {
 
     let mut config = SectionConfig::with_systemd_syntax(&SYSTEMD_SECTION_NAME_SCHEMA);
 
-    match SystemdUnitSection::API_SCHEMA {
-        Schema::Object(ref obj_schema) =>  {
-            let plugin = SectionConfigPlugin::new("Unit".to_string(), None, obj_schema);
-            config.register_plugin(plugin);
-        }
-        _ => unreachable!(),
-    };
-    match SystemdInstallSection::API_SCHEMA {
-        Schema::Object(ref obj_schema) =>  {
-            let plugin = SectionConfigPlugin::new("Install".to_string(), None, obj_schema);
-            config.register_plugin(plugin);
-        }
-        _ => unreachable!(),
-    };
-    match SystemdMountSection::API_SCHEMA {
-        Schema::Object(ref obj_schema) =>  {
-            let plugin = SectionConfigPlugin::new("Mount".to_string(), None, obj_schema);
-            config.register_plugin(plugin);
-        }
-        _ => unreachable!(),
-    };
+    register_unit_section(&mut config);
+    register_install_section(&mut config);
+
+    const MOUNT_SCHEMA: &ObjectSchema = SystemdMountSection::API_SCHEMA.unwrap_object_schema();
+    config.register_plugin(SectionConfigPlugin::new("Mount".to_string(), None, MOUNT_SCHEMA));
 
     config
 }
-- 
2.30.2





^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [pbs-devel] [PATCH proxmox] schema: add const fn unwrap_*_schema/format methods
  2022-02-22  8:47 [pbs-devel] [PATCH proxmox] schema: add const fn unwrap_*_schema/format methods Wolfgang Bumiller
  2022-02-22  8:47 ` [pbs-devel] [PATCH backup] constify schema usage and dedup some code Wolfgang Bumiller
@ 2022-02-23  8:31 ` Thomas Lamprecht
  1 sibling, 0 replies; 3+ messages in thread
From: Thomas Lamprecht @ 2022-02-23  8:31 UTC (permalink / raw)
  To: Proxmox Backup Server development discussion, Wolfgang Bumiller

On 22.02.22 09:47, Wolfgang Bumiller wrote:
> 'unwrap_' because they will panic and as `const fn` since
> panic in const fn is now possible
> 
> Note that const evaluation will only be triggered when
> actually used in const context, so to ensure *compile time*
> checks, use something like this:
> 
>     const FOO_SCHEMA: &AllOfSchema =
>         SomeType::API_SCHEMA.unwrap_all_of_schema();
>     then_use(FOO_SCHEMA);
> 
> or to use the list of enum values of an enum string type
> with compile time checks:
> 
>     const LIST: &'static [EnumEntry] =
>         AnEnumStringType::API_SCHEMA
>             .unwrap_string_schema()
>             .unwrap_format()
>             .unwrap_enum_format();
>     for values in LIST {
>         ...
>     }
> 
> Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
> ---
> While schemas are usually unlikely to change type or lose properties
> such as enum lists, for `ObjectSchema` and `AllOfSchema` this may
> actually allow catching future issues at build-time...
> 
> If we want to do this, I'd prepare a similar patch set for all the
> `ApiHandler::...` value extractions we do in the CLI in pbs (just look
> at the output of `egrep -B1 -nr 'unreachable' ./src ./*/src` in pbs ;-) )
> 

IMO the usage gets nicer, lots of removal of unreachable!(), and even if
not used correctly (without const) we're as good as now; so can only win.

If there's no objection from others I'd say: go for it.




^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-02-23  8:31 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-22  8:47 [pbs-devel] [PATCH proxmox] schema: add const fn unwrap_*_schema/format methods Wolfgang Bumiller
2022-02-22  8:47 ` [pbs-devel] [PATCH backup] constify schema usage and dedup some code Wolfgang Bumiller
2022-02-23  8:31 ` [pbs-devel] [PATCH proxmox] schema: add const fn unwrap_*_schema/format methods Thomas Lamprecht

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