1use crate::block::Block;
5use crate::database::properties::PropertyValue;
6use crate::database::Database;
7use crate::error::ErrorResponse;
8use crate::pages::Page;
9use crate::user::User;
10use crate::Error;
11use serde::{Deserialize, Serialize};
12
13#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone)]
14#[serde(transparent)]
15pub struct PagingCursor(String);
16
17#[derive(Serialize, Debug, Eq, PartialEq, Default, Clone)]
18pub struct Paging {
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub start_cursor: Option<PagingCursor>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub page_size: Option<u8>,
23}
24
25pub trait Pageable {
26 fn start_from(self, starting_point: Option<PagingCursor>) -> Self;
27}
28
29#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
31pub struct ListResponse<T> {
32 pub results: Vec<T>,
33 pub next_cursor: Option<PagingCursor>,
34 pub has_more: bool,
35}
36
37impl<T> ListResponse<T> {
38 pub fn results(&self) -> &[T] {
39 &self.results
40 }
41}
42impl ListResponse<Object> {
43 pub fn only_databases(self) -> ListResponse<Database> {
44 let databases = self
45 .results
46 .into_iter()
47 .filter_map(|object| match object {
48 Object::Database { database } => Some(database),
49 _ => None,
50 })
51 .collect();
52
53 ListResponse {
54 results: databases,
55 has_more: self.has_more,
56 next_cursor: self.next_cursor,
57 }
58 }
59
60 pub fn expect_databases(self) -> Result<ListResponse<Database>, Error> {
61 let databases: Result<Vec<_>, _> = self
62 .results
63 .into_iter()
64 .map(|object| match object {
65 Object::Database { database } => Ok(database),
66 response => Err(Error::UnexpectedResponse { response }),
67 })
68 .collect();
69
70 Ok(ListResponse {
71 results: databases?,
72 has_more: self.has_more,
73 next_cursor: self.next_cursor,
74 })
75 }
76
77 pub fn expect_pages(self) -> Result<ListResponse<Page>, Error> {
78 let items: Result<Vec<_>, _> = self
79 .results
80 .into_iter()
81 .map(|object| match object {
82 Object::Page { page } => Ok(page),
83 response => Err(Error::UnexpectedResponse { response }),
84 })
85 .collect();
86
87 Ok(ListResponse {
88 results: items?,
89 has_more: self.has_more,
90 next_cursor: self.next_cursor,
91 })
92 }
93
94 pub fn expect_blocks(self) -> Result<ListResponse<Block>, crate::Error> {
95 let items: Result<Vec<_>, _> = self
96 .results
97 .into_iter()
98 .map(|object| match object {
99 Object::Block { block } => Ok(block),
100 response => Err(Error::UnexpectedResponse { response }),
101 })
102 .collect();
103
104 Ok(ListResponse {
105 results: items?,
106 has_more: self.has_more,
107 next_cursor: self.next_cursor,
108 })
109 }
110}
111
112#[derive(Eq, Serialize, Deserialize, Clone, Debug, PartialEq)]
113#[serde(tag = "object")]
114#[serde(rename_all = "snake_case")]
115pub enum Object {
116 Block {
117 #[serde(flatten)]
118 block: Block,
119 },
120 Database {
121 #[serde(flatten)]
122 database: Database,
123 },
124 Page {
125 #[serde(flatten)]
126 page: Page,
127 },
128 List {
129 #[serde(flatten)]
130 list: ListResponse<Object>,
131 },
132 User {
133 #[serde(flatten)]
134 user: User,
135 },
136 PropertyItem {
137 #[serde(flatten)]
138 property_item: PropertyValue,
139 },
140 Error {
141 #[serde(flatten)]
142 error: ErrorResponse,
143 },
144}
145
146impl Object {
147 pub fn is_database(&self) -> bool {
148 matches!(self, Object::Database { .. })
149 }
150}