Use macro to define ID types

This commit is contained in:
D. Scott Boggs 2023-01-29 08:59:40 -05:00 committed by Scott Boggs
parent 3ac64d3d08
commit d6f9617207
13 changed files with 81 additions and 371 deletions

View File

@ -4,9 +4,11 @@ use serde::{
de::{self, Deserializer, Unexpected}, de::{self, Deserializer, Unexpected},
Deserialize, Serialize, Deserialize, Serialize,
}; };
use std::{fmt::Display, path::PathBuf}; use std::path::PathBuf;
use time::{serde::iso8601, OffsetDateTime}; use time::{serde::iso8601, OffsetDateTime};
use crate::AccountId;
/// A struct representing an Account. /// A struct representing an Account.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct Account { pub struct Account {
@ -54,41 +56,6 @@ pub struct Account {
pub bot: Option<bool>, pub bot: Option<bool>,
} }
/// Wrapper type for a account ID string
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)]
pub struct AccountId(String);
impl AsRef<str> for AccountId {
fn as_ref(&self) -> &str {
&self.0
}
}
impl AccountId {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
}
impl Display for AccountId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
static_assertions::assert_not_impl_any!(
AccountId: PartialEq<crate::attachment::AttachmentId>,
PartialEq<crate::filter::FilterId>,
PartialEq<crate::list::ListId>,
PartialEq<crate::mention::MentionId>,
PartialEq<crate::notification::NotificationId>,
PartialEq<crate::relationship::RelationshipId>,
PartialEq<crate::push::SubscriptionId>,
PartialEq<crate::report::ReportId>,
PartialEq<crate::status::StatusId>,
);
/// A single name: value pair from a user's profile /// A single name: value pair from a user's profile
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
pub struct MetadataField { pub struct MetadataField {

View File

@ -1,7 +1,6 @@
//! Module containing everything related to media attachements. //! Module containing everything related to media attachements.
use std::fmt::Display; use crate::AttachmentId;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// A struct representing a media attachment. /// A struct representing a media attachment.
@ -39,40 +38,6 @@ impl Attachment {
self.url.is_some() self.url.is_some()
} }
} }
/// Wrapper type for a attachment ID string
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)]
pub struct AttachmentId(String);
impl AsRef<str> for AttachmentId {
fn as_ref(&self) -> &str {
&self.0
}
}
impl AttachmentId {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
}
impl Display for AttachmentId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
static_assertions::assert_not_impl_any!(
AttachmentId: PartialEq<crate::account::AccountId>,
PartialEq<crate::filter::FilterId>,
PartialEq<crate::list::ListId>,
PartialEq<crate::mention::MentionId>,
PartialEq<crate::notification::NotificationId>,
PartialEq<crate::relationship::RelationshipId>,
PartialEq<crate::report::ReportId>,
PartialEq<crate::push::SubscriptionId>,
PartialEq<crate::status::StatusId>,
);
/// Information about the attachment itself. /// Information about the attachment itself.
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]

View File

@ -1,8 +1,8 @@
use std::fmt::Display;
use serde::{de::Visitor, Deserialize, Deserializer, Serialize}; use serde::{de::Visitor, Deserialize, Deserializer, Serialize};
use time::{serde::iso8601, OffsetDateTime}; use time::{serde::iso8601, OffsetDateTime};
use crate::FilterId;
/// Represents a user-defined filter for determining which statuses should not /// Represents a user-defined filter for determining which statuses should not
/// be shown to the user. /// be shown to the user.
/// ///
@ -53,41 +53,6 @@ pub struct Filter {
pub statuses: Vec<Status>, pub statuses: Vec<Status>,
} }
/// Wrapper type for a filter ID string
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)]
pub struct FilterId(String);
impl AsRef<str> for FilterId {
fn as_ref(&self) -> &str {
&self.0
}
}
impl FilterId {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
}
impl Display for FilterId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
static_assertions::assert_not_impl_any!(
FilterId: PartialEq<crate::account::AccountId>,
PartialEq<crate::attachment::AttachmentId>,
PartialEq<crate::list::ListId>,
PartialEq<crate::mention::MentionId>,
PartialEq<crate::notification::NotificationId>,
PartialEq<crate::relationship::RelationshipId>,
PartialEq<crate::push::SubscriptionId>,
PartialEq<crate::report::ReportId>,
PartialEq<crate::status::StatusId>,
);
/// Represents the various types of Filter contexts /// Represents the various types of Filter contexts
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]

