Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extractor: Rename format to parser and auto detect as default #521

Merged
merged 13 commits into from
Nov 29, 2023
53 changes: 28 additions & 25 deletions crates/core/src/extract/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ pub enum SourceFrom {
Cookie,
/// The field will extracted from http payload.
Body,
/// The field will extracted from request.
Request,
}

impl FromStr for SourceFrom {
Expand All @@ -35,7 +33,6 @@ impl FromStr for SourceFrom {
#[cfg(feature = "cookie")]
"cookie" => Ok(Self::Cookie),
"body" => Ok(Self::Body),
"request" => Ok(Self::Request),
_ => Err(crate::Error::Other(format!("invalid source from `{input}`").into())),
}
}
Expand Down Expand Up @@ -106,27 +103,29 @@ impl RenameRule {
}
}

/// Source format for a source. This format is just means that field format, not the request mime type.
/// For example, the request is posted as form, but if the field is string as json format, it can be parsed as json.
/// Source parser for a source.
///
/// This parser is used to parse field data, not the request mime type.
/// For example, if request is posted as form, but the field is string as json format, it can be parsed as json.
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
#[non_exhaustive]
pub enum SourceFormat {
/// MulitMap format. This is the default.
pub enum SourceParser {
/// MulitMap parser.
MultiMap,
/// Json format.
/// Json parser.
Json,
/// Request format means this field will extract from the request.
Request,
/// Smart parser.
Smart,
}

impl FromStr for SourceFormat {
impl FromStr for SourceParser {
type Err = crate::Error;

fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"multimap" => Ok(Self::MultiMap),
"json" => Ok(Self::Json),
"request" => Ok(Self::Request),
"smart" => Ok(Self::Smart),
_ => Err(crate::Error::Other("invalid source format".into())),
}
}
Expand Down Expand Up @@ -202,13 +201,15 @@ impl Metadata {
pub struct Field {
/// Field name.
pub name: &'static str,
/// Field flatten, this field will extracted from request.
pub flatten: bool,
/// Field sources.
pub sources: Vec<Source>,
/// Field aliaes.
pub aliases: Vec<&'static str>,
/// Field rename.
pub rename: Option<&'static str>,
/// Field metadata. This is used for nested extractible types.
/// Field metadata, this is used for nested extractible types.
pub metadata: Option<&'static Metadata>,
}
impl Field {
Expand All @@ -221,13 +222,20 @@ impl Field {
pub fn with_sources(name: &'static str, sources: Vec<Source>) -> Self {
Self {
name,
flatten: false,
sources,
aliases: vec![],
rename: None,
metadata: None,
}
}

/// Sets the flatten to the given value.
pub fn set_flatten(mut self, flatten: bool) -> Self {
self.flatten = flatten;
self
}

/// Sets the metadata to the field type.
pub fn metadata(mut self, metadata: &'static Metadata) -> Self {
self.metadata = Some(metadata);
Expand Down Expand Up @@ -270,13 +278,13 @@ impl Field {
pub struct Source {
/// The source from.
pub from: SourceFrom,
/// the origin data format of the field.
pub format: SourceFormat,
/// The parser used to parse data.
pub parser: SourceParser,
}
impl Source {
/// Create a new source from a string.
pub fn new(from: SourceFrom, format: SourceFormat) -> Self {
Self { from, format }
pub fn new(from: SourceFrom, parser: SourceParser) -> Self {
Self { from, parser }
}
}

Expand All @@ -293,7 +301,6 @@ mod tests {
#[cfg(feature = "cookie")]
("cookie", SourceFrom::Cookie),
("body", SourceFrom::Body),
("request", SourceFrom::Request),
] {
assert_eq!(key.parse::<SourceFrom>().unwrap(), value);
}
Expand All @@ -302,14 +309,10 @@ mod tests {

#[test]
fn test_parse_source_format() {
for (key, value) in [
("multimap", SourceFormat::MultiMap),
("json", SourceFormat::Json),
("request", SourceFormat::Request),
] {
assert_eq!(key.parse::<SourceFormat>().unwrap(), value);
for (key, value) in [("multimap", SourceParser::MultiMap), ("json", SourceParser::Json)] {
assert_eq!(key.parse::<SourceParser>().unwrap(), value);
}
assert!("abcd".parse::<SourceFormat>().is_err());
assert!("abcd".parse::<SourceParser>().is_err());
}

#[test]
Expand Down
6 changes: 3 additions & 3 deletions crates/core/src/extract/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
//! # use salvo_core::prelude::*;
//! # use serde::{Deserialize, Serialize};
//! #[derive(Serialize, Deserialize, Extractible, Debug)]
//! #[salvo(extract(default_source(from = "body", format = "json")))]
//! #[salvo(extract(default_source(from = "body")))]
//! struct GoodMan<'a> {
//! #[salvo(extract(source(from = "param")))]
//! id: i64,
Expand All @@ -41,12 +41,12 @@
//! last_name: String,
//! lovers: Vec<String>,
//! /// The nested field is completely reparsed from Request.
//! #[salvo(extract(source(from = "request")))]
//! #[serde(flatten)]
//! nested: Nested<'a>,
//! }
//!
//! #[derive(Serialize, Deserialize, Extractible, Debug)]
//! #[salvo(extract(default_source(from = "body", format = "json")))]
//! #[salvo(extract(default_source(from = "body")))]
//! struct Nested<'a> {
//! #[salvo(extract(source(from = "param")))]
//! id: i64,
Expand Down
Loading