Skip to content

Commit

Permalink
feat: add TryFromChunks impl for rust_decimal_1::Decimal (#93)
Browse files Browse the repository at this point in the history
Co-authored-by: Lorenzo Murarotto <murar8@proton.me>
  • Loading branch information
SimonErm and murar8 authored Dec 14, 2024
1 parent 10799c5 commit 9e0106f
Showing 2 changed files with 42 additions and 1 deletion.
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -30,9 +30,10 @@ repository.workspace = true
version.workspace = true

[features]
default = ["chrono_0_4", "tempfile_3", "uuid_1"]
default = ["chrono_0_4", "rust_decimal_1", "tempfile_3", "uuid_1"]

chrono_0_4 = ["dep:chrono_0_4"]
rust_decimal_1 = ["dep:rust_decimal_1"]
tempfile_3 = ["dep:tempfile_3", "dep:tokio"]
uuid_1 = ["dep:uuid_1"]

@@ -49,6 +50,9 @@ futures-util = "0.3.31"
thiserror = "2.0.0"

chrono_0_4 = { package = "chrono", version = "0.4.0", optional = true }
rust_decimal_1 = { package = "rust_decimal", version = "1.20.0", features = [
"serde-str",
], optional = true }
tempfile_3 = { package = "tempfile", version = "3.1.0", optional = true }
tokio = { workspace = true, features = ["fs", "io-util"], optional = true }
uuid_1 = { package = "uuid", version = "1.0.0", optional = true }
37 changes: 37 additions & 0 deletions src/try_from_chunks.rs
Original file line number Diff line number Diff line change
@@ -217,6 +217,35 @@ where
}
}

#[cfg(feature = "rust_decimal_1")]
#[async_trait]
impl<Err> TryFromChunks for rust_decimal_1::Decimal
where
Err: Into<anyhow::Error>,
rust_decimal_1::Decimal: FromStr<Err = Err>,
{
async fn try_from_chunks(
chunks: impl Stream<Item = Result<Bytes, TypedMultipartError>> + Send + Sync + Unpin,
metadata: FieldMetadata,
) -> Result<Self, TypedMultipartError> {
let field_name = get_field_name(&metadata.name);
let bytes = Bytes::try_from_chunks(chunks, metadata).await?;
let body_str =
std::str::from_utf8(&bytes).map_err(|err| TypedMultipartError::WrongFieldType {
field_name: field_name.clone(),
wanted_type: type_name::<rust_decimal_1::Decimal>().to_string(),
source: err.into(),
})?;
rust_decimal_1::Decimal::from_str(body_str).map_err(|err| {
TypedMultipartError::WrongFieldType {
field_name,
wanted_type: type_name::<rust_decimal_1::Decimal>().to_string(),
source: err.into(),
}
})
}
}

fn get_field_name(name: &Option<String>) -> String {
// Theoretically, the name should always be present, but it's better to be
// safe than sorry.
@@ -399,6 +428,14 @@ mod tests {
test_try_from_chunks_invalid::<DateTime>(Bytes::from_static(&[0, 159, 146, 150])).await;
}

#[tokio::test]
async fn test_try_from_chunks_rust_decimal() {
let valid_input = "1.50";
let valid_output = rust_decimal_1::Decimal::from_str(valid_input).unwrap();
test_try_from_chunks_valid::<rust_decimal_1::Decimal>(valid_input, valid_output).await;
test_try_from_chunks_invalid::<rust_decimal_1::Decimal>("invalid").await;
}

#[tokio::test]
async fn test_try_from_chunks_chrono_native_date_fixed() {
let valid_input = "2024-01-01";

0 comments on commit 9e0106f

Please sign in to comment.