1 00:00:06,660 --> 00:00:10,260 - As applications get larger, and Rust is no exception, 2 00:00:10,260 --> 00:00:12,930 it becomes important to start thinking about 3 00:00:12,930 --> 00:00:15,060 how you're gonna organize your application 4 00:00:15,060 --> 00:00:19,050 into separate files and separate data types. 5 00:00:19,050 --> 00:00:20,583 So things to consider. 6 00:00:21,900 --> 00:00:23,310 How are you gonna split your application 7 00:00:23,310 --> 00:00:27,030 into different files or modules in Rust? 8 00:00:27,030 --> 00:00:29,400 What data types do we need in the application 9 00:00:29,400 --> 00:00:33,210 in order to, you know, congeal data cohesively 10 00:00:33,210 --> 00:00:35,640 and do proper structures? 11 00:00:35,640 --> 00:00:38,460 Are there any additional libraries, or crates, 12 00:00:38,460 --> 00:00:42,450 as Rust would say, that we need to add into our application? 13 00:00:42,450 --> 00:00:45,120 So let's take a look at our application 14 00:00:45,120 --> 00:00:47,400 with those things in mind. 15 00:00:47,400 --> 00:00:49,670 We're going to take a bit of a closer look now 16 00:00:49,670 --> 00:00:52,140 at the source files in the application. 17 00:00:52,140 --> 00:00:54,420 So we're gonna have a look at main.rs first. 18 00:00:54,420 --> 00:00:56,160 We've already had a quick look at that. 19 00:00:56,160 --> 00:00:58,290 Then we'll have a look at types.rs, 20 00:00:58,290 --> 00:01:00,630 where we define structures that we need 21 00:01:00,630 --> 00:01:02,880 to represent the data in our application, 22 00:01:02,880 --> 00:01:05,940 like visit, for example, to Europe. 23 00:01:05,940 --> 00:01:07,170 Then we'll have a look at util. 24 00:01:07,170 --> 00:01:08,850 I'm not gonna go into the details yet, 25 00:01:08,850 --> 00:01:12,300 I'm just gonna discuss the broad intent. 26 00:01:12,300 --> 00:01:16,980 Util.rs defines some miscellaneous utility functions, 27 00:01:16,980 --> 00:01:20,460 getting stuff in the keyboard, handling dates and times, 28 00:01:20,460 --> 00:01:23,583 miscellaneous utility, things like that. 29 00:01:24,660 --> 00:01:27,870 File handling in fh.rs. 30 00:01:27,870 --> 00:01:30,450 And then the menu.rs, 31 00:01:30,450 --> 00:01:31,620 which displays our menu 32 00:01:31,620 --> 00:01:33,720 and keeps on redisplaying the menu 33 00:01:33,720 --> 00:01:36,060 until the user chooses to quit. 34 00:01:36,060 --> 00:01:38,160 Okay, so we'll have a look at all of these files. 35 00:01:38,160 --> 00:01:40,590 I will also have a quick look at the toml file 36 00:01:40,590 --> 00:01:44,313 to see what other crates our application requires. 37 00:01:45,540 --> 00:01:47,490 Okay, so here we are then. 38 00:01:47,490 --> 00:01:50,160 In main.rs first of all, 39 00:01:50,160 --> 00:01:53,400 we have already seen this in the last code walkthrough. 40 00:01:53,400 --> 00:01:56,850 So it defines four modules, 41 00:01:56,850 --> 00:01:59,730 which are defined in separate files, 42 00:01:59,730 --> 00:02:04,470 types.rs and it defines util.rs 43 00:02:04,470 --> 00:02:06,720 and module and main. 44 00:02:06,720 --> 00:02:10,890 So let's have a look first of all, in types, 45 00:02:10,890 --> 00:02:13,260 that's the first module that we define. 46 00:02:13,260 --> 00:02:16,140 It defines common structures and maybe other types, 47 00:02:16,140 --> 00:02:20,013 like enums and traits that are used in application. 48 00:02:22,470 --> 00:02:26,583 Okay, so here we are. 49 00:02:27,900 --> 00:02:32,463 Interesting, lots of different details here. 50 00:02:34,200 --> 00:02:38,133 Obviously we're gonna dive into the details later on. 51 00:02:39,000 --> 00:02:41,040 So I'm just gonna give you the big picture now. 52 00:02:41,040 --> 00:02:44,283 So you've got this kind of image of where we're heading to. 53 00:02:45,900 --> 00:02:46,733 A visit. 54 00:02:47,940 --> 00:02:50,340 The visit structure contains information 55 00:02:50,340 --> 00:02:53,430 about a visit to Europe, 56 00:02:53,430 --> 00:02:57,840 is public so I can use it in other files. 57 00:02:57,840 --> 00:03:01,440 It defines the data for a visit, the start date 58 00:03:01,440 --> 00:03:03,630 the end date, and the description. 59 00:03:03,630 --> 00:03:07,980 I've used a class or structure called naive date, okay? 60 00:03:07,980 --> 00:03:11,040 Naive date is defined in the chrono crate. 61 00:03:11,040 --> 00:03:13,200 Naive date represents, 62 00:03:13,200 --> 00:03:14,820 it's not that naive really. 63 00:03:14,820 --> 00:03:16,650 You'd think with a name like naive date 64 00:03:16,650 --> 00:03:19,440 you wouldn't wanna use it because it's naive, 65 00:03:19,440 --> 00:03:20,730 but it's naive in the sense 66 00:03:20,730 --> 00:03:22,680 that it doesn't have a time zone. 67 00:03:22,680 --> 00:03:26,280 Okay, but apart from that, it's perfectly usable. 68 00:03:26,280 --> 00:03:28,740 So if you're not interested in time zones 69 00:03:28,740 --> 00:03:30,990 in your date handling, use naive date. 70 00:03:30,990 --> 00:03:32,790 It's by far the simplest way. 71 00:03:32,790 --> 00:03:37,203 So the visit structure represents, as read from the file, 72 00:03:38,284 --> 00:03:39,870 a visit to Europe. 73 00:03:39,870 --> 00:03:41,370 What date did you visit? 74 00:03:41,370 --> 00:03:44,220 What was the end date, or the day after you came back, 75 00:03:44,220 --> 00:03:46,290 and the description of the visit? 76 00:03:46,290 --> 00:03:48,240 And then I've got some functionality 77 00:03:48,240 --> 00:03:52,530 associated with the visit structure as well, okay? 78 00:03:52,530 --> 00:03:56,160 And we'll have a look at these functions later on, 79 00:03:56,160 --> 00:03:57,210 but you can see that it has, 80 00:03:57,210 --> 00:04:00,060 it's quite a simple structure really. 81 00:04:00,060 --> 00:04:03,033 So we'll have a look at the details of that in due course. 82 00:04:04,170 --> 00:04:09,170 Oh, also the visit structure implements the display trait. 83 00:04:09,330 --> 00:04:11,520 Remember the display trait? 84 00:04:11,520 --> 00:04:13,620 If a structure implements display 85 00:04:13,620 --> 00:04:16,170 then you can output it using the default formatter 86 00:04:16,170 --> 00:04:17,127 in println. 87 00:04:17,127 --> 00:04:20,160 You can say println, curly brackets, visit 88 00:04:20,160 --> 00:04:23,400 and it'll call the display formatting to output. 89 00:04:23,400 --> 00:04:27,633 It's like a two sprint basically for the visit structure. 90 00:04:28,650 --> 00:04:31,890 I've also got another structure called record. 91 00:04:31,890 --> 00:04:34,620 The reason for that would become apparent later on. 92 00:04:34,620 --> 00:04:35,970 It defines some data. 93 00:04:35,970 --> 00:04:39,090 Oh, it automatically supports the eq 94 00:04:39,090 --> 00:04:41,010 and the partial eq traits. 95 00:04:41,010 --> 00:04:42,630 Remember those from before? 96 00:04:42,630 --> 00:04:46,080 That gives you the ability to say less than or greater than, 97 00:04:46,080 --> 00:04:48,480 less than or equal to, greater than or equal to. 98 00:04:50,070 --> 00:04:53,520 So there's implementation 99 00:04:53,520 --> 00:04:58,230 and then it implements the display trait to be displayed. 100 00:04:58,230 --> 00:05:01,320 And it implements a couple of other traits as well. 101 00:05:01,320 --> 00:05:04,260 I've gone to really like the way 102 00:05:04,260 --> 00:05:08,790 that Rust splits trait implementations into separate slices. 103 00:05:08,790 --> 00:05:11,820 If this is Java or C# or C++, 104 00:05:11,820 --> 00:05:14,580 then you would define a single block of code 105 00:05:14,580 --> 00:05:15,660 that contained all of this, 106 00:05:15,660 --> 00:05:18,060 the data and the functions. 107 00:05:18,060 --> 00:05:21,030 And the functions which implement one interface 108 00:05:21,030 --> 00:05:22,770 and the functions which implement another, 109 00:05:22,770 --> 00:05:25,350 all in one massive class. 110 00:05:25,350 --> 00:05:29,370 Whereas in Rust, it's much more obvious. 111 00:05:29,370 --> 00:05:33,870 This is the implementation of the display trait for record 112 00:05:33,870 --> 00:05:36,480 and this is the implementation of the ord trait 113 00:05:36,480 --> 00:05:37,800 and the partial ord trait. 114 00:05:37,800 --> 00:05:40,920 So it's much more segmented, much more discreet. 115 00:05:40,920 --> 00:05:42,543 So it's quite nice, I think. 116 00:05:43,770 --> 00:05:45,990 So obviously we look at the details of that later, 117 00:05:45,990 --> 00:05:48,273 but that's our types module. 118 00:05:49,170 --> 00:05:52,050 Next up we're gonna look at util. 119 00:05:52,050 --> 00:05:53,580 Here's our util module 120 00:05:53,580 --> 00:05:58,200 and it contains some miscellaneous utility functions, okay? 121 00:05:58,200 --> 00:06:02,430 Nothing strategic, just tactically useful 122 00:06:02,430 --> 00:06:07,430 to do some tricky code, hide it into this util module 123 00:06:07,500 --> 00:06:09,360 to parse the command line. 124 00:06:09,360 --> 00:06:11,250 It grabs the parameters in the command line 125 00:06:11,250 --> 00:06:16,020 and it gives me either a string, or nothing, 126 00:06:16,020 --> 00:06:18,843 depending on whether there was a command line or not. 127 00:06:20,070 --> 00:06:21,840 In many cases in the application 128 00:06:21,840 --> 00:06:25,050 I ask the user, please enter a string, okay? 129 00:06:25,050 --> 00:06:26,520 So I've encapsulated that 130 00:06:26,520 --> 00:06:29,580 in a prompt for string function. 131 00:06:29,580 --> 00:06:31,860 There's a message that it displays to the user, 132 00:06:31,860 --> 00:06:34,920 a prompt, please enter something, something, something, 133 00:06:34,920 --> 00:06:39,510 and it returns a string as entered by the user. 134 00:06:39,510 --> 00:06:41,160 There were other times when I asked the user 135 00:06:41,160 --> 00:06:43,410 to enter a date, okay? 136 00:06:43,410 --> 00:06:47,220 So like, what start date would you like to specify? 137 00:06:47,220 --> 00:06:49,590 So it displays a message and it returns a date, 138 00:06:49,590 --> 00:06:52,020 or rather a naive date without time zone, 139 00:06:52,020 --> 00:06:54,750 like the 31st of December. 140 00:06:54,750 --> 00:06:57,300 And then a conversion function. 141 00:06:57,300 --> 00:07:02,300 I pass in a string or a string slice, 142 00:07:03,240 --> 00:07:06,690 and it'll convert it or parse it into a date. 143 00:07:06,690 --> 00:07:10,080 It's like a date parser, really. 144 00:07:10,080 --> 00:07:13,980 You parse in a string and it parses it 145 00:07:13,980 --> 00:07:18,000 and returns the date that it contains. 146 00:07:18,000 --> 00:07:21,090 So I didn't plan on having these functions, 147 00:07:21,090 --> 00:07:23,640 I just started writing the main body of the code 148 00:07:23,640 --> 00:07:26,340 and often just something fiddly 149 00:07:26,340 --> 00:07:28,380 ends up being five lines of code 150 00:07:28,380 --> 00:07:31,350 just to parse a string for a date. 151 00:07:31,350 --> 00:07:34,050 So at that point, it's useful to push it down 152 00:07:34,050 --> 00:07:37,710 into a function to hide it from the main body of the code. 153 00:07:37,710 --> 00:07:40,830 And also potentially be able to reuse that function 154 00:07:40,830 --> 00:07:41,663 elsewhere. 155 00:07:42,780 --> 00:07:44,580 Okay, so that's util. 156 00:07:44,580 --> 00:07:48,900 The next module we're gonna look at is FH, file handling. 157 00:07:48,900 --> 00:07:50,850 So just two functions in here, 158 00:07:50,850 --> 00:07:53,340 notice they're both public, obviously. 159 00:07:53,340 --> 00:07:56,130 There's a function which will read visits from a file. 160 00:07:56,130 --> 00:07:56,963 This is the function. 161 00:07:56,963 --> 00:07:58,980 It gets (indistinct) called at the start of the application. 162 00:07:58,980 --> 00:08:02,130 Remember, in main when the application starts 163 00:08:02,130 --> 00:08:06,570 from the file module fh, it reads the visits from the file 164 00:08:06,570 --> 00:08:08,670 whatever file name it is, like data.text 165 00:08:08,670 --> 00:08:12,690 and it returns a collection of visit objects 166 00:08:12,690 --> 00:08:14,373 as read from the data file. 167 00:08:16,260 --> 00:08:20,310 Okay, so it takes a file name 168 00:08:20,310 --> 00:08:24,240 and it returns a vector of visit, 169 00:08:24,240 --> 00:08:27,753 where visit is defined in the types module in my crate. 170 00:08:29,640 --> 00:08:31,140 Oh, and then at the end of the application 171 00:08:31,140 --> 00:08:35,070 remember if the user chose to save the data 172 00:08:35,070 --> 00:08:37,320 then at the end of the application in my FH module 173 00:08:37,320 --> 00:08:39,360 it'll write those visits to the file. 174 00:08:39,360 --> 00:08:43,350 It takes the name of the file, it takes the visits data, 175 00:08:43,350 --> 00:08:45,510 as a vector, basically will reference to the vector. 176 00:08:45,510 --> 00:08:50,510 It borrows the vector and writes it to a file. 177 00:08:50,940 --> 00:08:53,790 So inside here, it's got code to take that vector, 178 00:08:53,790 --> 00:08:55,260 it doesn't change the vector, 179 00:08:55,260 --> 00:08:57,210 it just writes it to a file. 180 00:08:57,210 --> 00:09:00,060 And we're gonna look at that later in detail. 181 00:09:00,060 --> 00:09:03,720 Right, so the last thing to look at is the menu module. 182 00:09:03,720 --> 00:09:08,720 And the menu module, let's just collapse this down. 183 00:09:10,260 --> 00:09:12,510 I'm gonna go through this as well in more detail. 184 00:09:12,510 --> 00:09:15,210 I just wanna kinda give you the structure for now 185 00:09:15,210 --> 00:09:17,790 so you kinda get a framework in your mind. 186 00:09:17,790 --> 00:09:20,970 So at the moment, the rule with Schengen 187 00:09:20,970 --> 00:09:24,330 is that the number of days that matter is 180. 188 00:09:24,330 --> 00:09:26,880 You need to go back over the previous 180 days 189 00:09:26,880 --> 00:09:28,350 to count the number of visits. 190 00:09:28,350 --> 00:09:30,150 So I defined that as a constant. 191 00:09:30,150 --> 00:09:33,870 I could've just put the number 180 in my code down below, 192 00:09:33,870 --> 00:09:35,910 but it's much better to declare it as a constant. 193 00:09:35,910 --> 00:09:40,910 It's much more readable and potentially maintainable. 194 00:09:41,370 --> 00:09:44,400 So this is the main do menu function. 195 00:09:44,400 --> 00:09:47,070 That's what I call from main. 196 00:09:47,070 --> 00:09:50,103 Basically when the application starts, it says menu do menu. 197 00:09:51,090 --> 00:09:55,530 So in my menu module, the do menu function, 198 00:09:55,530 --> 00:10:00,060 here is the menu that's gonna be displayed, okay? 199 00:10:00,060 --> 00:10:02,460 I'm not sure if I've mentioned r strings before, 200 00:10:02,460 --> 00:10:03,540 Raw strings. 201 00:10:03,540 --> 00:10:05,583 A raw string is basically, 202 00:10:07,525 --> 00:10:12,525 it's a string that can span multiple lines, okay? 203 00:10:12,540 --> 00:10:15,660 So I don't have to kind of end one line 204 00:10:15,660 --> 00:10:18,570 and then display another line, that's just one string. 205 00:10:18,570 --> 00:10:21,480 And in the string I've got soft count returns. 206 00:10:21,480 --> 00:10:22,950 Those were actually displayed 207 00:10:22,950 --> 00:10:25,470 as count returns in the output. 208 00:10:25,470 --> 00:10:27,700 So my application loops forever 209 00:10:28,560 --> 00:10:30,540 until the user says to quit. 210 00:10:30,540 --> 00:10:31,980 So that's a good example of loop. 211 00:10:31,980 --> 00:10:35,163 Loop forever, until the user says, stop. 212 00:10:36,420 --> 00:10:38,553 In my util module, 213 00:10:39,420 --> 00:10:42,513 there's a prompt to string function that we saw just now. 214 00:10:43,680 --> 00:10:48,270 The message that it displays is this menu, 215 00:10:48,270 --> 00:10:52,710 it'll display that menu on the screen, okay? 216 00:10:52,710 --> 00:10:57,710 And it returns the option selected by the user 217 00:10:58,830 --> 00:11:03,300 which will hopefully be one or two or three or four or five. 218 00:11:03,300 --> 00:11:05,910 So I take that selection as a string 219 00:11:05,910 --> 00:11:09,450 and trim any white space, 220 00:11:09,450 --> 00:11:11,220 and then see what option the user has chosen. 221 00:11:11,220 --> 00:11:12,180 I mean, there were lots of different ways 222 00:11:12,180 --> 00:11:13,013 I could have done this. 223 00:11:13,013 --> 00:11:16,530 If the user chose option one, call this function. 224 00:11:16,530 --> 00:11:20,940 Now these functions are actually here in my menu code. 225 00:11:20,940 --> 00:11:25,710 So if the user chose option two, then that function is here. 226 00:11:25,710 --> 00:11:30,003 If the user chose option three, then that option is here. 227 00:11:30,870 --> 00:11:34,800 Okay, so the code to enforce or to enact those options 228 00:11:34,800 --> 00:11:37,620 is actually here in the same module. 229 00:11:37,620 --> 00:11:41,610 If the user chose option four, then a return true 230 00:11:41,610 --> 00:11:45,900 back to the main code, which means save the data. 231 00:11:45,900 --> 00:11:48,690 If I return false, then it returns back to the main code 232 00:11:48,690 --> 00:11:50,760 and it says, don't save the data. 233 00:11:50,760 --> 00:11:52,650 If the user chooses any other option, 234 00:11:52,650 --> 00:11:53,763 I say, "What? 235 00:11:54,750 --> 00:11:56,373 Okay, and that loops forever. 236 00:11:57,900 --> 00:12:00,390 Right, so there we are. 237 00:12:00,390 --> 00:12:01,830 And then obviously at the end, 238 00:12:01,830 --> 00:12:03,540 it'll choose, if you've returned true, 239 00:12:03,540 --> 00:12:06,060 to save the data back to the file. 240 00:12:06,060 --> 00:12:08,160 So we start to get a feel now 241 00:12:08,160 --> 00:12:11,040 for how the code structure works. 242 00:12:11,040 --> 00:12:13,410 The next steps obviously is to dive into the details 243 00:12:13,410 --> 00:12:14,640 of each of those modules, 244 00:12:14,640 --> 00:12:17,670 and have a closer look at the coding techniques 245 00:12:17,670 --> 00:12:19,020 and the library functions 246 00:12:19,020 --> 00:12:20,920 that I've used to achieve the effects.