use std::{collections::VecDeque, fmt::Debug, pin::Pin};
use derive_builder::Builder;
use futures::prelude::*;
use percent_encoding::{NON_ALPHANUMERIC, utf8_percent_encode};
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use crate::{
client::Client,
errors::ExecutionError,
pagination::{PaginatedQuery, PaginatedResponse, execute_paginated},
types::AirtableRecord,
};
#[derive(Builder, Clone, Debug, Serialize)]
#[builder(pattern = "owned", setter(prefix = "with"))]
pub struct ListRecordsQuery {
#[serde(skip)]
base_id: String,
#[serde(skip)]
#[builder(vis = "pub(crate)")]
client: Client,
#[builder(default)]
fields: Option<Vec<String>>,
#[builder(default)]
#[serde(rename = "filterByFormula")]
filter: Option<String>,
#[builder(default, private)]
offset: Option<String>,
#[serde(rename = "pageSize")]
#[builder(default)]
page_size: Option<usize>,
#[serde(skip)]
table_id: String,
}
impl<T> PaginatedQuery<AirtableRecord<T>, ListRecordsResponse<T>> for ListRecordsQuery
where
T: Clone + Debug + DeserializeOwned,
{
fn get_offset(&self) -> Option<String> {
self.offset.clone()
}
fn set_offset(&mut self, value: Option<String>) {
self.offset = value;
}
fn get_req_builder(&self) -> reqwest::RequestBuilder {
let base_id = utf8_percent_encode(&self.base_id, NON_ALPHANUMERIC).to_string();
let table_id = utf8_percent_encode(&self.table_id, NON_ALPHANUMERIC).to_string();
self.client
.post_path(&format!("v0/{base_id}/{table_id}/listRecords",))
.json(&self)
}
}
impl ListRecordsQuery {
pub fn stream_items<T>(
self,
) -> Pin<Box<impl Stream<Item = Result<AirtableRecord<T>, ExecutionError>>>>
where
T: Clone + Debug + DeserializeOwned,
{
execute_paginated::<AirtableRecord<T>, ListRecordsResponse<T>>(self)
}
}
#[derive(Clone, Deserialize)]
struct ListRecordsResponse<T>
where
T: Clone + Debug,
{
offset: Option<String>,
records: VecDeque<AirtableRecord<T>>,
}
impl<T> PaginatedResponse<AirtableRecord<T>> for ListRecordsResponse<T>
where
T: Clone + Debug + DeserializeOwned,
{
fn get_offset(&self) -> Option<String> {
self.offset.clone()
}
fn get_items(&self) -> VecDeque<AirtableRecord<T>> {
self.records.clone()
}
}