-
Notifications
You must be signed in to change notification settings - Fork 0
Improve dump subcommand. #162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
e679734
to
408e711
Compare
Fixes <#160>.
353fbe6
to
482151e
Compare
Depends on oxidecomputer/amd-apcb#115 and will not build until that one is merged. |
013d690
to
a8e64fe
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dummy dump at the end is a good idea. I didn't look at the serde stuff because it's beyond my feeble mind.
amd-apcb = { git = "https://github.com/oxidecomputer/amd-apcb.git", branch = "issue-113", features = ["std", "serde", "schemars"] } | ||
amd-efs = { git = "ssh://[email protected]/oxidecomputer/amd-efs.git", branch = "issue-99", features = ["std", "serde", "schemars"] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's so the github CI and thus buildomat can build it. Otherwise all we'd see is a build failure.
But yeah, definitely not merge it like that.
amd-apcb = { git = "https://github.com/oxidecomputer/amd-apcb.git", branch = "issue-113", features = ["std", "serde", "schemars"] } | ||
amd-efs = { git = "ssh://[email protected]/oxidecomputer/amd-efs.git", branch = "issue-99", features = ["std", "serde", "schemars"] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise.
@@ -735,25 +772,48 @@ fn dump( | |||
if filesize <= 0x100_0000 { Some(filesize as u32) } else { None }; | |||
let efs = Efs::load(&storage, None, amd_physical_mode_mmio_size).unwrap(); | |||
if !efs.compatible_with_processor_generation(ProcessorGeneration::Milan) { | |||
panic!("only Milan is supported for dumping right now"); | |||
if !efs.compatible_with_processor_generation(ProcessorGeneration::Rome) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Surely this could be phrased as a compound condition. Is there a reason not to?
fallback: T, | ||
result_text: &str, | ||
) -> T { | ||
match result { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is unwrap_or_else
, isn't it? E.g.,
result.unwrap_or_else(|e| { eprintln!("{result_text} was invalid: {e}. Falling back to default"); default })
impl std::fmt::Display for PathNode { | ||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||
match self.next { | ||
Some(ref x) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would phrase this as an if let
. E.g.,
if let Some(ref x) = self.next {
x.fmt(f)?;
write!(f, "/")?;
}
} | ||
} | ||
|
||
type Ok = (); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How/where is this used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of the serializer impls use it (type Ok = Ok
), for example impl<'a> ser::Serializer for &'a mut DummySerializer
in line 238.
I didn't want to repeat the concrete respective Ok
and Error
types in each of the ~20 impls, so I introduced global type aliases Ok
and Error
.
Since the custom serializer only exists to find errors (and not serialize into anything), Ok = ()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps then use it on lines 70, 88, 104, 124, 149, 193, and 216 as well? And any other places that I missed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed!
Changed.
Some background: I wasn't sure whether I'd have to thread through the error infos (path and raw value of unknown thing in zerocopy struct) in the Ok variant--so this is why this is parametrizable in the first place.
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { | ||
eprintln!( | ||
"{}: skipped field {}", | ||
match self.path { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is unwrap_or_default
, I think. You may need a map
first. e.g., self.path.map(|p| p.to_string()).unwrap_or_default()
.
T: Serialize, | ||
{ | ||
value.serialize(&mut DummySerializer { | ||
path: self.path.clone(), // FIXME check |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the comment refer to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, this is doing path building inside the virtual json (or whatever it is it's serializing to). The path to the json node is then printed on error.
All those path: self.path.clone() // FIXME
is supposed to allude to that this specific combination wasn't tested yet.
For example, if you are in DummySerializer and do serialize_seq
, should that introduce a path element (representing the entire seq)? Probably not, but I've learned to check. Also, I'm not sure whether all Rust upstream serializers do it the same way. I think serde json does some flattening--and I guess we should just adapt to what serde json does, even within our dummy serializer.
Likewise, SerializeSeq's serialize_element in SerializeVec could add a vec element index to the path, but currently it does not. Should it? Probably.
} | ||
|
||
impl<'a> ser::SerializeStruct for &'a mut DummySerializer { | ||
// Must match the `Ok` type of the serializer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is clear, and these comments don't show up any other places similar types are defined.
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { | ||
eprintln!( | ||
"{}: skipped field {}", | ||
match self.path { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above for replacing the match with some combination of map and unwrap_or_default
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { | ||
eprintln!( | ||
"{}: skipped field {}", | ||
match self.path { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above.
Fixes #160.