use std::future::{Future, IntoFuture};
use std::pin::Pin;
use super::*;
use aws_sdk_dynamodb::operation::get_item::builders::GetItemFluentBuilder;
#[must_use = "builder does nothing until awaited or executed"]
pub struct GetItemRequest<
TD: TableDefinition,
T = (),
O: OutputFormat = Raw,
P: ProjectionState = NoProjection,
> {
builder: GetItemFluentBuilder,
_marker: PhantomData<(TD, T, O, P)>,
}
impl<TD: TableDefinition> GetItemRequest<TD> {
pub fn new(client: aws_sdk_dynamodb::Client, key: Key<TD>) -> Self {
Self::_new(client, key)
}
}
impl<TD: TableDefinition, T, O: OutputFormat, P: ProjectionState> GetItemRequest<TD, T, O, P> {
pub(super) fn _new(client: aws_sdk_dynamodb::Client, key: Key<TD>) -> Self {
let table_name = TD::table_name();
tracing::debug!(table_name, ?key, "GetItem");
Self {
builder: client
.get_item()
.table_name(table_name)
.set_key(Some(key.into_inner())),
_marker: PhantomData,
}
}
pub fn consistent_read(mut self) -> Self {
tracing::debug!("GetItem consistent_read");
self.builder = self.builder.consistent_read(true);
self
}
pub fn into_inner(self) -> GetItemFluentBuilder {
self.builder
}
}
impl<TD: TableDefinition, T, O: OutputFormat> GetItemRequest<TD, T, O, NoProjection> {
pub fn project(
mut self,
projection: Projection<'_, TD>,
) -> GetItemRequest<TD, T, Raw, AlreadyHasProjection> {
tracing::debug!(%projection, "GetItem project");
self.builder = projection.apply_projection(self.builder);
GetItemRequest {
builder: self.builder,
_marker: PhantomData,
}
}
}
impl<TD: TableDefinition, T, P: ProjectionState> GetItemRequest<TD, T, Typed, P> {
pub fn raw(self) -> GetItemRequest<TD, T, Raw, P> {
GetItemRequest {
builder: self.builder,
_marker: PhantomData,
}
}
}
impl<TD: TableDefinition, T: DynamoDBItem<TD> + DeserializeOwned, P: ProjectionState>
GetItemRequest<TD, T, Typed, P>
{
#[tracing::instrument(level = "debug", skip(self), name = "get_execute")]
pub fn execute(self) -> impl Future<Output = Result<Option<T>>> + Send + 'static {
let builder = self.builder;
async move {
builder
.send()
.await?
.item
.map(Item::from_dynamodb_response)
.map(T::try_from_item)
.transpose()
}
}
}
impl<TD: TableDefinition, T: DynamoDBItem<TD> + DeserializeOwned, P: ProjectionState> IntoFuture
for GetItemRequest<TD, T, Typed, P>
{
type Output = Result<Option<T>>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
fn into_future(self) -> Self::IntoFuture {
Box::pin(self.execute())
}
}
impl<TD: TableDefinition, T, P: ProjectionState> GetItemRequest<TD, T, Raw, P> {
#[tracing::instrument(level = "debug", skip(self), name = "get_execute_raw")]
pub fn execute(self) -> impl Future<Output = Result<Option<Item<TD>>>> + Send + 'static {
let builder = self.builder;
async move { Ok(builder.send().await?.item.map(Item::from_dynamodb_response)) }
}
}
impl<TD: TableDefinition, T, P: ProjectionState> IntoFuture for GetItemRequest<TD, T, Raw, P> {
type Output = Result<Option<Item<TD>>>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
fn into_future(self) -> Self::IntoFuture {
Box::pin(self.execute())
}
}