Fallible Conversions — TryMapFrom (v0.2)
+Sometimes struct conversions can fail. For example:
+-
+
- Converting
i64→u32(negative numbers will fail)
+ - Parsing a
Stringinto a number or email
+ - Validating field values +
For these cases, use #[derive(TryMapFrom)] which generates impl TryFrom<Source> for Target.
Basic Usage
+use struct_mapper::TryMapFrom;
+
+struct RawInput {
+ count: i64,
+ name: String,
+}
+
+#[derive(TryMapFrom)]
+#[try_map_from(RawInput)]
+struct ValidInput {
+ #[map(try_into)]
+ count: u32, // i64 → u32 can fail if negative
+ name: String, // direct (always succeeds)
+}
+
+let raw = RawInput { count: 42, name: "Alice".into() };
+let valid: ValidInput = raw.try_into().unwrap();
+
+// Failure case:
+let bad = RawInput { count: -1, name: "Bob".into() };
+assert!(ValidInput::try_from(bad).is_err());
+#[map(try_into)] — Fallible Type Conversion
+Use this when the source field type implements TryInto<TargetType>:
struct Source { value: i64 }
+
+#[derive(TryMapFrom)]
+#[try_map_from(Source)]
+struct Target {
+ #[map(try_into)]
+ value: u32, // calls source.value.try_into()
+}
+#[map(try_with = "fn")] — Fallible Custom Function
+Use this with a function that returns Result<T, E>:
use std::num::ParseIntError;
+
+fn parse_port(s: String) -> Result<u16, ParseIntError> {
+ s.parse::<u16>()
+}
+
+struct Config { port: String }
+
+#[derive(TryMapFrom)]
+#[try_map_from(Config)]
+struct ValidConfig {
+ #[map(try_with = "parse_port")]
+ port: u16,
+}
+Mixing Infallible and Fallible Attributes
+You can freely mix all attributes in a single TryMapFrom struct:
#[derive(TryMapFrom)]
+#[try_map_from(Source)]
+struct Target {
+ id: u64, // direct (infallible)
+ #[map(from = "raw_name", with = "to_upper")]
+ name: String, // infallible rename + transform
+ #[map(try_into)]
+ count: u32, // fallible type conversion
+ #[map(from = "age_str", try_with = "parse")]
+ age: u8, // fallible rename + transform
+ #[map(skip, default)]
+ request_id: String, // skipped
+}
+Error Handling — MapError
+When a conversion fails, you get a struct_mapper::MapError which tells you exactly which field failed:
use struct_mapper::{TryMapFrom, MapError};
+
+let result = Target::try_from(source);
+match result {
+ Ok(target) => println!("Success: {:?}", target),
+ Err(e) => {
+ println!("Field: {}", e.field); // e.g., "count"
+ println!("Error: {}", e); // "mapping failed at field `count`: ..."
+ println!("Source: {:?}", e.source); // underlying error
+ }
+}
+++ +Tip:
+MapErrorimplementsstd::error::Error,Display, andDebug, so it works seamlessly with?operator and error handling libraries likeanyhoworthiserror.