Skip to content

Commit 03d2260

Browse files
committed
Change Rust client's arguments to a builder approach (as opposed to leaking the struct) for better forward compatibility.
1 parent 681db62 commit 03d2260

File tree

3 files changed

+110
-79
lines changed

3 files changed

+110
-79
lines changed

client/trailbase-rs/src/lib.rs

Lines changed: 74 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -71,28 +71,31 @@ pub struct Tokens {
7171
pub csrf_token: Option<String>,
7272
}
7373

74-
#[derive(Clone, Debug, Default)]
74+
#[derive(Clone, Debug, Default, PartialEq)]
7575
pub struct Pagination {
76-
pub cursor: Option<String>,
77-
pub limit: Option<usize>,
78-
pub offset: Option<usize>,
76+
cursor: Option<String>,
77+
limit: Option<usize>,
78+
offset: Option<usize>,
7979
}
8080

8181
impl Pagination {
82-
pub fn with(limit: impl Into<Option<usize>>, cursor: impl Into<Option<String>>) -> Pagination {
83-
return Pagination {
84-
limit: limit.into(),
85-
cursor: cursor.into(),
86-
offset: None,
87-
};
82+
pub fn new() -> Self {
83+
return Self::default();
84+
}
85+
86+
pub fn with_limit(mut self, limit: impl Into<Option<usize>>) -> Pagination {
87+
self.limit = limit.into();
88+
return self;
8889
}
8990

90-
pub fn with_limit(limit: impl Into<Option<usize>>) -> Pagination {
91-
return Pagination::with(limit, None);
91+
pub fn with_cursor(mut self, cursor: impl Into<Option<String>>) -> Pagination {
92+
self.cursor = cursor.into();
93+
return self;
9294
}
9395

94-
pub fn with_cursor(cursor: impl Into<Option<String>>) -> Pagination {
95-
return Pagination::with(None, cursor);
96+
pub fn with_offset(mut self, offset: impl Into<Option<usize>>) -> Pagination {
97+
self.offset = offset.into();
98+
return self;
9699
}
97100
}
98101

@@ -141,32 +144,43 @@ impl RecordId<'_> for i64 {
141144

142145
pub trait ReadArgumentsTrait<'a> {
143146
fn serialized_id(self) -> Cow<'a, str>;
144-
fn expand(&self) -> Option<&'a [&'a str]>;
147+
fn expand(&self) -> Option<&Vec<&'a str>>;
145148
}
146149

147150
impl<'a, T: RecordId<'a>> ReadArgumentsTrait<'a> for T {
148151
fn serialized_id(self) -> Cow<'a, str> {
149152
return self.serialized_id();
150153
}
151154

152-
fn expand(&self) -> Option<&'a [&'a str]> {
155+
fn expand(&self) -> Option<&Vec<&'a str>> {
153156
return None;
154157
}
155158
}
156159

157-
#[derive(Debug, Default)]
160+
#[derive(Clone, Debug, PartialEq)]
158161
pub struct ReadArguments<'a, T: RecordId<'a>> {
159-
pub id: T,
160-
pub expand: Option<&'a [&'a str]>,
162+
id: T,
163+
expand: Option<Vec<&'a str>>,
164+
}
165+
166+
impl<'a, T: RecordId<'a>> ReadArguments<'a, T> {
167+
pub fn new(id: T) -> Self {
168+
return Self { id, expand: None };
169+
}
170+
171+
pub fn with_expand(mut self, expand: impl AsRef<[&'a str]>) -> Self {
172+
self.expand = Some(expand.as_ref().to_vec());
173+
return self;
174+
}
161175
}
162176

163177
impl<'a, T: RecordId<'a>> ReadArgumentsTrait<'a> for ReadArguments<'a, T> {
164178
fn serialized_id(self) -> Cow<'a, str> {
165179
return self.id.serialized_id();
166180
}
167181

168-
fn expand(&self) -> Option<&'a [&'a str]> {
169-
return self.expand;
182+
fn expand(&self) -> Option<&Vec<&'a str>> {
183+
return self.expand.as_ref();
170184
}
171185
}
172186

@@ -236,13 +250,44 @@ pub struct RecordApi {
236250
name: String,
237251
}
238252

