use std::marker::PhantomData;
use futures::future::BoxFuture;
use crate::Command;
use super::query::QueryError;
#[derive(Debug, Clone)]
pub enum MutationState<T> {
Idle,
Loading,
Success(T),
Error(String),
}
#[derive(Debug, Clone)]
pub struct MutationResult<T> {
pub state: MutationState<T>,
}
impl<T> MutationResult<T> {
pub const fn data(&self) -> Option<&T> {
match &self.state {
MutationState::Success(data) => Some(data),
_ => None,
}
}
pub const fn is_loading(&self) -> bool {
matches!(self.state, MutationState::Loading)
}
pub const fn is_success(&self) -> bool {
matches!(self.state, MutationState::Success(_))
}
pub const fn is_error(&self) -> bool {
matches!(self.state, MutationState::Error(_))
}
}
pub struct Mutation<I, O> {
_phantom: PhantomData<(I, O)>,
}
impl<I, O> Mutation<I, O>
where
I: Send + 'static,
O: Send + 'static,
{
pub fn mutate<F>(input: I, mutator: F) -> Command<Result<O, QueryError>>
where
F: FnOnce(I) -> BoxFuture<'static, Result<O, QueryError>> + Send + 'static,
{
Command::future(async move { mutator(input).await })
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mutation_result_data() {
let result = MutationResult {
state: MutationState::Success(42),
};
assert_eq!(result.data(), Some(&42));
let result: MutationResult<i32> = MutationResult {
state: MutationState::Idle,
};
assert_eq!(result.data(), None);
let result: MutationResult<i32> = MutationResult {
state: MutationState::Loading,
};
assert_eq!(result.data(), None);
let result: MutationResult<i32> = MutationResult {
state: MutationState::Error("error".to_string()),
};
assert_eq!(result.data(), None);
}
#[test]
fn test_mutation_result_predicates() {
let idle: MutationResult<i32> = MutationResult {
state: MutationState::Idle,
};
assert!(!idle.is_loading());
assert!(!idle.is_success());
assert!(!idle.is_error());
let loading: MutationResult<i32> = MutationResult {
state: MutationState::Loading,
};
assert!(loading.is_loading());
assert!(!loading.is_success());
assert!(!loading.is_error());
let success = MutationResult {
state: MutationState::Success(42),
};
assert!(!success.is_loading());
assert!(success.is_success());
assert!(!success.is_error());
let error: MutationResult<i32> = MutationResult {
state: MutationState::Error("error".to_string()),
};
assert!(!error.is_loading());
assert!(!error.is_success());
assert!(error.is_error());
}
}