block: qcow: Consolidate BE file I/O with BeUint trait - #7637
Conversation
| fn write_refcount<T: BeUint>(file: &mut RawFile, table: &[u64]) -> io::Result<()> { | ||
| fn write_refcount<T: BeUint + TryFrom<u64>>(file: &mut RawFile, table: &[u64]) -> io::Result<()> | ||
| where | ||
| <T as TryFrom<u64>>::Error: std::fmt::Debug, |
There was a problem hiding this comment.
nit: I prefer to use Debug here with a use statement in the top
| let bytes_per_entry = size_of::<T>(); | ||
| let mut buffer = BufWriter::with_capacity(table.len() * bytes_per_entry, file); | ||
| for &val in table { | ||
| T::write(&mut buffer, val)?; | ||
| T::write(&mut buffer, T::try_from(val).unwrap())?; |
There was a problem hiding this comment.
Please use expect("should <explain condition why this should be okay>) here or a comment explaining why this can never panic.
It is currently not clear to me from reading the code why this won't fail on the happy path or won't fail at all
There was a problem hiding this comment.
Added an expect, which seems better than a comment as it can catch a bug. For the refcount validation, please see mod.rs around lines 116 and 1171 throwing RefcountOverflow. Thus the downcast is expected to be safe.
Thanks
| @@ -40,8 +46,12 @@ impl BeUint for u16 { | |||
| u16::from_be_bytes([bytes[0], bytes[1]]) as u64 | |||
| } | |||
| #[inline(always)] | |||
| fn write<W: Write>(w: &mut W, val: u64) -> io::Result<()> { | |||
| w.write_u16::<BigEndian>(val as u16) | |||
| fn read<R: Read>(r: &mut R) -> io::Result<Self> { | |||
There was a problem hiding this comment.
I would strongly prefer to make sure these methods include _be in the name - so it's very apparent from the call side the endianness.
There was a problem hiding this comment.
Right, I see now also u64::write is unclear, as the trait only imported at the top but the connection is not obvious. Did the renames now. Thanks
phip1611
left a comment
There was a problem hiding this comment.
LGTM now! Left a nit, feel free to address.
| @@ -18,9 +19,10 @@ type RefcountReader = fn(&mut RawFile, usize) -> io::Result<Vec<u64>>; | |||
| type RefcountWriter = fn(&mut RawFile, &[u64]) -> io::Result<()>; | |||
|
|
|||
| /// Big-endian file access trait. | |||
| trait BeUint: Sized + Copy { | |||
| pub trait BeUint: Sized + Copy { | |||
There was a problem hiding this comment.
the commit message says
BeUint trait and make it pub so it can be
used across the qcow module.
so this line could also be pub(super) trait BeUint: ...
There was a problem hiding this comment.
Good that you notice. I was considering that but saw other structs being just pub so did alike. Fixed tihs. Thanks!
Add a read_be() method to the BeUint trait and make it pub(super) so it can be used across the qcow module. Change BeUint::write_be() to take Self instead of u64, providing type safety through TryFrom conversion. Suggested-by: Rob Bradford <[email protected]> Signed-off-by: Anatol Belski <[email protected]>
| fn write_u32_to_file<F: Write>(f: &mut F, value: u32) -> Result<()> { | ||
| f.write_u32::<BigEndian>(value) | ||
| .map_err(Error::WritingHeader) | ||
| fn write_u32<F: Write>(f: &mut F, value: u32) -> Result<()> { |
There was a problem hiding this comment.
Sorry, I should have been clearer. I still think that calling this write_u32_be would just be safer for readability. I know the original code didn't do that but I think this is an opportunity to improve that.
There was a problem hiding this comment.
Sure, renamed the local helpers to include the _be suffix as well. Checked - everything I touched here has the suffix now. Thanks
Update QcowHeader and other related places to use BeUint methods internally for reading/writing header fields. This removes the byteorder dependency from mod.rs and consolidates all big-endian file I/O through the shared BeUint trait. Suggested-by: Rob Bradford <[email protected]> Signed-off-by: Anatol Belski <[email protected]>
Extend the
BeUinttrait with aread_be()method and make itpub(super)so it can be used across the qcow module. ChangeBeUint::write_be()to takeSelfinstead ofu64, providing type safety throughTryFromconversion.Update
QcowHeaderand other related places to useBeUintmethods internally for reading/writing header fields.This removes the
byteorderdependency from mod.rs and consolidates all big-endian file I/O through the sharedBeUinttrait.Suggested-by: Rob Bradford [email protected]