50
entities/src/ids.rs Normal file
View File

@ -0,0 +1,50 @@
use serde::{Deserialize, Serialize};
use std::fmt::Display;
macro_rules! define_ids {
($name:ident, $($rest:ident,)+) => {
define_ids!($name,);
static_assertions::assert_not_impl_any!(
$name: $(PartialEq<$rest>,)+
);
define_ids!($($rest,)+);
};
($name:ident,) => {
/// Wrapper type for a account ID string
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)]
pub struct $name(String);
impl AsRef<str> for $name {
fn as_ref(&self) -> &str {
&self.0
}
}
impl $name {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
}
impl Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
};
() => {}
}
define_ids!(
AccountId,
AttachmentId,
FilterId,
ListId,
MentionId,
NotificationId,
SubscriptionId,
RelationshipId,
ReportId,
StatusId,
);

View File

@ -16,6 +16,9 @@ pub mod context;
pub mod event; pub mod event;
/// Data structures for ser/de of filter-related resources /// Data structures for ser/de of filter-related resources
pub mod filter; pub mod filter;
/// Type-safe ID values
pub mod ids;
pub use ids::*;
/// Data structures for ser/de of instance-related resources /// Data structures for ser/de of instance-related resources
pub mod instance; pub mod instance;
/// Data structures for ser/de of list-related resources /// Data structures for ser/de of list-related resources
@ -46,21 +49,23 @@ pub struct Empty {}
/// modules: /// modules:
pub mod prelude { pub mod prelude {
pub use super::{ pub use super::{
account::{Account, AccountId, Source}, account::{Account, Source},
attachment::{Attachment, AttachmentId, MediaType}, attachment::{Attachment, MediaType},
card::Card, card::Card,
context::Context, context::Context,
event::Event, event::Event,
filter::{Filter, FilterContext, FilterId}, filter::{Filter, FilterContext},
ids::*,
instance::*, instance::*,
list::{List, ListId}, list::List,
mention::{Mention, MentionId}, mention::Mention,
notification::{Notification, NotificationId}, notification::Notification,
push::{Subscription, SubscriptionId}, push::Subscription,
relationship::{Relationship, RelationshipId}, relationship::Relationship,
report::{Report, ReportId}, report::Report,
search_result::SearchResult, search_result::SearchResult,
status::{Application, Emoji, Status, StatusId}, status::{Application, Emoji, Status},
visibility::Visibility,
Empty, Empty,
}; };
} }

View File

@ -1,37 +1,10 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::ListId;
/// Used for ser/de of list resources /// Used for ser/de of list resources
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct List { pub struct List {
id: ListId, id: ListId,
title: String, title: String,
} }
/// Wrapper type for a list ID string
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)]
pub struct ListId(String);
impl AsRef<str> for ListId {
fn as_ref(&self) -> &str {
&self.0
}
}
impl ListId {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
}
static_assertions::assert_not_impl_any!(
ListId: PartialEq<crate::account::AccountId>,
PartialEq<crate::attachment::AttachmentId>,
PartialEq<crate::filter::FilterId>,
PartialEq<crate::push::SubscriptionId>,
PartialEq<crate::mention::MentionId>,
PartialEq<crate::notification::NotificationId>,
PartialEq<crate::relationship::RelationshipId>,
PartialEq<crate::report::ReportId>,
PartialEq<crate::status::StatusId>,
);

View File

