* [pbs-devel] [RFC backup 1/2] implement an api_string_type helper macro
@ 2021-05-04 10:19 Wolfgang Bumiller
2021-05-04 10:19 ` [pbs-devel] [RFC backup 2/2] use api_string_type macro Wolfgang Bumiller
2021-05-04 11:17 ` [pbs-devel] [RFC backup 1/2] implement an api_string_type helper macro Dietmar Maurer
0 siblings, 2 replies; 4+ messages in thread
From: Wolfgang Bumiller @ 2021-05-04 10:19 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
src/tools.rs | 3 +
src/tools/api_string_type.rs | 105 +++++++++++++++++++++++++++++++++++
2 files changed, 108 insertions(+)
create mode 100644 src/tools/api_string_type.rs
diff --git a/src/tools.rs b/src/tools.rs
index c58569a6..98597c29 100644
--- a/src/tools.rs
+++ b/src/tools.rs
@@ -18,6 +18,9 @@ use percent_encoding::{utf8_percent_encode, AsciiSet};
pub use proxmox::tools::fd::Fd;
use proxmox::tools::fs::{create_path, CreateOptions};
+#[macro_use]
+pub mod api_string_type;
+
pub mod acl;
pub mod apt;
pub mod async_io;
diff --git a/src/tools/api_string_type.rs b/src/tools/api_string_type.rs
new file mode 100644
index 00000000..122fcbed
--- /dev/null
+++ b/src/tools/api_string_type.rs
@@ -0,0 +1,105 @@
+/// Helper macro to generate a simple string type wrapper.
+///
+/// This is meant to be used with an API-type tuple struct containing a single `String` like this:
+///
+/// ```ignore
+/// api_string_type! {
+/// #[api(format: &PROXMOX_SAFE_ID_FORMAT)]
+/// /// ACME account name.
+/// #[derive(Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
+/// #[serde(transparent)]
+/// pub struct AccountName(String);
+/// }
+/// ```
+///
+/// This will automatically implements:
+/// * `Display` as a pass-through to `String`'s `Display`
+/// * `Debug` as a pass-through to `String`'s `Debug`
+/// * `Deref`
+/// * `DerefMut`
+/// * `AsRef<str>`
+/// * `fn into_string(self) -> String`
+/// * `fn as_str(&self) -> &str`
+/// * `fn from_string(inner: String) -> Result<Self, anyhow::Error>` using
+/// `StringSchema::check_constraints`.
+/// * `unsafe fn from_string_unchecked(inner: String) -> Self`
+macro_rules! api_string_type {
+ (
+ $(#[$doc:meta])*
+ $vis:vis struct $name:ident(String);
+ ) => (
+ $(#[$doc])*
+ $vis struct $name(String);
+
+ impl ::std::ops::Deref for $name {
+ type Target = str;
+
+ #[inline]
+ fn deref(&self) -> &str {
+ &self.0
+ }
+ }
+
+ impl ::std::ops::DerefMut for $name {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut str {
+ &mut self.0
+ }
+ }
+
+ impl AsRef<str> for $name {
+ #[inline]
+ fn as_ref(&self) -> &str {
+ self.0.as_ref()
+ }
+ }
+
+ impl $name {
+ /// Get the contained string.
+ pub fn into_string(self) -> String {
+ self.0
+ }
+
+ /// Get the string as slice.
+ pub fn as_str(&self) -> &str {
+ self.0.as_str()
+ }
+
+ /// Create an instance directly from a `String`.
+ ///
+ /// # Safety
+ ///
+ /// It is the caller's job to have validated the contents.
+ /// While there are no memory safety issues, a wrong string can cause API calls to
+ /// fail parameter validation.
+ pub unsafe fn from_string_unchecked(name: String) -> Self {
+ Self(name)
+ }
+
+ /// Create an instance directly from a `String`, validating it using the API schema's
+ /// [`check_constraints`](::proxmox::api::schema::StringSchema::check_constraints())
+ /// method.
+ pub fn from_string(inner: String) -> Result<Self, ::anyhow::Error> {
+ match &Self::API_SCHEMA {
+ ::proxmox::api::schema::Schema::String(s) => s.check_constraints(&inner)?,
+ _ => unreachable!(),
+ }
+ Ok(Self(inner))
+ }
+ }
+
+ impl ::std::fmt::Debug for $name {
+ #[inline]
+ fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+ ::std::fmt::Debug::fmt(&self.0, f)
+ }
+ }
+
+ impl ::std::fmt::Display for $name {
+ #[inline]
+ fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+ ::std::fmt::Display::fmt(&self.0, f)
+ }
+ }
+ );
+}
--
2.20.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [pbs-devel] [RFC backup 2/2] use api_string_type macro
2021-05-04 10:19 [pbs-devel] [RFC backup 1/2] implement an api_string_type helper macro Wolfgang Bumiller
@ 2021-05-04 10:19 ` Wolfgang Bumiller
2021-05-05 6:33 ` [pbs-devel] applied: " Dietmar Maurer
2021-05-04 11:17 ` [pbs-devel] [RFC backup 1/2] implement an api_string_type helper macro Dietmar Maurer
1 sibling, 1 reply; 4+ messages in thread
From: Wolfgang Bumiller @ 2021-05-04 10:19 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
src/api2/types/acme.rs | 68 ++++--------------------------------------
1 file changed, 6 insertions(+), 62 deletions(-)
diff --git a/src/api2/types/acme.rs b/src/api2/types/acme.rs
index cc5df322..f66a0801 100644
--- a/src/api2/types/acme.rs
+++ b/src/api2/types/acme.rs
@@ -1,6 +1,3 @@
-use std::fmt;
-
-use anyhow::Error;
use serde::{Deserialize, Serialize};
use proxmox::api::{api, schema::{Schema, StringSchema, ApiStringFormat}};
@@ -64,63 +61,10 @@ pub struct KnownAcmeDirectory {
pub url: &'static str,
}
-#[api(format: &PROXMOX_SAFE_ID_FORMAT)]
-/// ACME account name.
-#[derive(Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
-#[serde(transparent)]
-pub struct AcmeAccountName(String);
-
-impl AcmeAccountName {
- pub fn into_string(self) -> String {
- self.0
- }
-
- pub fn from_string(name: String) -> Result<Self, Error> {
- match &Self::API_SCHEMA {
- Schema::String(s) => s.check_constraints(&name)?,
- _ => unreachable!(),
- }
- Ok(Self(name))
- }
-
- pub unsafe fn from_string_unchecked(name: String) -> Self {
- Self(name)
- }
-}
-
-impl std::ops::Deref for AcmeAccountName {
- type Target = str;
-
- #[inline]
- fn deref(&self) -> &str {
- &self.0
- }
-}
-
-impl std::ops::DerefMut for AcmeAccountName {
- #[inline]
- fn deref_mut(&mut self) -> &mut str {
- &mut self.0
- }
-}
-
-impl AsRef<str> for AcmeAccountName {
- #[inline]
- fn as_ref(&self) -> &str {
- self.0.as_ref()
- }
-}
-
-impl fmt::Debug for AcmeAccountName {
- #[inline]
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Debug::fmt(&self.0, f)
- }
-}
-
-impl fmt::Display for AcmeAccountName {
- #[inline]
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Display::fmt(&self.0, f)
- }
+api_string_type! {
+ #[api(format: &PROXMOX_SAFE_ID_FORMAT)]
+ /// ACME account name.
+ #[derive(Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
+ #[serde(transparent)]
+ pub struct AcmeAccountName(String);
}
--
2.20.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [pbs-devel] [RFC backup 1/2] implement an api_string_type helper macro
2021-05-04 10:19 [pbs-devel] [RFC backup 1/2] implement an api_string_type helper macro Wolfgang Bumiller
2021-05-04 10:19 ` [pbs-devel] [RFC backup 2/2] use api_string_type macro Wolfgang Bumiller
@ 2021-05-04 11:17 ` Dietmar Maurer
1 sibling, 0 replies; 4+ messages in thread
From: Dietmar Maurer @ 2021-05-04 11:17 UTC (permalink / raw)
To: Proxmox Backup Server development discussion, Wolfgang Bumiller
two suggestions:
1.) Move the code to the proxmox crate
2.) Do not implement Debug (can be derived)
On 5/4/21 12:19 PM, Wolfgang Bumiller wrote:
> Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
> ---
> src/tools.rs | 3 +
> src/tools/api_string_type.rs | 105 +++++++++++++++++++++++++++++++++++
> 2 files changed, 108 insertions(+)
> create mode 100644 src/tools/api_string_type.rs
>
> diff --git a/src/tools.rs b/src/tools.rs
> index c58569a6..98597c29 100644
> --- a/src/tools.rs
> +++ b/src/tools.rs
> @@ -18,6 +18,9 @@ use percent_encoding::{utf8_percent_encode, AsciiSet};
> pub use proxmox::tools::fd::Fd;
> use proxmox::tools::fs::{create_path, CreateOptions};
>
> +#[macro_use]
> +pub mod api_string_type;
> +
> pub mod acl;
> pub mod apt;
> pub mod async_io;
> diff --git a/src/tools/api_string_type.rs b/src/tools/api_string_type.rs
> new file mode 100644
> index 00000000..122fcbed
> --- /dev/null
> +++ b/src/tools/api_string_type.rs
> @@ -0,0 +1,105 @@
> +/// Helper macro to generate a simple string type wrapper.
> +///
> +/// This is meant to be used with an API-type tuple struct containing a single `String` like this:
> +///
> +/// ```ignore
> +/// api_string_type! {
> +/// #[api(format: &PROXMOX_SAFE_ID_FORMAT)]
> +/// /// ACME account name.
> +/// #[derive(Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
> +/// #[serde(transparent)]
> +/// pub struct AccountName(String);
> +/// }
> +/// ```
> +///
> +/// This will automatically implements:
> +/// * `Display` as a pass-through to `String`'s `Display`
> +/// * `Debug` as a pass-through to `String`'s `Debug`
> +/// * `Deref`
> +/// * `DerefMut`
> +/// * `AsRef<str>`
> +/// * `fn into_string(self) -> String`
> +/// * `fn as_str(&self) -> &str`
> +/// * `fn from_string(inner: String) -> Result<Self, anyhow::Error>` using
> +/// `StringSchema::check_constraints`.
> +/// * `unsafe fn from_string_unchecked(inner: String) -> Self`
> +macro_rules! api_string_type {
> + (
> + $(#[$doc:meta])*
> + $vis:vis struct $name:ident(String);
> + ) => (
> + $(#[$doc])*
> + $vis struct $name(String);
> +
> + impl ::std::ops::Deref for $name {
> + type Target = str;
> +
> + #[inline]
> + fn deref(&self) -> &str {
> + &self.0
> + }
> + }
> +
> + impl ::std::ops::DerefMut for $name {
> + #[inline]
> + fn deref_mut(&mut self) -> &mut str {
> + &mut self.0
> + }
> + }
> +
> + impl AsRef<str> for $name {
> + #[inline]
> + fn as_ref(&self) -> &str {
> + self.0.as_ref()
> + }
> + }
> +
> + impl $name {
> + /// Get the contained string.
> + pub fn into_string(self) -> String {
> + self.0
> + }
> +
> + /// Get the string as slice.
> + pub fn as_str(&self) -> &str {
> + self.0.as_str()
> + }
> +
> + /// Create an instance directly from a `String`.
> + ///
> + /// # Safety
> + ///
> + /// It is the caller's job to have validated the contents.
> + /// While there are no memory safety issues, a wrong string can cause API calls to
> + /// fail parameter validation.
> + pub unsafe fn from_string_unchecked(name: String) -> Self {
> + Self(name)
> + }
> +
> + /// Create an instance directly from a `String`, validating it using the API schema's
> + /// [`check_constraints`](::proxmox::api::schema::StringSchema::check_constraints())
> + /// method.
> + pub fn from_string(inner: String) -> Result<Self, ::anyhow::Error> {
> + match &Self::API_SCHEMA {
> + ::proxmox::api::schema::Schema::String(s) => s.check_constraints(&inner)?,
> + _ => unreachable!(),
> + }
> + Ok(Self(inner))
> + }
> + }
> +
> + impl ::std::fmt::Debug for $name {
> + #[inline]
> + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
> + ::std::fmt::Debug::fmt(&self.0, f)
> + }
> + }
> +
> + impl ::std::fmt::Display for $name {
> + #[inline]
> + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
> + ::std::fmt::Display::fmt(&self.0, f)
> + }
> + }
> + );
> +}
^ permalink raw reply [flat|nested] 4+ messages in thread
* [pbs-devel] applied: [RFC backup 2/2] use api_string_type macro
2021-05-04 10:19 ` [pbs-devel] [RFC backup 2/2] use api_string_type macro Wolfgang Bumiller
@ 2021-05-05 6:33 ` Dietmar Maurer
0 siblings, 0 replies; 4+ messages in thread
From: Dietmar Maurer @ 2021-05-05 6:33 UTC (permalink / raw)
To: Proxmox Backup Server development discussion, Wolfgang Bumiller
applied, with minor modifications
On 5/4/21 12:19 PM, Wolfgang Bumiller wrote:
> Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
> ---
> src/api2/types/acme.rs | 68 ++++--------------------------------------
> 1 file changed, 6 insertions(+), 62 deletions(-)
>
> diff --git a/src/api2/types/acme.rs b/src/api2/types/acme.rs
> index cc5df322..f66a0801 100644
> --- a/src/api2/types/acme.rs
> +++ b/src/api2/types/acme.rs
> @@ -1,6 +1,3 @@
> -use std::fmt;
> -
> -use anyhow::Error;
> use serde::{Deserialize, Serialize};
>
> use proxmox::api::{api, schema::{Schema, StringSchema, ApiStringFormat}};
> @@ -64,63 +61,10 @@ pub struct KnownAcmeDirectory {
> pub url: &'static str,
> }
>
> -#[api(format: &PROXMOX_SAFE_ID_FORMAT)]
> -/// ACME account name.
> -#[derive(Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
> -#[serde(transparent)]
> -pub struct AcmeAccountName(String);
> -
> -impl AcmeAccountName {
> - pub fn into_string(self) -> String {
> - self.0
> - }
> -
> - pub fn from_string(name: String) -> Result<Self, Error> {
> - match &Self::API_SCHEMA {
> - Schema::String(s) => s.check_constraints(&name)?,
> - _ => unreachable!(),
> - }
> - Ok(Self(name))
> - }
> -
> - pub unsafe fn from_string_unchecked(name: String) -> Self {
> - Self(name)
> - }
> -}
> -
> -impl std::ops::Deref for AcmeAccountName {
> - type Target = str;
> -
> - #[inline]
> - fn deref(&self) -> &str {
> - &self.0
> - }
> -}
> -
> -impl std::ops::DerefMut for AcmeAccountName {
> - #[inline]
> - fn deref_mut(&mut self) -> &mut str {
> - &mut self.0
> - }
> -}
> -
> -impl AsRef<str> for AcmeAccountName {
> - #[inline]
> - fn as_ref(&self) -> &str {
> - self.0.as_ref()
> - }
> -}
> -
> -impl fmt::Debug for AcmeAccountName {
> - #[inline]
> - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
> - fmt::Debug::fmt(&self.0, f)
> - }
> -}
> -
> -impl fmt::Display for AcmeAccountName {
> - #[inline]
> - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
> - fmt::Display::fmt(&self.0, f)
> - }
> +api_string_type! {
> + #[api(format: &PROXMOX_SAFE_ID_FORMAT)]
> + /// ACME account name.
> + #[derive(Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
> + #[serde(transparent)]
> + pub struct AcmeAccountName(String);
> }
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2021-05-05 6:33 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-04 10:19 [pbs-devel] [RFC backup 1/2] implement an api_string_type helper macro Wolfgang Bumiller
2021-05-04 10:19 ` [pbs-devel] [RFC backup 2/2] use api_string_type macro Wolfgang Bumiller
2021-05-05 6:33 ` [pbs-devel] applied: " Dietmar Maurer
2021-05-04 11:17 ` [pbs-devel] [RFC backup 1/2] implement an api_string_type helper macro Dietmar Maurer
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