Your approach will work, I guess. One possibly nicer approach (because it has a chance of not needing to zero-initialize memory) might be
let mut x = Vec::with_capacity(n);
(&mut reader).take(n as u64).read_to_end(&mut x);
return x;
though I'm not actually entirely certain which of the two approaches is "the correct way" or the best way; or if there's another alternative I've missed.
In general, Rust libraries try to avoid allocating buffers unless they need to instead preferring to accept a &mut [u8] argument. That way the caller can choose when the allocations are done, read data into a sub-section of some larger buffer, and reuse the same buffer across multiple calls.