Return Consumed Argument on Error
From: https://rust-unofficial.github.io/patterns/idioms/return-consumed-arg-on-error.html
For better performance, the argument is usually moved into function.
Take the example of String::from_utf8()
:
rust
pub fn from_utf8(vec: Vec<u8>) -> Result<String, SomeError>
But if I need to convert my vec to string after String::from_utf8()
failed:
rust
let res = String::from_utf8(my_vec);
match res {
Ok(s) => println!("utf8 string is {s:?}"),
Err(_) => convert_non_utf8_to_string(my_vec),
}
There is compile error because my_vec
is moved in String::from_utf8()
:
4 | let res = String::from_utf8(my_vec);
| ------ value moved here
...
7 | Err(e) => convert_non_utf8_to_string(my_vec),
| ^^^^^^ value used here after move
|
help: consider cloning the value if the performance cost is acceptable
|
4 | let res = String::from_utf8(my_vec.clone());
| ++++++++
Cloning the my_vec can do but it takes a performance cost.
Luckly String::from_utf8()
returns the original vec on error:
rust
pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error>
rust
// some invalid bytes, in a vector
let bytes = vec![0, 159];
let value = String::from_utf8(bytes);
assert!(value.is_err());
assert_eq!(vec![0, 159], value.unwrap_err().into_bytes());
The trick is: if a fallible function consumes an argument, returns the argument back inside the error.