@ -1,5 +1,3 @@
use std::fmt::Display;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// Represents a `mention` used in a status /// Represents a `mention` used in a status
@ -14,38 +12,3 @@ pub struct Mention {
/// Account ID /// Account ID
pub id: String, pub id: String,
} }
/// Wrapper type for a mention ID string
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)]
pub struct MentionId(String);
impl AsRef<str> for MentionId {
fn as_ref(&self) -> &str {
&self.0
}
}
impl MentionId {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
}
impl Display for MentionId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
static_assertions::assert_not_impl_any!(
Mention: PartialEq<crate::account::AccountId>,
PartialEq<crate::attachment::AttachmentId>,
PartialEq<crate::filter::FilterId>,
PartialEq<crate::list::ListId>,
PartialEq<crate::notification::NotificationId>,
PartialEq<crate::relationship::RelationshipId>,
PartialEq<crate::push::SubscriptionId>,
PartialEq<crate::report::ReportId>,
PartialEq<crate::status::StatusId>,
);

View File

@ -1,6 +1,6 @@
//! Module containing all info about notifications. //! Module containing all info about notifications.
use std::fmt::Display; use crate::NotificationId;
use super::{account::Account, status::Status}; use super::{account::Account, status::Status};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -24,41 +24,6 @@ pub struct Notification {
pub status: Option<Status>, pub status: Option<Status>,
} }
/// Wrapper type for a notification ID string
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)]
pub struct NotificationId(String);
impl AsRef<str> for NotificationId {
fn as_ref(&self) -> &str {
&self.0
}
}
impl NotificationId {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
}
impl Display for NotificationId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
static_assertions::assert_not_impl_any!(
NotificationId: PartialEq<crate::account::AccountId>,
PartialEq<crate::attachment::AttachmentId>,
PartialEq<crate::filter::FilterId>,
PartialEq<crate::mention::MentionId>,
PartialEq<crate::list::ListId>,
PartialEq<crate::push::SubscriptionId>,
PartialEq<crate::relationship::RelationshipId>,
PartialEq<crate::report::ReportId>,
PartialEq<crate::status::StatusId>,
);
/// The type of notification. /// The type of notification.
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)] #[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]

View File

@ -1,7 +1,7 @@
use std::fmt::Display;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::SubscriptionId;
/// Represents the `alerts` key of the `Subscription` object /// Represents the `alerts` key of the `Subscription` object
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct Alerts { pub struct Alerts {
@ -28,40 +28,6 @@ pub struct Subscription {
pub alerts: Option<Alerts>, pub alerts: Option<Alerts>,
} }
/// Wrapper type for a subscription ID string
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)]
pub struct SubscriptionId(String);
impl AsRef<str> for SubscriptionId {
fn as_ref(&self) -> &str {
&self.0
}
}
impl SubscriptionId {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
}
impl Display for SubscriptionId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
static_assertions::assert_not_impl_any!(
SubscriptionId: PartialEq<crate::account::AccountId>,
PartialEq<crate::attachment::AttachmentId>,
PartialEq<crate::filter::FilterId>,
PartialEq<crate::mention::MentionId>,
PartialEq<crate::notification::NotificationId>,
PartialEq<crate::relationship::RelationshipId>,
PartialEq<crate::report::ReportId>,
PartialEq<crate::status::StatusId>,
);
pub mod add_subscription { pub mod add_subscription {
use serde::Serialize; use serde::Serialize;

View File

@ -1,10 +1,9 @@
//! module containing everything relating to a relationship with //! module containing everything relating to a relationship with
//! another account. //! another account.
use std::fmt::Display;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::RelationshipId;
/// A struct containing information about a relationship with another account. /// A struct containing information about a relationship with another account.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Relationship { pub struct Relationship {
@ -33,37 +32,3 @@ pub struct Relationship {
/// making calls to pleroma or mastodon<2.5.0 instances /// making calls to pleroma or mastodon<2.5.0 instances
pub endorsed: Option<bool>, pub endorsed: Option<bool>,
} }
/// Wrapper type for a relationship ID string
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)]
pub struct RelationshipId(String);
impl AsRef<str> for RelationshipId {
fn as_ref(&self) -> &str {
&self.0
}
}
impl RelationshipId {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
}
impl Display for RelationshipId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
static_assertions::assert_not_impl_any!(
RelationshipId: PartialEq<crate::account::AccountId>,
PartialEq<crate::attachment::AttachmentId>,
PartialEq<crate::filter::FilterId>,
PartialEq<crate::push::SubscriptionId>,
PartialEq<crate::mention::MentionId>,
PartialEq<crate::notification::NotificationId>,
PartialEq<crate::list::ListId>,
PartialEq<crate::report::ReportId>,
PartialEq<crate::status::StatusId>,
);

