-
-
Save igalic/6261f3f0124d2115cf88c31f7916a706 to your computer and use it in GitHub Desktop.
match req { | |
Ok(mut res) => { | |
if let Ok(text) = &res.text() { | |
if let Ok(ap_sign) = serde_json::from_str::<ApSignature>(text) { | |
if let Ok(mut json) = serde_json::from_str::<CustomPerson>(text) { | |
json.custom_props = ap_sign; // without this workaround, publicKey is not correctly deserialized | |
Some(json) | |
} else { | |
None | |
} | |
} else { | |
None | |
} | |
} else { | |
None | |
} | |
} | |
Err(e) => { | |
println!("User fetch error: {:?}", e); | |
None | |
} | |
} |
Using and_then
:
let stuff = req
.and_then(|res| {
res.text().and_then(|text| {
serde_json::from_str::<ApSignature>(text).and_then(|ap_sign| {
serde_json::from_str::<CustomPerson>(text).map(|mut json| {
json.custom_props = ap_sign;
Ok(json)
})
})
})
})
.map_err(|e| {
println!("User fetch error: {:?}", e);
e
})
.ok();
The early-exit answers with ?
are the same direction as I would go. I generally like to handle my errors as they come up, not save them for later, because all the intervening stuff is irrelevant for the errors. I haven't conducted benchmarking to know whether there is a performance penalty for the (implicit) double-testing using this approach, but if there is a penalty it should be small. So:
let mut res = req.map_err(|e| println!("User fetch error: {:?}", e)).ok()?;
let text = &res.text().ok()?;
let ap_sign = serde_json::from_str::<ApSignature>(text).ok()?;
let mut json = serde_json::from_str::<CustomPerson>(text).ok()?;
json.custom_props = ap_sign;
Some(json)
I haven't conducted benchmarking to know whether there is a performance penalty for the (implicit) double-testing using this approach, but if there is a penalty it should be small.
and_then
is basically a match expression that calls the passed function with the value of T
if self
is Ok(T)
and bypasses self
if it is Err(E)
, so you don't avoid anything there.
The and_then
example doesn't work very well here because the value extraction can't be done in a fully stream-like fashion. To work around that without creating new variables (which is useless in itself) you have to do all that ugly indenting stuff that makes the code more difficult to read. The only thing you gain with that approach is not calling ok()
multiple times, but again, I think the real solution is to change the return type of the function.
BTW I don't think losing information about Err
is a good idea, unless you are micro-optimizing hard on memory usage and transfers for a very good reason.
You can use
?
in amatch
expiration too.match req? {
}