By limiting yourself to the standard library at first, I find that you can get a good feel for the language itself.
You could look up some of the published solutions from last year to get a feel for what is possible.
Example: https://github.com/bertptrs/adventofcode/tree/master/2018/sr...
This person kept a minimal common library for recurring functionality and a small wrapper application that launches the code for each puzzle. It looks like a really clean approach.
i.e. pass the input from standard input, and just build an on-the-go Vector of some data type that is appropriate for the problem at hand. Day 3 was different from 1 and 2 in that for the first time the parsing was not immediate; using Serde and Recap modules did a fantastically succinct job of parsing the text input. Of course it depends on how much you want to rely on external crates.
Let's see if this year I can do more than 3 days worth of AoC :-)
Also had a good learning experience using the nom parser combinator package [0], but this takes a bit of code (that you can often reuse between days).
If you are aiming for fast solutions, the !scan macro of serde-scan [1] is made for exactly this, but then you are far outside the core language...
[0]: https://crates.io/crates/nom [1]: https://docs.rs/serde_scan/0.3.2/serde_scan/macro.scan.html
Last year I asked the same, and I found this answer on SO:
https://stackoverflow.com/questions/31046763/does-rust-have-...
See the answer which mentions the "text_io" crete.
As I recall, most of the time the input is delineated by spaces or linebreaks and it helps if you can carve it up easily right off the bat.