Further downstream code size improvements (#3300)

This commit is contained in:
Jonas Platte
2025-04-01 06:33:18 -04:00
committed by GitHub
parent cd2d5e1417
commit af6a595fdf
3 changed files with 80 additions and 67 deletions
+22 -19
View File
@@ -162,27 +162,30 @@ where
type Rejection = PathRejection;
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
let params = match parts.extensions.get::<UrlParams>() {
Some(UrlParams::Params(params)) => params,
Some(UrlParams::InvalidUtf8InPathParam { key }) => {
let err = PathDeserializationError {
kind: ErrorKind::InvalidUtf8InPathParam {
key: key.to_string(),
},
};
let err = FailedToDeserializePathParams(err);
return Err(err.into());
// Extracted into separate fn so it's only compiled once for all T.
fn get_params(parts: &Parts) -> Result<&[(Arc<str>, PercentDecodedStr)], PathRejection> {
match parts.extensions.get::<UrlParams>() {
Some(UrlParams::Params(params)) => Ok(params),
Some(UrlParams::InvalidUtf8InPathParam { key }) => {
let err = PathDeserializationError {
kind: ErrorKind::InvalidUtf8InPathParam {
key: key.to_string(),
},
};
Err(FailedToDeserializePathParams(err).into())
}
None => Err(MissingPathParams.into()),
}
None => {
return Err(MissingPathParams.into());
}
};
}
T::deserialize(de::PathDeserializer::new(params))
.map_err(|err| {
PathRejection::FailedToDeserializePathParams(FailedToDeserializePathParams(err))
})
.map(Path)
fn failed_to_deserialize_path_params(err: PathDeserializationError) -> PathRejection {
PathRejection::FailedToDeserializePathParams(FailedToDeserializePathParams(err))
}
match T::deserialize(de::PathDeserializer::new(get_params(parts)?)) {
Ok(val) => Ok(Path(val)),
Err(e) => Err(failed_to_deserialize_path_params(e)),
}
}
}
+12 -8
View File
@@ -110,17 +110,21 @@ where
T: Serialize,
{
fn into_response(self) -> Response {
match serde_urlencoded::to_string(&self.0) {
Ok(body) => (
[(CONTENT_TYPE, mime::APPLICATION_WWW_FORM_URLENCODED.as_ref())],
body,
)
.into_response(),
Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into_response(),
// Extracted into separate fn so it's only compiled once for all T.
fn make_response(ser_result: Result<String, serde_urlencoded::ser::Error>) -> Response {
match ser_result {
Ok(body) => (
[(CONTENT_TYPE, mime::APPLICATION_WWW_FORM_URLENCODED.as_ref())],
body,
)
.into_response(),
Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into_response(),
}
}
make_response(serde_urlencoded::to_string(&self.0))
}
}
axum_core::__impl_deref!(Form);
#[cfg(test)]
+46 -40
View File
@@ -176,31 +176,31 @@ where
/// but special cases may require first extracting a `Request` into `Bytes` then optionally
/// constructing a `Json<T>`.
pub fn from_bytes(bytes: &[u8]) -> Result<Self, JsonRejection> {
let deserializer = &mut serde_json::Deserializer::from_slice(bytes);
let value = match serde_path_to_error::deserialize(deserializer) {
Ok(value) => value,
Err(err) => {
let rejection = match err.inner().classify() {
serde_json::error::Category::Data => JsonDataError::from_err(err).into(),
serde_json::error::Category::Syntax | serde_json::error::Category::Eof => {
// Extracted into separate fn so it's only compiled once for all T.
fn make_rejection(err: serde_path_to_error::Error<serde_json::Error>) -> JsonRejection {
match err.inner().classify() {
serde_json::error::Category::Data => JsonDataError::from_err(err).into(),
serde_json::error::Category::Syntax | serde_json::error::Category::Eof => {
JsonSyntaxError::from_err(err).into()
}
serde_json::error::Category::Io => {
if cfg!(debug_assertions) {
// we don't use `serde_json::from_reader` and instead always buffer
// bodies first, so we shouldn't encounter any IO errors
unreachable!()
} else {
JsonSyntaxError::from_err(err).into()
}
serde_json::error::Category::Io => {
if cfg!(debug_assertions) {
// we don't use `serde_json::from_reader` and instead always buffer
// bodies first, so we shouldn't encounter any IO errors
unreachable!()
} else {
JsonSyntaxError::from_err(err).into()
}
}
};
return Err(rejection);
}
}
};
}
Ok(Json(value))
let deserializer = &mut serde_json::Deserializer::from_slice(bytes);
match serde_path_to_error::deserialize(deserializer) {
Ok(value) => Ok(Json(value)),
Err(err) => Err(make_rejection(err)),
}
}
}
@@ -209,28 +209,34 @@ where
T: Serialize,
{
fn into_response(self) -> Response {
// Extracted into separate fn so it's only compiled once for all T.
fn make_response(buf: BytesMut, ser_result: serde_json::Result<()>) -> Response {
match ser_result {
Ok(()) => (
[(
header::CONTENT_TYPE,
HeaderValue::from_static(mime::APPLICATION_JSON.as_ref()),
)],
buf.freeze(),
)
.into_response(),
Err(err) => (
StatusCode::INTERNAL_SERVER_ERROR,
[(
header::CONTENT_TYPE,
HeaderValue::from_static(mime::TEXT_PLAIN_UTF_8.as_ref()),
)],
err.to_string(),
)
.into_response(),
}
}
// Use a small initial capacity of 128 bytes like serde_json::to_vec
// https://docs.rs/serde_json/1.0.82/src/serde_json/ser.rs.html#2189
let mut buf = BytesMut::with_capacity(128).writer();
match serde_json::to_writer(&mut buf, &self.0) {
Ok(()) => (
[(
header::CONTENT_TYPE,
HeaderValue::from_static(mime::APPLICATION_JSON.as_ref()),
)],
buf.into_inner().freeze(),
)
.into_response(),
Err(err) => (
StatusCode::INTERNAL_SERVER_ERROR,
[(
header::CONTENT_TYPE,
HeaderValue::from_static(mime::TEXT_PLAIN_UTF_8.as_ref()),
)],
err.to_string(),
)
.into_response(),
}
let res = serde_json::to_writer(&mut buf, &self.0);
make_response(buf.into_inner(), res)
}
}