summaryrefslogtreecommitdiffstats
path: root/src/doc/rust-by-example/src/error/multiple_error_types/define_error_type.md
diff options
context:
space:
mode:
Diffstat (limited to 'src/doc/rust-by-example/src/error/multiple_error_types/define_error_type.md')
-rw-r--r--src/doc/rust-by-example/src/error/multiple_error_types/define_error_type.md68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/doc/rust-by-example/src/error/multiple_error_types/define_error_type.md b/src/doc/rust-by-example/src/error/multiple_error_types/define_error_type.md
new file mode 100644
index 000000000..4c374276d
--- /dev/null
+++ b/src/doc/rust-by-example/src/error/multiple_error_types/define_error_type.md
@@ -0,0 +1,68 @@
+# Defining an error type
+
+Sometimes it simplifies the code to mask all of the different errors with a
+single type of error. We'll show this with a custom error.
+
+Rust allows us to define our own error types. In general, a "good" error type:
+
+* Represents different errors with the same type
+* Presents nice error messages to the user
+* Is easy to compare with other types
+ - Good: `Err(EmptyVec)`
+ - Bad: `Err("Please use a vector with at least one element".to_owned())`
+* Can hold information about the error
+ - Good: `Err(BadChar(c, position))`
+ - Bad: `Err("+ cannot be used here".to_owned())`
+* Composes well with other errors
+
+```rust,editable
+use std::fmt;
+
+type Result<T> = std::result::Result<T, DoubleError>;
+
+// Define our error types. These may be customized for our error handling cases.
+// Now we will be able to write our own errors, defer to an underlying error
+// implementation, or do something in between.
+#[derive(Debug, Clone)]
+struct DoubleError;
+
+// Generation of an error is completely separate from how it is displayed.
+// There's no need to be concerned about cluttering complex logic with the display style.
+//
+// Note that we don't store any extra info about the errors. This means we can't state
+// which string failed to parse without modifying our types to carry that information.
+impl fmt::Display for DoubleError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "invalid first item to double")
+ }
+}
+
+fn double_first(vec: Vec<&str>) -> Result<i32> {
+ vec.first()
+ // Change the error to our new type.
+ .ok_or(DoubleError)
+ .and_then(|s| {
+ s.parse::<i32>()
+ // Update to the new error type here also.
+ .map_err(|_| DoubleError)
+ .map(|i| 2 * i)
+ })
+}
+
+fn print(result: Result<i32>) {
+ match result {
+ Ok(n) => println!("The first doubled is {}", n),
+ Err(e) => println!("Error: {}", e),
+ }
+}
+
+fn main() {
+ let numbers = vec!["42", "93", "18"];
+ let empty = vec![];
+ let strings = vec!["tofu", "93", "18"];
+
+ print(double_first(numbers));
+ print(double_first(empty));
+ print(double_first(strings));
+}
+```