all lists on 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal