use super::*;
use aws_sdk_dynamodb::operation::scan::builders::ScanFluentBuilder;
#[must_use = "builder does nothing until executed via .all() or .stream()"]
pub struct ScanRequest<
TD: TableDefinition,
T = (),
O: OutputFormat = Raw,
F: FilterState = NoFilter,
P: ProjectionState = NoProjection,
> {
builder: ScanFluentBuilder,
_marker: PhantomData<(TD, T, O, F, P)>,
}
impl<TD: TableDefinition> ScanRequest<TD> {
pub fn new(client: aws_sdk_dynamodb::Client) -> Self {
Self::_new(client)
}
pub fn new_index<I: IndexDefinition<TD>>(client: aws_sdk_dynamodb::Client) -> Self {
Self::_new_index::<I>(client)
}
}
impl<TD: TableDefinition, T, O: OutputFormat, F: FilterState, P: ProjectionState>
ScanRequest<TD, T, O, F, P>
{
pub(super) fn _new(client: aws_sdk_dynamodb::Client) -> Self {
let table_name = TD::table_name();
tracing::debug!(table_name, "Scan");
Self {
builder: client.scan().table_name(table_name),
_marker: PhantomData,
}
}
pub(super) fn _new_index<I: IndexDefinition<TD>>(client: aws_sdk_dynamodb::Client) -> Self {
let table_name = TD::table_name();
let index_name = I::index_name();
tracing::debug!(table_name, index_name, "Scan (index)");
Self {
builder: client.scan().table_name(table_name).index_name(index_name),
_marker: PhantomData,
}
}
pub fn consistent_read(mut self) -> Self {
tracing::debug!("Scan consistent_read");
self.builder = self.builder.consistent_read(true);
self
}
pub fn limit(mut self, limit: i32) -> Self {
tracing::debug!(limit, "Scan limit");
self.builder = self.builder.limit(limit);
self
}
pub fn into_inner(self) -> ScanFluentBuilder {
self.builder
}
}
impl<TD: TableDefinition, T, O: OutputFormat, P: ProjectionState>
ScanRequest<TD, T, O, NoFilter, P>
{
pub fn filter(mut self, filter: Condition<'_>) -> ScanRequest<TD, T, O, AlreadyHasFilter, P> {
tracing::debug!(%filter, "Scan filter");
self.builder = filter.apply_filter(self.builder);
ScanRequest {
builder: self.builder,
_marker: PhantomData,
}
}
}
impl<TD: TableDefinition, T, O: OutputFormat, F: FilterState>
ScanRequest<TD, T, O, F, NoProjection>
{
pub fn project(
mut self,
projection: Projection<'_, TD>,
) -> ScanRequest<TD, T, Raw, F, AlreadyHasProjection> {
tracing::debug!(%projection, "Scan project");
self.builder = projection.apply_projection(self.builder);
ScanRequest {
builder: self.builder,
_marker: PhantomData,
}
}
}
impl<TD: TableDefinition, T, F: FilterState, P: ProjectionState> ScanRequest<TD, T, Typed, F, P> {
pub fn raw(self) -> ScanRequest<TD, T, Raw, F, P> {
ScanRequest {
builder: self.builder,
_marker: PhantomData,
}
}
}
impl<
TD: TableDefinition,
T: DynamoDBItem<TD> + DeserializeOwned,
F: FilterState,
P: ProjectionState,
> ScanRequest<TD, T, Typed, F, P>
{
#[tracing::instrument(level = "debug", skip(self), name = "scan_all")]
pub async fn all(self) -> Result<Vec<T>> {
dynamodb_execute_scan(self.builder)
.await?
.into_iter()
.map(T::try_from_item)
.collect()
}
pub fn stream(self) -> impl Stream<Item = Result<Vec<T>>> {
dynamodb_stream_scan::<TD>(self.builder).map(|result| {
result.and_then(|items| items.into_iter().map(T::try_from_item).collect())
})
}
}
impl<TD: TableDefinition, T, F: FilterState, P: ProjectionState> ScanRequest<TD, T, Raw, F, P> {
#[tracing::instrument(level = "debug", skip(self), name = "scan_all_raw")]
pub async fn all(self) -> Result<Vec<Item<TD>>> {
dynamodb_execute_scan(self.builder).await
}
pub fn stream(self) -> impl Stream<Item = Result<Vec<Item<TD>>>> {
dynamodb_stream_scan(self.builder)
}
}