Yep, exactly. You can actually look at their source code, it should be very good for learning.
Rust Error Handling and Rust in General is still a big black box for me yet to be unveiled :D
Conceptually, error handling in Rust is incredibly simple: if a function can fail, its return type is an enum of either the result of the function (in case of success) or a description of the error that happened. This enum is called Result. See:
- https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html
- https://doc.rust-lang.org/rust-by-example/error/result/early_returns.html
- https://doc.rust-lang.org/book/ch02-00-guessing-game-tutorial.html#handling-potential-failure-with-result
why do i need crates for error handling?
You don't. You can 100% handle errors without any additional dependencies, and probably you should be doing that in the beginning. The crates simply add a little bit of syntactic sugar to simplify some boilerplate that you'll have to start writing as soon as your error handling gets sufficiently complex.
Welcome to Rust, I hope you enjoyed learning and using it :)
One major advice would be to run cargo clippy, which gives a lot of helpful hints. Apart from that I also have some feedback.
40 struct VendorOuiData {
41 vendor_organization: String, // Vendor Organization
These comments should be doc-comments (///) so that cargo doc picks them up.
49 fn fetch_oui_database(url_string: &String) -> Result<String, Box<dyn std::error::Error>> {
Not saying that your return type is bad, but in general you might be interested in crates thiserror and anyhow that simplify error handling.
51 .timeout(Duration::new(60, 0))
Duration::from_mins(1) would be much more readable.
66 panic!("{}", err);
You should almost never panic. Your function already returns a Result<>, so you should be using that for error handling.
70 } else {
71 // HTTP Status is not 200
Not Rust specific, but usually I recommend to handle errors first, and return from the function early. This way you reduce cognitive load on the reader, and reduce nesting of if-blocks.
150 let mut parts = line.splitn(2, '\t');
There's a convenient method to split in two substrings that you could have used:
let (mac_address, vendor_organization) = line.split_once('\t').unwrap_or(("", ""));
166 vendor_oui_data.vendor_address += line
167 .trim()
168 .split(' ')
169 .filter(|s| !s.is_empty())
170 .collect::<Vec<_>>()
171 .join(" ")
172 .as_str();
I would probably write a regular expression that replaces all contiguous whitespace with a single space instead.
173 vendor_oui_data.vendor_address.push('\n');
Aren't you trimming this new line off in line 181?
181 vendor_oui_data.vendor_address = vendor_oui_data.vendor_address.trim().to_string();
This is somewhat inefficient, since you'll be allocating and copying your string here.
That’s a very interesting thought! I was thinking of writing my own Rust data type that would automatically upgrade to big integer, similarly to the int type in Python.
Just needs a bit of formal languages theory, but otherwise the algorithm is fairly simple. Here’s my code if you decide to look at it at some point: https://github.com/hades/aoc2015/blob/master/dec19.cc
Christmas, I guess :) (I just pick a random colour each time a roll is removed)
Day 7 (zoom to full screen): https://lgbt.earth/i/web/post/903381501524320591
I can probably improve this a lot, but I was afraid I'll be too lazy after getting this far, so posting as is. Still, lmk if you have any suggestions :)
That's day 7, right?
Apart from day 4 not much to visualise so far this year :/
it all fit in int64 tho, so could be worse