Just finished chapter 10 of the Rust book and I thought I’d try digging into some real code. I’m a rust noob, but I’ve got 15 years with embedded C.
I’m working my way through the source code of the stm32l0xx-hal crate. Inside adc.rs on line 96, an implementation for the Adc struct is created for the type Adc<Ready> where Ready is defined on line 324.
/// Analog to Digital converter interface
pub struct Adc<State> {
rb: ADC,
sample_time: SampleTime,
align: Align,
precision: Precision,
_state: State,
}
impl Adc<Ready> {
pub fn new(adc: ADC, rcc: &mut Rcc) -> Self {
// Enable ADC clocks
ADC::enable(rcc);
adc.cr.modify(|_, w| w.advregen().set_bit());
Self {
rb: adc,
sample_time: SampleTime::T_1_5,
align: Align::Right,
precision: Precision::B_12,
_state: Ready,
}
}
...
}
...
/// Indicates that the ADC peripheral is ready
pub struct Ready;
I’m a little confused about how the associated function new() works. I understand that it generates a new Adc<Ready>, but I don’t fully understand why it’s inside the impl Adc<Ready> block.
It’s not a method that would be called on an Adc<Ready> type, and it doesn’t take any arguments of type Ready. Couldn’t it just as easily have been inside a impl<T> Adc<T> block?
Or is it that impl types go both ways. Like you can’t return an Adc<Ready> unless you’re inside an impl Adc<Ready>?
Sidenote: Since the Ready struct has no fields, does “Ready” actually create a new instance of a Ready type? (like you don’t need Ready{}?)


Yeah, I mean, you’ve got previous programming experience. You evidently know that you’re tackling a harder problem and probably know when to step back and try an easier problem first, if it becomes too frustrating. I just wanted to give a bit of context, so that you know it’s more exotic knowledge, because that’s not always going to be obvious when learning a new language…
Oh I super appreciate the advice. Thanks!