Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
chrislearn committed Oct 4, 2024
1 parent b3cd11c commit a6a05dd
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 18 deletions.
4 changes: 2 additions & 2 deletions crates/core/src/extract/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ pub enum SourceParser {
MultiMap,
/// Json parser.
Json,
/// Url parser.
UrlQuery,
/// Url or Header parser.
Flat,
/// Smart parser.
Smart,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ macro_rules! forward_url_query_parsed_value {
}
}

pub(super) struct UrlQueryValue<'de>(pub(super) Vec<CowValue<'de>>);
impl<'de> IntoDeserializer<'de> for UrlQueryValue<'de> {
pub(super) struct FlatValue<'de>(pub(super) Vec<CowValue<'de>>);
impl<'de> IntoDeserializer<'de> for FlatValue<'de> {
type Deserializer = Self;

#[inline]
Expand All @@ -35,7 +35,7 @@ impl<'de> IntoDeserializer<'de> for UrlQueryValue<'de> {
}
}

impl<'de> Deserializer<'de> for UrlQueryValue<'de> {
impl<'de> Deserializer<'de> for FlatValue<'de> {
type Error = ValError;

#[inline]
Expand Down Expand Up @@ -121,12 +121,11 @@ impl<'de> Deserializer<'de> for UrlQueryValue<'de> {
} else {
false
};
if !single_mode {
visitor.visit_seq(SeqDeserializer::new(items.into_iter()))
if single_mode {
let parser = FlatParser::new(items.remove(0).0);
visitor.visit_seq(SeqDeserializer::new(parser.into_iter()))
} else {
let vec_value: Vec<Cow<'de, str>> = serde_json::from_str(&items.remove(0).0)
.map_err(|e| ValError::custom(e.to_string()))?;
visitor.visit_seq(SeqDeserializer::new(vec_value.into_iter().map(CowValue)))
visitor.visit_seq(SeqDeserializer::new(items.into_iter()))
}
}

Expand Down Expand Up @@ -158,3 +157,47 @@ impl<'de> Deserializer<'de> for UrlQueryValue<'de> {
f64 => deserialize_f64,
}
}

struct FlatParser<'de> {
input: Cow<'de, str>,
start: usize,
}
impl<'de> FlatParser<'de> {
fn new(input: Cow<'de, str>) -> Self {
Self { input, start: 1 }
}
}
impl<'de> Iterator for FlatParser<'de> {
type Item = CowValue<'de>;

fn next(&mut self) -> Option<Self::Item> {
let mut in_quote = false;
let mut in_escape = false;
let mut end = self.start;
for c in self.input[self.start..].chars() {
if in_escape {
in_escape = false;
continue;
}
match c {
'\\' => {
in_escape = true;
}
'"' => {
in_quote = !in_quote;
}
',' | ']' => {
if !in_quote {
let item: Cow<'de, str> =
Cow::Owned(self.input[self.start..end].to_string());
self.start = end + 1;
return Some(CowValue(item));
}
}
_ => {}
}
end += 1;
}
None
}
}
4 changes: 2 additions & 2 deletions crates/core/src/serde/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ mod cow_value;
use cow_value::CowValue;
mod vec_value;
use vec_value::VecValue;
mod url_query_value;
use url_query_value::UrlQueryValue;
mod flat_value;
use flat_value::FlatValue;

#[inline]
pub fn from_str_map<'de, I, T, K, V>(input: I) -> Result<T, ValError>
Expand Down
35 changes: 29 additions & 6 deletions crates/core/src/serde/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::http::header::HeaderMap;
use crate::http::ParseError;
use crate::Request;

use super::{CowValue, UrlQueryValue, VecValue};
use super::{CowValue, FlatValue, VecValue};

pub async fn from_request<'de, T>(
req: &'de mut Request,
Expand Down Expand Up @@ -141,8 +141,8 @@ impl<'de> RequestDeserializer<'de> {
} else {
parser = SourceParser::MultiMap;
}
} else if source.from == SourceFrom::Query {
parser = SourceParser::UrlQuery;
} else if source.from == SourceFrom::Query || source.from == SourceFrom::Header {
parser = SourceParser::Flat;
} else {
parser = SourceParser::MultiMap;
}
Expand All @@ -160,7 +160,7 @@ impl<'de> RequestDeserializer<'de> {
.fields
.get(self.field_index as usize)
.expect("field must exist.");
let metadata = field.metadata.expect("Field's metadata must exist");
let metadata = field.metadata.expect("field's metadata must exist");
seed.deserialize(RequestDeserializer {
params: self.params,
queries: self.queries,
Expand Down Expand Up @@ -194,8 +194,8 @@ impl<'de> RequestDeserializer<'de> {
} else if let Some(value) = self.field_str_value.take() {
seed.deserialize(CowValue(value.into()))
} else if let Some(value) = self.field_vec_value.take() {
if source.from == SourceFrom::Query {
seed.deserialize(UrlQueryValue(value))
if source.from == SourceFrom::Query || source.from == SourceFrom::Header {
seed.deserialize(FlatValue(value))
} else {
seed.deserialize(VecValue(value.into_iter()))
}
Expand Down Expand Up @@ -674,6 +674,7 @@ mod tests {
let data: RequestData = req.extract().await.unwrap();
assert_eq!(data, RequestData { p2: "921", b: true });
}

#[tokio::test]
async fn test_de_request_with_json_str() {
#[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
Expand All @@ -697,6 +698,7 @@ mod tests {
}
);
}

#[tokio::test]
async fn test_de_request_with_form_json_str() {
#[derive(Deserialize, Eq, PartialEq, Debug)]
Expand Down Expand Up @@ -727,6 +729,7 @@ mod tests {
}
);
}

#[tokio::test]
async fn test_de_request_with_extract_rename_all() {
#[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
Expand All @@ -749,6 +752,7 @@ mod tests {
}
);
}

#[tokio::test]
async fn test_de_request_with_serde_rename_all() {
#[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
Expand All @@ -772,6 +776,7 @@ mod tests {
}
);
}

#[tokio::test]
async fn test_de_request_with_both_rename_all() {
#[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
Expand All @@ -795,4 +800,22 @@ mod tests {
}
);
}

#[tokio::test]
async fn test_de_request_url_array() {
#[derive(Deserialize, Extractible, Eq, PartialEq, Debug)]
#[salvo(extract(default_source(from = "query")))]
struct RequestData {
ids: Vec<String>,
}
let mut req =
TestClient::get("http://127.0.0.1:5800/test/1234/param2v?ids=[3,2,11]").build();
let data: RequestData = req.extract().await.unwrap();
assert_eq!(
data,
RequestData {
ids: vec!["3".to_string(), "2".to_string(), "11".to_string()]
}
);
}
}

0 comments on commit a6a05dd

Please sign in to comment.