1 00:00:00,340 --> 00:00:02,919 In this video, we will learn how to 2 00:00:02,919 --> 00:00:05,830 handle errors gracefully as part of 3 00:00:05,830 --> 00:00:08,740 Rust's emphasis on safety, you will get a 4 00:00:08,740 --> 00:00:10,870 warning if you don't do something with a 5 00:00:10,870 --> 00:00:13,240 result enum you receive, because the 6 00:00:13,240 --> 00:00:15,700 result might be an error. We've already 7 00:00:15,700 --> 00:00:18,460 seen two ways to handle errors, call 8 00:00:18,460 --> 00:00:21,429 unwrap and let the program crash if it 9 00:00:21,429 --> 00:00:24,039 hits an error, and using a match 10 00:00:24,039 --> 00:00:26,919 expression to handle the error in a 11 00:00:26,919 --> 00:00:29,890 match arm. This is one of the areas where 12 00:00:29,890 --> 00:00:32,680 Rust really excels at making life better, 13 00:00:32,680 --> 00:00:35,470 because when you handle errors that can 14 00:00:35,470 --> 00:00:37,390 occur, you don't have to spend hours 15 00:00:37,390 --> 00:00:40,600 later trying to reproduce a rare crash 16 00:00:40,600 --> 00:00:43,390 just to discover that it was because you 17 00:00:43,390 --> 00:00:45,880 forgot to handle an error somewhere, and 18 00:00:45,880 --> 00:00:47,860 the program proceeded a good way down 19 00:00:47,860 --> 00:00:49,660 the execution path before bad things 20 00:00:49,660 --> 00:00:52,780 happened. Let's explore some ways to 21 00:00:52,780 --> 00:00:55,840 handle errors gracefully. Let's review 22 00:00:55,840 --> 00:00:58,810 the result enum. This is the definition 23 00:00:58,810 --> 00:01:01,210 of result from the standard library, it 24 00:01:01,210 --> 00:01:03,610 takes two generic types and wraps the 25 00:01:03,610 --> 00:01:06,608 success value in okay, and the error type 26 00:01:06,608 --> 00:01:09,850 in error. Rust wants you to program 27 00:01:09,850 --> 00:01:12,820 safely, since result could be an error, 28 00:01:12,820 --> 00:01:15,969 it's been annotated with the must use 29 00:01:15,969 --> 00:01:18,729 attribute, which means the compiler will 30 00:01:18,729 --> 00:01:21,369 warn you if you get a result enum and 31 00:01:21,369 --> 00:01:24,490 don't do anything with it. Here's the 32 00:01:24,490 --> 00:01:27,069 standard out struct, let's scroll down and 33 00:01:27,069 --> 00:01:28,450 take a look at the write trait 34 00:01:28,450 --> 00:01:31,569 implementation of the write all method. 35 00:01:31,569 --> 00:01:34,270 This method returns a result but it 36 00:01:34,270 --> 00:01:34,929 looks funny, 37 00:01:34,929 --> 00:01:37,409 it only takes a unit type. Why is that? 38 00:01:37,409 --> 00:01:40,539 Because this result is actually a type 39 00:01:40,539 --> 00:01:43,359 def let's take a look, it passes through 40 00:01:43,359 --> 00:01:46,719 the type T but it always uses this type 41 00:01:46,719 --> 00:01:49,630 of error, which is the I/O library's 42 00:01:49,630 --> 00:01:52,359 error. let's take a look at that. There's 43 00:01:52,359 --> 00:01:54,280 three things I want to point out here. 44 00:01:54,280 --> 00:01:57,909 First this error is a strut that's used 45 00:01:57,909 --> 00:02:00,459 throughout the I/O library, second it has 46 00:02:00,459 --> 00:02:02,619 a two string method that will give you a 47 00:02:02,619 --> 00:02:04,450 message, and third it's got this error 48 00:02:04,450 --> 00:02:07,899 kind enum with all of the variants for 49 00:02:07,899 --> 00:02:10,470 every possible error we could care about. 50 00:02:10,470 --> 00:02:13,360 Let's drill down into the error kind 51 00:02:13,360 --> 00:02:14,169 enum and take a peek. 52 00:02:14,169 --> 00:02:17,290 Get the variance, there's a long list of 53 00:02:17,290 --> 00:02:19,239 variance for the most part we're going 54 00:02:19,239 --> 00:02:21,459 to consider these variances fatal, 55 00:02:21,459 --> 00:02:23,920 there is one though that we're going to 56 00:02:23,920 --> 00:02:25,989 catch and ignore and that's the broken 57 00:02:25,989 --> 00:02:28,450 pipe error, since we're actually going to 58 00:02:28,450 --> 00:02:30,430 be dealing with pipes a lot and they 59 00:02:30,430 --> 00:02:33,040 tend to break when they end, we're going 60 00:02:33,040 --> 00:02:34,870 to just catch that condition and ignore 61 00:02:34,870 --> 00:02:37,900 it. One nice thing about Rust is that the 62 00:02:37,900 --> 00:02:40,989 main function can return result, we just 63 00:02:40,989 --> 00:02:43,959 need to import result, and then return a 64 00:02:43,959 --> 00:02:47,410 result from the main function. Then we 65 00:02:47,410 --> 00:02:49,209 need to go to unto the end of main and 66 00:02:49,209 --> 00:02:52,299 return an okay. Since we only care about 67 00:02:52,299 --> 00:02:55,060 the result up here if it's an error, we 68 00:02:55,060 --> 00:02:56,980 can use an if let's statement with a 69 00:02:56,980 --> 00:03:00,190 pattern to match the error, then let's 70 00:03:00,190 --> 00:03:03,489 return this error from main, and see how 71 00:03:03,489 --> 00:03:06,190 the Rust handles it when we return an 72 00:03:06,190 --> 00:03:09,640 error from main. I'm going to use the yes 73 00:03:09,640 --> 00:03:11,920 utility to print an infinite number of 74 00:03:11,920 --> 00:03:15,250 y's, then I'm going to pipe that to Cargo 75 00:03:15,250 --> 00:03:17,799 run to have some continuous input, and 76 00:03:17,799 --> 00:03:20,260 then I'm going to pipe our program's 77 00:03:20,260 --> 00:03:23,799 output to head, but I'm gonna tell head 78 00:03:23,799 --> 00:03:25,840 to only accept one line and then close 79 00:03:25,840 --> 00:03:28,600 it standard in, which will cause us to 80 00:03:28,600 --> 00:03:31,329 get a broken pipe error, and here we can 81 00:03:31,329 --> 00:03:33,790 see Russ default handling, it shows error 82 00:03:33,790 --> 00:03:36,040 code 32 and it formatted this nice 83 00:03:36,040 --> 00:03:38,769 message for us. But wait this is such a 84 00:03:38,769 --> 00:03:41,079 common thing to do that we made a syntax 85 00:03:41,079 --> 00:03:43,720 just for it, replace all of that with 86 00:03:43,720 --> 00:03:46,060 just a question mark, and it does exactly 87 00:03:46,060 --> 00:03:50,130 the same thing, check it out. 88 00:03:50,130 --> 00:03:53,890 Exactly the same behavior I'm going to 89 00:03:53,890 --> 00:03:55,930 go ahead and undo this because I want to 90 00:03:55,930 --> 00:03:57,790 treat the broken pipe as something 91 00:03:57,790 --> 00:04:00,280 normal and not as an error. So I'm going 92 00:04:00,280 --> 00:04:03,370 to check for it right here. First I need 93 00:04:03,370 --> 00:04:07,290 to go up in import error kind, 94 00:04:07,290 --> 00:04:09,390 then I can use error kind and grab the 95 00:04:09,390 --> 00:04:11,819 variant that I want, which is the broken 96 00:04:11,819 --> 00:04:14,849 pipe variant, and then if I see that then 97 00:04:14,849 --> 00:04:17,608 I can break out of this, and just end 98 00:04:17,608 --> 00:04:21,060 normally. Let's take a look, we'll go ahead 99 00:04:21,060 --> 00:04:23,759 and run it again and we get ninety-eight 100 00:04:23,759 --> 00:04:25,350 thousand three hundred and four yeses 101 00:04:25,350 --> 00:04:28,019 that get through. For us a broken pipe is 102 00:04:28,019 --> 00:04:30,419 normal so we ignored it and ended like 103 00:04:30,419 --> 00:04:32,880 usual. Of course, we could have just 104 00:04:32,880 --> 00:04:34,979 handled this all ourselves if we just 105 00:04:34,979 --> 00:04:37,500 comment out the return, we can print to 106 00:04:37,500 --> 00:04:38,970 standard error and choose our own 107 00:04:38,970 --> 00:04:41,669 message, we can choose our own string 108 00:04:41,669 --> 00:04:44,099 representation of the string, in this 109 00:04:44,099 --> 00:04:47,009 case I'll just use the built-in one if 110 00:04:47,009 --> 00:04:49,349 you call two string, and we can choose 111 00:04:49,349 --> 00:04:51,479 our own return code and it can be whatever 112 00:04:51,479 --> 00:04:54,419 we want, so if go standard process exit 113 00:04:54,419 --> 00:04:57,000 I'll choose one, then to see the error 114 00:04:57,000 --> 00:04:59,250 I'll need to comment out our skipping 115 00:04:59,250 --> 00:05:01,919 the error, so we actually hit it, and then 116 00:05:01,919 --> 00:05:04,349 when we run it we see our custom error 117 00:05:04,349 --> 00:05:06,539 down here. Now that I've demonstrated 118 00:05:06,539 --> 00:05:08,639 that I'd like to go back to what I had 119 00:05:08,639 --> 00:05:10,680 before, because I actually liked that how 120 00:05:10,680 --> 00:05:13,409 it was. Now let's go do a little bit of 121 00:05:13,409 --> 00:05:16,289 cleanup, we go up here. Let's take this 122 00:05:16,289 --> 00:05:19,199 buffer and put it outside the loop, so we 123 00:05:19,199 --> 00:05:21,120 just create it once instead of every 124 00:05:21,120 --> 00:05:22,740 time to the loop and run it one more 125 00:05:22,740 --> 00:05:24,180 time to make sure we have a messed 126 00:05:24,180 --> 00:05:27,000 anything up. Okay good, let's play with 127 00:05:27,000 --> 00:05:29,159 the output a little bit now. I'm going to 128 00:05:29,159 --> 00:05:31,139 use the carriage return to return the 129 00:05:31,139 --> 00:05:33,210 cursor to the beginning of the line, and 130 00:05:33,210 --> 00:05:35,490 I'm going to take this and put the 131 00:05:35,490 --> 00:05:38,400 output inside the loop, so every time we 132 00:05:38,400 --> 00:05:39,840 go around the loop we're gonna do some 133 00:05:39,840 --> 00:05:42,030 output which is why and what the cursor 134 00:05:42,030 --> 00:05:45,120 to return to the start of the line, so 135 00:05:45,120 --> 00:05:48,270 that overwrites the previous value. So 136 00:05:48,270 --> 00:05:49,919 let's go try it out we shouldn't see 137 00:05:49,919 --> 00:05:52,139 much difference. Okay it was so fast we 138 00:05:52,139 --> 00:05:53,639 didn't see any difference at all, so we 139 00:05:53,639 --> 00:05:55,229 needed to do something so we can see it, 140 00:05:55,229 --> 00:05:57,570 so let's go back and let's do a hundred 141 00:05:57,570 --> 00:06:00,449 million, and yeah we can tell it's 142 00:06:00,449 --> 00:06:02,340 definitely working going back and 143 00:06:02,340 --> 00:06:04,680 rewriting itself. And that's it for this 144 00:06:04,680 --> 00:06:07,830 video. In the next video, we will learn 145 00:06:07,830 --> 00:06:09,810 how to handle command-line arguments 146 00:06:09,810 --> 00:06:14,810 with the clap library.