mirror of
https://github.com/google/comprehensive-rust.git
synced 2024-12-02 11:03:18 +02:00
Split out example to separate page. (#319)
The example is quite long and so the page didn't easily fit on the same screen as the explanation
This commit is contained in:
parent
20f02db5f5
commit
1be641203e
@ -153,6 +153,7 @@
|
||||
- [Structured Error Handling](error-handling/result.md)
|
||||
- [Propagating Errors with ?](error-handling/try-operator.md)
|
||||
- [Converting Error Types](error-handling/converting-error-types.md)
|
||||
- [Example](error-handling/converting-error-types-example.md)
|
||||
- [Deriving Error Enums](error-handling/deriving-error-enums.md)
|
||||
- [Dynamic Error Types](error-handling/dynamic-errors.md)
|
||||
- [Adding Context to Errors](error-handling/error-contexts.md)
|
||||
|
60
src/error-handling/converting-error-types-example.md
Normal file
60
src/error-handling/converting-error-types-example.md
Normal file
@ -0,0 +1,60 @@
|
||||
# Converting Error Types
|
||||
|
||||
```rust,editable
|
||||
use std::error::Error;
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::fs::{self, File};
|
||||
use std::io::{self, Read};
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ReadUsernameError {
|
||||
IoError(io::Error),
|
||||
EmptyUsername(String),
|
||||
}
|
||||
|
||||
impl Error for ReadUsernameError {}
|
||||
|
||||
impl Display for ReadUsernameError {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::IoError(e) => write!(f, "IO error: {}", e),
|
||||
Self::EmptyUsername(filename) => write!(f, "Found no username in {}", filename),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for ReadUsernameError {
|
||||
fn from(err: io::Error) -> ReadUsernameError {
|
||||
ReadUsernameError::IoError(err)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_username(path: &str) -> Result<String, ReadUsernameError> {
|
||||
let mut username = String::with_capacity(100);
|
||||
File::open(path)?.read_to_string(&mut username)?;
|
||||
if username.is_empty() {
|
||||
return Err(ReadUsernameError::EmptyUsername(String::from(path)));
|
||||
}
|
||||
Ok(username)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
//fs::write("config.dat", "").unwrap();
|
||||
let username = read_username("config.dat");
|
||||
println!("username or error: {username:?}");
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
Key points:
|
||||
|
||||
* The `username` variable can be either `Ok(string)` or `Err(error)`.
|
||||
* Use the `fs::write` call to test out the different scenarios: no file, empty file, file with username.
|
||||
|
||||
It is good practice for all error types to implement `std::error::Error`, which requires `Debug` and
|
||||
`Display`. It's generally helpful for them to implement `Clone` and `Eq` too where possible, to make
|
||||
life easier for tests and consumers of your library. In this case we can't easily do so, because
|
||||
`io::Error` doesn't implement them.
|
||||
|
||||
</details>
|
@ -17,62 +17,3 @@ match expression {
|
||||
|
||||
The `From::from` call here means we attempt to convert the error type to the
|
||||
type returned by the function:
|
||||
|
||||
```rust,editable
|
||||
use std::error::Error;
|
||||
use std::{fs, io};
|
||||
use std::io::Read;
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ReadUsernameError {
|
||||
IoError(io::Error),
|
||||
EmptyUsername(String),
|
||||
}
|
||||
|
||||
impl Error for ReadUsernameError {}
|
||||
|
||||
impl Display for ReadUsernameError {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::IoError(e) => write!(f, "IO error: {}", e),
|
||||
Self::EmptyUsername(filename) => write!(f, "Found no username in {}", filename),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for ReadUsernameError {
|
||||
fn from(err: io::Error) -> ReadUsernameError {
|
||||
ReadUsernameError::IoError(err)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_username(path: &str) -> Result<String, ReadUsernameError> {
|
||||
let mut username = String::with_capacity(100);
|
||||
fs::File::open(path)?.read_to_string(&mut username)?;
|
||||
if username.is_empty() {
|
||||
return Err(ReadUsernameError::EmptyUsername(String::from(path)));
|
||||
}
|
||||
Ok(username)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
//fs::write("config.dat", "").unwrap();
|
||||
let username = read_username("config.dat");
|
||||
println!("username or error: {username:?}");
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
Key points:
|
||||
|
||||
* The `username` variable can be either `Ok(string)` or `Err(error)`.
|
||||
* Use the `fs::write` call to test out the different scenarios: no file, empty file, file with username.
|
||||
|
||||
It is good practice for all error types to implement `std::error::Error`, which requires `Debug` and
|
||||
`Display`. It's generally helpful for them to implement `Clone` and `Eq` too where possible, to make
|
||||
life easier for tests and consumers of your library. In this case we can't easily do so, because
|
||||
`io::Error` doesn't implement them.
|
||||
|
||||
</details>
|
||||
|
Loading…
Reference in New Issue
Block a user