diff --git a/wp_api/src/categories.rs b/wp_api/src/categories.rs index 507df37db..8ce0b041a 100644 --- a/wp_api/src/categories.rs +++ b/wp_api/src/categories.rs @@ -1,34 +1,17 @@ use crate::{ - WpApiParamOrder, impl_as_query_value_for_new_type, impl_as_query_value_from_to_string, + WpApiParamOrder, impl_as_query_value_from_to_string, posts::PostId, taxonomies::TaxonomyType, url_query::{ AppendUrlQueryPairs, FromUrlQueryPairs, QueryPairs, QueryPairsExtension, UrlQueryPairsMap, }, + wp_content_i64_id, }; use serde::{Deserialize, Serialize}; -use std::{num::ParseIntError, str::FromStr}; use strum_macros::IntoStaticStr; use wp_contextual::WpContextual; -impl_as_query_value_for_new_type!(CategoryId); -uniffi::custom_newtype!(CategoryId, i64); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub struct CategoryId(pub i64); - -impl FromStr for CategoryId { - type Err = ParseIntError; - - fn from_str(s: &str) -> Result { - s.parse().map(Self) - } -} - -impl std::fmt::Display for CategoryId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} +wp_content_i64_id!(CategoryId); #[derive( Debug, diff --git a/wp_api/src/comments.rs b/wp_api/src/comments.rs index 2a5a4715f..39d9c1100 100644 --- a/wp_api/src/comments.rs +++ b/wp_api/src/comments.rs @@ -1,14 +1,15 @@ use crate::{ AnyJson, UserAvatarSize, UserId, WpApiParamOrder, WpResponseString, date::WpGmtDateTime, - impl_as_query_value_for_new_type, impl_as_query_value_from_to_string, + impl_as_query_value_from_to_string, posts::PostId, url_query::{ AppendUrlQueryPairs, FromUrlQueryPairs, QueryPairs, QueryPairsExtension, UrlQueryPairsMap, }, + wp_content_i64_id, }; use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, num::ParseIntError, str::FromStr, sync::Arc}; +use std::{collections::HashMap, str::FromStr, sync::Arc}; use strum_macros::IntoStaticStr; use wp_contextual::WpContextual; @@ -37,24 +38,7 @@ pub enum WpApiParamCommentsOrderBy { impl_as_query_value_from_to_string!(WpApiParamCommentsOrderBy); -impl_as_query_value_for_new_type!(CommentId); -uniffi::custom_newtype!(CommentId, i64); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub struct CommentId(pub i64); - -impl FromStr for CommentId { - type Err = ParseIntError; - - fn from_str(s: &str) -> Result { - s.parse().map(Self) - } -} - -impl std::fmt::Display for CommentId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} +wp_content_i64_id!(CommentId); #[derive( Debug, diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index 182842af1..73af6024f 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -39,6 +39,7 @@ pub mod uuid; pub mod widget_types; pub mod widgets; pub mod wordpress_org; +pub mod wp_content_macros; pub mod wp_site_health_tests; mod uniffi_serde; diff --git a/wp_api/src/media.rs b/wp_api/src/media.rs index 3c346d031..5fc06c411 100644 --- a/wp_api/src/media.rs +++ b/wp_api/src/media.rs @@ -1,7 +1,7 @@ use crate::{ UserId, WpApiParamOrder, date::WpGmtDateTime, - impl_as_query_value_for_new_type, impl_as_query_value_from_to_string, + impl_as_query_value_from_to_string, posts::{ PostCommentStatus, PostId, PostPingStatus, PostStatus, WpApiParamPostsOrderBy, WpApiParamPostsSearchColumn, @@ -9,32 +9,16 @@ use crate::{ url_query::{ AppendUrlQueryPairs, FromUrlQueryPairs, QueryPairs, QueryPairsExtension, UrlQueryPairsMap, }, + wp_content_i64_id, }; use serde::{Deserialize, Serialize}; use serde_json::value::RawValue; +use std::collections::HashMap; use std::sync::Arc; -use std::{collections::HashMap, num::ParseIntError, str::FromStr}; use strum_macros::IntoStaticStr; use wp_contextual::WpContextual; -impl_as_query_value_for_new_type!(MediaId); -uniffi::custom_newtype!(MediaId, i64); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub struct MediaId(pub i64); - -impl FromStr for MediaId { - type Err = ParseIntError; - - fn from_str(s: &str) -> Result { - s.parse().map(Self) - } -} - -impl std::fmt::Display for MediaId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} +wp_content_i64_id!(MediaId); #[derive( Debug, diff --git a/wp_api/src/post_revisions.rs b/wp_api/src/post_revisions.rs index 60fac7fc8..327e21826 100644 --- a/wp_api/src/post_revisions.rs +++ b/wp_api/src/post_revisions.rs @@ -1,35 +1,18 @@ use crate::{ UserId, WpApiParamOrder, date::WpGmtDateTime, - impl_as_query_value_for_new_type, impl_as_query_value_from_to_string, + impl_as_query_value_from_to_string, posts::PostId, url_query::{ AppendUrlQueryPairs, FromUrlQueryPairs, QueryPairs, QueryPairsExtension, UrlQueryPairsMap, }, + wp_content_i64_id, }; use serde::{Deserialize, Serialize}; -use std::{num::ParseIntError, str::FromStr}; use strum_macros::IntoStaticStr; use wp_contextual::WpContextual; -impl_as_query_value_for_new_type!(PostRevisionId); -uniffi::custom_newtype!(PostRevisionId, i64); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub struct PostRevisionId(pub i64); - -impl FromStr for PostRevisionId { - type Err = ParseIntError; - - fn from_str(s: &str) -> Result { - s.parse().map(Self) - } -} - -impl std::fmt::Display for PostRevisionId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} +wp_content_i64_id!(PostRevisionId); #[derive( Debug, diff --git a/wp_api/src/posts.rs b/wp_api/src/posts.rs index 6883ae7a1..1b92628af 100644 --- a/wp_api/src/posts.rs +++ b/wp_api/src/posts.rs @@ -2,15 +2,15 @@ use crate::{ UserId, WpApiParamOrder, categories::CategoryId, date::WpGmtDateTime, - impl_as_query_value_for_new_type, impl_as_query_value_from_to_string, + impl_as_query_value_from_to_string, media::MediaId, tags::TagId, url_query::{ AppendUrlQueryPairs, FromUrlQueryPairs, QueryPairs, QueryPairsExtension, UrlQueryPairsMap, }, + wp_content_i64_id, }; use serde::{Deserialize, Serialize}; -use std::{num::ParseIntError, str::FromStr}; use strum_macros::IntoStaticStr; use wp_contextual::WpContextual; use wp_serde_helper::{deserialize_from_string_of_json_array, serialize_as_json_string}; @@ -448,24 +448,7 @@ pub struct PostUpdateParams { pub tags: Vec, } -impl_as_query_value_for_new_type!(PostId); -uniffi::custom_newtype!(PostId, i64); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub struct PostId(pub i64); - -impl FromStr for PostId { - type Err = ParseIntError; - - fn from_str(s: &str) -> Result { - s.parse().map(Self) - } -} - -impl std::fmt::Display for PostId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} +wp_content_i64_id!(PostId); #[derive(Debug, Serialize, Deserialize, uniffi::Record, WpContextual)] pub struct SparsePost { diff --git a/wp_api/src/prelude.rs b/wp_api/src/prelude.rs index 0b0bc3368..902a3d115 100644 --- a/wp_api/src/prelude.rs +++ b/wp_api/src/prelude.rs @@ -17,6 +17,7 @@ pub use crate::{ endpoint::{ApiUrlResolver, WpOrgSiteApiUrlResolver, media_endpoint::MediaUploadRequest}, }, uuid::{WpUuid, WpUuidParseError}, + wp_content_i64_id, wp_content_string_id, }; #[cfg(feature = "reqwest-request-executor")] diff --git a/wp_api/src/tags.rs b/wp_api/src/tags.rs index 0f7046177..866de7671 100644 --- a/wp_api/src/tags.rs +++ b/wp_api/src/tags.rs @@ -1,34 +1,17 @@ use crate::{ - WpApiParamOrder, impl_as_query_value_for_new_type, impl_as_query_value_from_to_string, + WpApiParamOrder, impl_as_query_value_from_to_string, posts::PostId, taxonomies::TaxonomyType, url_query::{ AppendUrlQueryPairs, FromUrlQueryPairs, QueryPairs, QueryPairsExtension, UrlQueryPairsMap, }, + wp_content_i64_id, }; use serde::{Deserialize, Serialize}; -use std::{num::ParseIntError, str::FromStr}; use strum_macros::IntoStaticStr; use wp_contextual::WpContextual; -impl_as_query_value_for_new_type!(TagId); -uniffi::custom_newtype!(TagId, i64); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub struct TagId(pub i64); - -impl FromStr for TagId { - type Err = ParseIntError; - - fn from_str(s: &str) -> Result { - s.parse().map(Self) - } -} - -impl std::fmt::Display for TagId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} +wp_content_i64_id!(TagId); #[derive( Debug, diff --git a/wp_api/src/users.rs b/wp_api/src/users.rs index 33f8b7884..0ae475a9e 100644 --- a/wp_api/src/users.rs +++ b/wp_api/src/users.rs @@ -1,14 +1,13 @@ use crate::{ EnumFromStrParsingError, OptionFromStr, WpApiParamOrder, WpResponseString, - impl_as_query_value_for_new_type, impl_as_query_value_from_to_string, + impl_as_query_value_from_to_string, url_query::{ AppendUrlQueryPairs, FromUrlQueryPairs, QueryPairs, QueryPairsExtension, UrlQueryPairsMap, }, + wp_content_i64_id, }; use serde::{Deserialize, Serialize}; -use std::{ - collections::HashMap, convert::Infallible, fmt::Display, num::ParseIntError, str::FromStr, -}; +use std::{collections::HashMap, convert::Infallible, fmt::Display, str::FromStr}; use strum_macros::IntoStaticStr; use wp_contextual::WpContextual; @@ -403,30 +402,7 @@ pub struct UserDeleteResponse { pub previous: UserWithEditContext, } -impl_as_query_value_for_new_type!(UserId); -uniffi::custom_newtype!(UserId, i64); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub struct UserId(pub i64); - -impl FromStr for UserId { - type Err = ParseIntError; - - fn from_str(s: &str) -> Result { - s.parse().map(Self) - } -} - -impl std::fmt::Display for UserId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -impl From for UserId { - fn from(value: i64) -> Self { - Self(value) - } -} +wp_content_i64_id!(UserId); #[derive(Debug, Serialize, Deserialize, uniffi::Record, WpContextual)] pub struct SparseUser { diff --git a/wp_api/src/wp_content_macros.rs b/wp_api/src/wp_content_macros.rs new file mode 100644 index 000000000..5770e1259 --- /dev/null +++ b/wp_api/src/wp_content_macros.rs @@ -0,0 +1,92 @@ +//! Macros for generating WordPress content ID and identifier types +//! These macros reduce duplication across ID types like PostId, MediaId, CategoryId, etc. + +/// Generates a WordPress content ID type based on i64 with standard implementations +/// +/// This macro creates: +/// - The ID struct with uniffi support +/// - AsQueryValue implementation +/// - FromStr, Display, and From implementations +/// +/// # Example +/// ```rust,ignore +/// wp_api::wp_content_i64_id!(PostId); +/// // Generates: PostId(i64) with all required traits +/// ``` +#[macro_export] +macro_rules! wp_content_i64_id { + ($id_type:ident) => { + $crate::impl_as_query_value_for_new_type!($id_type); + ::uniffi::custom_newtype!($id_type, i64); + #[derive(Debug, Clone, Copy, PartialEq, Eq, ::serde::Serialize, ::serde::Deserialize)] + pub struct $id_type(pub i64); + + impl ::core::str::FromStr for $id_type { + type Err = ::core::num::ParseIntError; + + fn from_str(s: &str) -> ::core::result::Result { + s.parse().map(Self) + } + } + + impl ::core::fmt::Display for $id_type { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + write!(f, "{}", self.0) + } + } + + impl From for $id_type { + fn from(value: i64) -> Self { + Self(value) + } + } + }; +} + +/// Generates a WordPress content identifier type based on String with standard implementations +/// +/// This macro creates: +/// - The identifier struct with uniffi support +/// - AsQueryValue implementation using to_string +/// - FromStr (infallible), Display, and From implementations +/// +/// # Example +/// ```rust,ignore +/// wp_api::wp_content_string_id!(WidgetId); +/// // Generates: WidgetId(String) with all required traits +/// ``` +#[macro_export] +macro_rules! wp_content_string_id { + ($id_type:ident) => { + ::uniffi::custom_newtype!($id_type, ::std::string::String); + $crate::impl_as_query_value_from_to_string!($id_type); + #[derive(Debug, Clone, PartialEq, Eq, ::serde::Serialize, ::serde::Deserialize)] + pub struct $id_type(pub ::std::string::String); + + impl ::core::str::FromStr for $id_type { + type Err = ::core::convert::Infallible; + + fn from_str(s: &str) -> ::core::result::Result { + ::core::result::Result::Ok(Self(s.to_string())) + } + } + + impl ::core::fmt::Display for $id_type { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + write!(f, "{}", self.0) + } + } + + impl From<::std::string::String> for $id_type { + fn from(value: ::std::string::String) -> Self { + Self(value) + } + } + + impl From<&str> for $id_type { + fn from(value: &str) -> Self { + Self(value.to_string()) + } + } + }; +}