pub mod metadata;
pub use metadata::Metadata;
mod case;
use std::fmt::Debug;
pub use case::RenameRule;
use crate::http::{ParseError, Request};
use crate::{Depot, Writer};
pub trait Extractible<'ex> {
fn metadata() -> &'static Metadata;
fn extract(
req: &'ex mut Request,
depot: &'ex mut Depot,
) -> impl Future<Output = Result<Self, impl Writer + Send + Debug + 'static>> + Send
where
Self: Sized;
fn extract_with_arg(
req: &'ex mut Request,
depot: &'ex mut Depot,
_arg: &str,
) -> impl Future<Output = Result<Self, impl Writer + Send + Debug + 'static>> + Send
where
Self: Sized,
{
Self::extract(req, depot)
}
}
impl<'ex, T> Extractible<'ex> for Option<T>
where
T: Extractible<'ex> + ::serde::de::Deserialize<'ex>,
{
fn metadata() -> &'static Metadata {
T::metadata()
}
#[allow(refining_impl_trait)]
async fn extract(req: &'ex mut Request, depot: &'ex mut Depot) -> Result<Self, ParseError> {
Ok(T::extract(req, depot).await.ok())
}
}
#[cfg(test)]
mod tests {
use serde::Deserialize;
use crate::prelude::*;
use crate::test::TestClient;
#[tokio::test]
async fn test_generic_struct() {
#[derive(Debug, Deserialize, Extractible)]
struct Outer<T> {
#[salvo(extract(flatten))]
inner: T,
}
#[derive(Debug, Deserialize, Extractible)]
#[salvo(extract(default_source(from = "query")))]
struct Inner {
a: String,
}
let mut req = TestClient::get("http://127.0.0.1:8698/test/1234/param2v")
.query("a", "1")
.build();
let mut depot = crate::Depot::new();
let data: Outer<Inner> = req.extract(&mut depot).await.unwrap();
assert_eq!(data.inner.a, "1");
}
}