Skip to main content

paperless_api/
id.rs

1//! Paperless ID types.
2//!
3//! Paperless uses numeric IDs for most entities.
4//! To avoid confusion, ID types are defined as wrappers around the underlying numeric type.
5//! e.g. `DocumentId(u32)`.
6
7use derive_more::Display;
8use serde::{Deserialize, Serialize};
9
10/// Marker trait for Paperless ID types.
11pub trait PaperlessId:
12    std::fmt::Display + PartialEq + Eq + std::hash::Hash + serde::de::DeserializeOwned + Serialize
13{
14}
15
16/// Trait for all Paperless IDs which can be treated as items.
17pub trait ItemId: PaperlessId {
18    #[must_use]
19    fn endpoint() -> &'static str;
20}
21
22/// Macro for defining ID wrapper types.
23macro_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        /// ID type for a Paperless entity.
45        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        /// ID type for a Paperless entity (non-copy).
67        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);