View File

@ -1,9 +1,8 @@
//! module containing information about a finished report of a user. //! module containing information about a finished report of a user.
use std::fmt::Display;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::ReportId;
/// A struct containing info about a report. /// A struct containing info about a report.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Report { pub struct Report {
@ -12,38 +11,3 @@ pub struct Report {
/// The action taken in response to the report. /// The action taken in response to the report.
pub action_taken: String, pub action_taken: String,
} }
/// Wrapper type for a report ID string
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)]
pub struct ReportId(String);
impl AsRef<str> for ReportId {
fn as_ref(&self) -> &str {
&self.0
}
}
impl ReportId {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
}
impl Display for ReportId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
static_assertions::assert_not_impl_any!(
ReportId: PartialEq<crate::account::AccountId>,
PartialEq<crate::attachment::AttachmentId>,
PartialEq<crate::filter::FilterId>,
PartialEq<crate::push::SubscriptionId>,
PartialEq<crate::mention::MentionId>,
PartialEq<crate::notification::NotificationId>,
PartialEq<crate::relationship::RelationshipId>,
PartialEq<crate::list::ListId>,
PartialEq<crate::status::StatusId>,
);

View File

@ -1,9 +1,6 @@
//! Module containing all info relating to a status. //! Module containing all info relating to a status.
use std::fmt::Display;
use super::prelude::*; use super::prelude::*;
use crate::{card::Card, visibility::Visibility};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use time::{serde::iso8601, OffsetDateTime}; use time::{serde::iso8601, OffsetDateTime};
@ -67,41 +64,6 @@ pub struct Status {
pub pinned: Option<bool>, pub pinned: Option<bool>,
} }
/// Wrapper type for a status ID string
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)]
pub struct StatusId(String);
impl AsRef<str> for StatusId {
fn as_ref(&self) -> &str {
&self.0
}
}
impl StatusId {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
}
impl Display for StatusId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
static_assertions::assert_not_impl_any!(
StatusId: PartialEq<crate::account::AccountId>,
PartialEq<crate::attachment::AttachmentId>,
PartialEq<crate::filter::FilterId>,
PartialEq<crate::push::SubscriptionId>,
PartialEq<crate::mention::MentionId>,
PartialEq<crate::notification::NotificationId>,
PartialEq<crate::relationship::RelationshipId>,
PartialEq<crate::report::ReportId>,
PartialEq<crate::list::ListId>,
);
/// A mention of another user. /// A mention of another user.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Mention { pub struct Mention {

View File

@ -5,7 +5,7 @@ use mastodon_async::Result;
#[cfg(feature = "toml")] #[cfg(feature = "toml")]
async fn run() -> Result<()> { async fn run() -> Result<()> {
use mastodon_async::entities::account::AccountId; use mastodon_async::entities::AccountId;
let mastodon = register::get_mastodon_data().await?; let mastodon = register::get_mastodon_data().await?;
let input = register::read_line("Enter the account id you'd like to follow: ")?; let input = register::read_line("Enter the account id you'd like to follow: ")?;
let account = AccountId::new(input.trim()); let account = AccountId::new(input.trim());