payjp_types/
pagination.rs1use std::fmt::Debug;
2use std::str::FromStr;
3
4use serde::{Serialize, Serializer};
5
6#[doc(hidden)]
7pub trait FromCursor {
8 fn from_cursor(val: &str) -> Option<Self>
9 where
10 Self: Sized;
11}
12
13impl FromCursor for smol_str::SmolStr {
14 fn from_cursor(val: &str) -> Option<Self> {
15 Self::from_str(val).ok()
16 }
17}
18
19impl<T: FromCursor> FromCursor for Option<T> {
20 fn from_cursor(val: &str) -> Option<Self> {
21 Some(T::from_cursor(val))
22 }
23}
24
25#[doc(hidden)]
26pub trait AsCursorOpt {
27 fn as_cursor_opt(&self) -> Option<&str>;
28}
29
30#[doc(hidden)]
31pub trait AsCursor {
32 fn as_cursor(&self) -> &str;
33}
34
35impl AsCursor for smol_str::SmolStr {
36 fn as_cursor(&self) -> &str {
37 self.as_str()
38 }
39}
40
41impl<T: AsCursor> AsCursorOpt for T {
42 fn as_cursor_opt(&self) -> Option<&str> {
43 Some(self.as_cursor())
44 }
45}
46
47impl<T: AsCursor> AsCursorOpt for Option<T> {
48 fn as_cursor_opt(&self) -> Option<&str> {
49 self.as_ref().map(|id| id.as_cursor())
50 }
51}
52
53pub trait Object {
55 type Id: AsCursorOpt + FromCursor;
57
58 fn id(&self) -> &Self::Id;
60
61 fn into_id(self) -> Self::Id;
63}
64
65#[derive(Debug)]
67#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
68pub struct List<T> {
69 pub data: Vec<T>,
71 pub has_more: bool,
73 pub count: Option<u64>,
75 pub url: String,
77}
78
79impl<T: Serialize> Serialize for List<T> {
84 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
85 where
86 S: Serializer,
87 {
88 use serde::ser::SerializeStruct;
89 let mut ser = serializer.serialize_struct("List", 5)?;
90 ser.serialize_field("data", &self.data)?;
91 ser.serialize_field("has_more", &self.has_more)?;
92 ser.serialize_field("count", &self.count)?;
93 ser.serialize_field("url", &self.url)?;
94 ser.serialize_field("object", "list")?;
95 ser.end()
96 }
97}
98
99impl<T: Clone> Clone for List<T> {
100 fn clone(&self) -> Self {
101 List {
102 data: self.data.clone(),
103 has_more: self.has_more,
104 count: self.count,
105 url: self.url.clone(),
106 }
107 }
108}
109
110#[doc(hidden)]
111mod impl_deserialize {
112 use miniserde::de::{Map, Visitor};
113 use miniserde::json::Value;
114 use miniserde::{make_place, Deserialize, Error};
115
116 use crate::miniserde_helpers::FromValueOpt;
117 use crate::{List};
118 make_place!(Place);
119
120 impl<T: Deserialize> Deserialize for List<T> {
121 fn begin(out: &mut Option<Self>) -> &mut dyn Visitor {
122 Place::new(out)
123 }
124 }
125
126 impl<T: Deserialize> Visitor for Place<List<T>> {
127 fn map(&mut self) -> miniserde::Result<Box<dyn Map + '_>> {
128 Ok(Box::new(ListBuilder {
129 out: &mut self.out,
130 data: Deserialize::default(),
131 has_more: Deserialize::default(),
132 count: Deserialize::default(),
133 url: Deserialize::default(),
134 }))
135 }
136 }
137
138 struct ListBuilder<'a, T> {
139 out: &'a mut Option<List<T>>,
140 data: Option<Vec<T>>,
141 has_more: Option<bool>,
142 count: Option<Option<u64>>,
143 url: Option<String>,
144 }
145
146 impl<'a, T: Deserialize> Map for ListBuilder<'a, T> {
147 fn key(&mut self, k: &str) -> miniserde::Result<&mut dyn Visitor> {
148 match k {
149 "url" => Ok(Deserialize::begin(&mut self.url)),
150 "data" => Ok(Deserialize::begin(&mut self.data)),
151 "has_more" => Ok(Deserialize::begin(&mut self.has_more)),
152 "count" => Ok(Deserialize::begin(&mut self.count)),
153 _ => Ok(<dyn Visitor>::ignore()),
154 }
155 }
156
157 fn finish(&mut self) -> miniserde::Result<()> {
158 let url = self.url.take().ok_or(Error)?;
159 let data = self.data.take().ok_or(Error)?;
160 let has_more = self.has_more.ok_or(Error)?;
161 let count = self.count.ok_or(Error)?;
162 *self.out = Some(List { data, has_more, count, url });
163 Ok(())
164 }
165 }
166
167 impl<T: FromValueOpt> FromValueOpt for List<T> {
168 fn from_value(v: Value) -> Option<Self> {
169 let mut data: Option<Vec<T>> = None;
170 let mut has_more: Option<bool> = None;
171 let mut count: Option<Option<u64>> = Some(None);
172 let mut url: Option<String> = None;
173 let Value::Object(obj) = v else {
174 return None;
175 };
176 for (k, v) in obj {
177 match k.as_str() {
178 "has_more" => has_more = Some(bool::from_value(v)?),
179 "data" => data = Some(FromValueOpt::from_value(v)?),
180 "url" => url = Some(FromValueOpt::from_value(v)?),
181 "count" => count = Some(FromValueOpt::from_value(v)?),
182 _ => {}
183 }
184 }
185 Some(Self { data: data?, has_more: has_more?, count: count?, url: url? })
186 }
187 }
188}