239-
#[derive(Default)]
253+
#[derive(Clone, Debug, Default, PartialEq)]
240254
pub struct ListArguments<'a> {
241-
pub pagination: Pagination,
242-
pub order: Option<&'a [&'a str]>,
243-
pub filters: Option<&'a [&'a str]>,
244-
pub expand: Option<&'a [&'a str]>,
245-
pub count: bool,
255+
pagination: Pagination,
256+
order: Option<Vec<&'a str>>,
257+
filters: Option<Vec<&'a str>>,
258+
expand: Option<Vec<&'a str>>,
259+
count: bool,
260+
}
261+
262+
impl<'a> ListArguments<'a> {
263+
pub fn new() -> Self {
264+
return ListArguments::default();
265+
}
266+
267+
pub fn with_pagination(mut self, pagination: Pagination) -> Self {
268+
self.pagination = pagination;
269+
return self;
270+
}
271+
272+
pub fn with_order(mut self, order: impl AsRef<[&'a str]>) -> Self {
273+
self.order = Some(order.as_ref().to_vec());
274+
return self;
275+
}
276+
277+
pub fn with_filters(mut self, filters: impl AsRef<[&'a str]>) -> Self {
278+
self.filters = Some(filters.as_ref().to_vec());
279+
return self;
280+
}
281+
282+
pub fn with_expand(mut self, expand: impl AsRef<[&'a str]>) -> Self {
283+
self.expand = Some(expand.as_ref().to_vec());
284+
return self;
285+
}
286+
287+
pub fn with_count(mut self, count: bool) -> Self {
288+
self.count = count;
289+
return self;
290+
}
246291
}
247292

248293
impl RecordApi {
@@ -266,13 +311,13 @@ impl RecordApi {
266311

267312
if let Some(order) = args.order {
268313
if !order.is_empty() {
269-
params.push((Cow::Borrowed("order"), Cow::Owned(to_list(order))));
314+
params.push((Cow::Borrowed("order"), Cow::Owned(to_list(&order))));
270315
}
271316
}
272317

273318
if let Some(expand) = args.expand {
274319
if !expand.is_empty() {
275-
params.push((Cow::Borrowed("expand"), Cow::Owned(to_list(expand))));
320+
params.push((Cow::Borrowed("expand"), Cow::Owned(to_list(&expand))));
276321
}
277322
}
278323

client/trailbase-rs/tests/integration_test.rs

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -169,23 +169,19 @@ async fn records_test() {
169169
{
170170
// List one specific message.
171171
let filter = format!("text_not_null={}", messages[0]);
172-
let filters = vec![filter.as_str()];
173172
let response = api
174-
.list::<serde_json::Value>(ListArguments {
175-
filters: Some(&filters),
176-
..Default::default()
177-
})
173+
.list::<serde_json::Value>(ListArguments::new().with_filters([filter.as_str()]))
178174
.await
179175
.unwrap();
180176

181177
assert_eq!(response.records.len(), 1);
182178

183179
let second_response = api
184-
.list::<serde_json::Value>(ListArguments {
185-
pagination: Pagination::with_cursor(response.cursor),
186-
filters: Some(&filters),
187-
..Default::default()
188-
})
180+
.list::<serde_json::Value>(
181+
ListArguments::new()
182+
.with_filters(&[filter.as_str()])
183+
.with_pagination(Pagination::new().with_cursor(response.cursor)),
184+
)
189185
.await
190186
.unwrap();
191187

@@ -196,12 +192,12 @@ async fn records_test() {
196192
// List all the messages
197193
let filter = format!("text_not_null[like]=% =?&{now}");
198194
let records_ascending: ListResponse<SimpleStrict> = api
199-
.list(ListArguments {
200-
order: Some(&["+text_not_null"]),
201-
filters: Some(&[&filter]),
202-
count: true,
203-
..Default::default()
204-
})
195+
.list(
196+
ListArguments::new()
197+
.with_order(["+text_not_null"])
198+
.with_filters([filter.as_str()])
199+
.with_count(true),
200+
)
205201
.await
206202
.unwrap();
207203

@@ -214,11 +210,11 @@ async fn records_test() {
214210
assert_eq!(Some(2), records_ascending.total_count);
215211

216212
let records_descending: ListResponse<SimpleStrict> = api
217-
.list(ListArguments {
218-
order: Some(&["-text_not_null"]),
219-
filters: Some(&[&filter]),
220-
..Default::default()
221-
})
213+
.list(
214+
ListArguments::new()
215+
.with_order(["-text_not_null"])
216+
.with_filters([filter.as_str()]),
217+
)
222218
.await
223219
.unwrap();
224220

@@ -277,10 +273,7 @@ async fn expand_foreign_records_test() {
277273

278274
{
279275
let comment: Comment = api
280-
.read(ReadArguments {
281-
id: 1,
282-
expand: Some(&["post"]),
283-
})
276+
.read(ReadArguments::new(1).with_expand(["post"]))
284277
.await
285278
.unwrap();
286279
assert_eq!(1, comment.id);
@@ -291,12 +284,12 @@ async fn expand_foreign_records_test() {
291284

292285
{
293286
let comments: ListResponse<Comment> = api
294-
.list(ListArguments {
295-
pagination: Pagination::with_limit(2),
296-
order: Some(&["-id"]),
297-
expand: Some(&["author", "post"]),
298-
..Default::default()
299-
})
287+
.list(
288+
ListArguments::new()
289+
.with_pagination(Pagination::new().with_limit(2))
290+
.with_order(["-id"])
291+
.with_expand(["author", "post"]),
292+
)
300293
.await
301294
.unwrap();
302295

@@ -311,16 +304,12 @@ async fn expand_foreign_records_test() {
311304
let second = &comments.records[0];
312305

313306
let offset_comments: ListResponse<Comment> = api
314-
.list(ListArguments {
315-
pagination: Pagination {
316-
limit: Some(1),
317-
offset: Some(1),
318-
..Default::default()
319-
},
320-
order: Some(&["-id"]),
321-
expand: Some(&["author", "post"]),
322-
..Default::default()
323-
})
307+
.list(
308+
ListArguments::new()
309+
.with_pagination(Pagination::new().with_limit(1).with_offset(1))
310+
.with_order(["-id"])
311+
.with_expand(["author", "post"]),
312+
)
324313
.await
325314
.unwrap();
326315

docs/examples/record_api_rs/src/list.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,12 @@ pub async fn list(client: &Client) -> anyhow::Result<ListResponse<serde_json::Va
44
Ok(
55
client
66
.records("movies")
7-
.list(ListArguments {
8-
pagination: Pagination {
9-
limit: Some(3),
10-
..Default::default()
11-
},
12-
order: Some(&["rank"]),
13-
filters: Some(&["watch_time[lt]=120", "description[like]=%love%"]),
14-
..Default::default()
15-
})
7+
.list(
8+
ListArguments::new()
9+
.with_pagination(Pagination::new().with_limit(3))
10+
.with_order(["rank"])
11+
.with_filters(["watch_time[lt]=120", "description[like]=%love%"]),
12+
)
1613
.await?,
1714
)
1815
}

0 commit comments

Comments
 (0)