Enable inspect to display symbol table encodings#18
Conversation
`ion-rs` v0.8.0 introduced a `SystemReader` which allows applications to inspect local symbol tables in the stream with the same granularity with which they can inspect user-level Ion values. This PR upgrades the `beta inspect` command to use the new `SystemReader` instead of the now-defunct `SystemEventHandler` callback API. This allows `inspect` to show the complete contents of any symbol table it encounters.
|
|
||
| const ABOUT: &str = "Displays hex-encoded binary Ion alongside its equivalent text for human-friendly debugging."; | ||
| const ABOUT: &str = | ||
| "Displays hex-encoded binary Ion alongside its equivalent text for human-friendly debugging."; |
There was a problem hiding this comment.
Unfortunately, this diff contains whitespace changes introduced by a cargo fmt run that I forgot to isolate into its own commit. 🤦 Mea culpa. I'll add comments indicating the important logic changes.
| // Create a type alias to simplify working with a shared, mutable reference to our output stream. | ||
| type OutputRef = Rc<RefCell<dyn io::Write>>; | ||
| // Create a type alias to simplify working with a shared reference to our output stream. | ||
| type OutputRef = Box<dyn io::Write>; |
There was a problem hiding this comment.
Now that we're not using a callback system, there's no need to share the output stream between multiple owners. We can discard the wrapper types that enabled that sharing (Rc<RefCell<_>>).
| } | ||
|
|
||
| let output: OutputRef; | ||
| let mut output: OutputRef; |
There was a problem hiding this comment.
Now that we're not sharing the output stream via Rc<RefCell<_>>, we need to use explicit mutability.
|
|
||
| write_header(&output)?; | ||
| write_header(output)?; | ||
| let mut inspector = IonInspector::new(ion_data, output, bytes_to_skip, limit_bytes); |
There was a problem hiding this comment.
We no longer have to do Rc::clone here.
| // System events (IVM, symtabs) are always at the top level. | ||
| const SYSTEM_EVENT_INDENTATION: &str = ""; | ||
|
|
||
| impl SystemEventHandler for SystemLevelEventSummarizer { |
There was a problem hiding this comment.
The new SystemReader in ion-rs obviated the need for the SystemEventHandler trait.
|
|
||
| while let Some((ion_type, _is_null)) = self.reader.next()? { | ||
| loop { | ||
| let (ion_type, _is_null) = match self.reader.next()? { |
There was a problem hiding this comment.
Now that we're using a SystemReader, we have to distinguish between a few types of data that might appear each time that we call next:
None: No more data at this level of nesting.Some(VersionMarker(_)): We found an Ion Version Marker.Some(SymbolTableData(_)): We found an Ion value that was part of a Local Symbol Table (LST) and is not user data.Some(Value(_)): We found user-level data.
The handling for the last two types is identical; in either case we want to display the bytes that were used to encode that particular value, whether it's user-level or not.
| // Print the container's closing delimiter: }, ), or ] | ||
| // FIXME: This should also print a trailing `,` if the parent context is | ||
| // a list or struct. See this issue for details: | ||
| // https://github.com/amzn/ion-cli/issues/17 |
There was a problem hiding this comment.
Discovered this unrelated bug while working on this PR: #17
|
|
||
| fn increase_indentation(&mut self) { | ||
| // Remove a level's worth of indentation from the buffer. | ||
| // Add a level's worth of indentation to the buffer. |
There was a problem hiding this comment.
The old version of this comment was a copy/paste error.
|
|
||
| fn write_field_if_present(&mut self) -> IonResult<()> { | ||
| if let Some(field_id) = self.reader.field_id() { | ||
| if let Some(field_token) = self.reader.raw_field_name_token() { |
There was a problem hiding this comment.
The reader now has APIs that allow an application to see the original encoding of the field name, be it a symbol ID ($12) or text (foo).
| fn write_field_if_present(&mut self) -> IonResult<()> { | ||
| if let Some(field_id) = self.reader.field_id() { | ||
| if let Some(field_token) = self.reader.raw_field_name_token() { | ||
| let field_id = field_token.local_sid().expect("No SID for field name."); |
There was a problem hiding this comment.
inspect only ever reads binary Ion. In Ion v1.0, symbols MUST be local SIDs.
ion-rsv0.8.0 introduced aSystemReaderwhich allows applications toinspect local symbol tables in the stream with the same granularity with
which they can inspect user-level Ion values.
This PR upgrades the
beta inspectcommand to use the newSystemReaderinstead of the now-defunctSystemEventHandlercallbackAPI. This allows
inspectto show the complete contents of any symboltable it encounters.
Before
After
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.