1use derive_more::Display;
8use serde::{Deserialize, Serialize};
9
10pub trait PaperlessId:
12 std::fmt::Display + PartialEq + Eq + std::hash::Hash + serde::de::DeserializeOwned + Serialize
13{
14}
15
16pub trait ItemId: PaperlessId {
18 #[must_use]
19 fn endpoint() -> &'static str;
20}
21
22macro_rules! define_ids {
24 ($($def:tt),* $(,)?) => {
25 $(define_ids!(@parse $def);)*
26 };
27
28 (@parse ($name:ident, $type:ty)) => {
29 define_ids!(@emit copy $name, $type);
30 };
31 (@parse ($name:ident, $type:ty, noncopy)) => {
32 define_ids!(@emit noncopy $name, $type);
33 };
34 (@parse ($name:ident, $type:ty, $endpoint:literal)) => {
35 define_ids!(@emit copy $name, $type, $endpoint);
36 };
37 (@parse ($name:ident, $type:ty, noncopy, $endpoint:literal)) => {
38 define_ids!(@emit noncopy $name, $type, $endpoint);
39 };
40
41 (@emit copy $name:ident, $type:ty $(, $endpoint:literal)?) => {
42 #[derive(Clone, Copy, Display, Default, PartialEq, Eq, Hash, Deserialize, Serialize)]
43 #[repr(transparent)]
44 pub struct $name(pub $type);
46
47 impl std::fmt::Debug for $name {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 write!(f, "{}({})", stringify!($name), *self)
50 }
51 }
52
53 impl From<$name> for $type {
54 #[inline]
55 fn from(item: $name) -> Self {
56 item.0
57 }
58 }
59
60 impl PaperlessId for $name {}
61 define_ids!(@maybe_item_id $name $(, $endpoint)?);
62 };
63 (@emit noncopy $name:ident, $type:ty $(, $endpoint:literal)?) => {
64 #[derive(Clone, Display, Default, PartialEq, Eq, Hash, Deserialize, Serialize)]
65 #[repr(transparent)]
66 pub struct $name(pub $type);
68
69 impl std::fmt::Debug for $name {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 write!(f, "{}({})", stringify!($name), *self)
72 }
73 }
74
75 impl AsRef<str> for $name {
76 #[inline]
77 fn as_ref(&self) -> &str {
78 self.0.as_ref()
79 }
80 }
81
82 impl PaperlessId for $name {}
83 define_ids!(@maybe_item_id $name $(, $endpoint)?);
84 };
85 (@maybe_item_id $name:ident) => {};
86 (@maybe_item_id $name:ident, $endpoint:literal) => {
87 impl ItemId for $name {
88 #[inline]
89 fn endpoint() -> &'static str {
90 $endpoint
91 }
92 }
93 };
94}
95
96define_ids!(
97 (CorrespondentId, u32, "correspondents"),
98 (CustomFieldId, u32, "custom_fields"),
99 (DocumentId, u32, "documents"),
100 (DocumentTypeId, u32, "document_types"),
101 (GroupId, u32, "groups"),
102 (NoteId, u32),
103 (SavedViewId, u32, "saved_views"),
104 (SelectableOptionId, String, noncopy),
105 (ShareLinkId, u32, "share_links"),
106 (StoragePathId, u32, "storage_paths"),
107 (TagId, u32, "tags"),
108 (TaskId, String, noncopy),
109 (UserId, u32, "users"),
110 (WorkflowActionId, u32),
111 (WorkflowId, u32, "workflows"),
112 (WorkflowTriggerId, u32),
113 (WebhookActionId, u32),
114);