Skip to content
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

Upgrade to ion_rs dependency to v1.0.0-rc.5 #113

Merged
merged 13 commits into from
Jun 3, 2024
Merged

Conversation

zslayton
Copy link
Contributor

@zslayton zslayton commented Jun 2, 2024

  • Upgrades the ion-cli's dependency on ion_rs from v1.0.0-rc.2 to v1.0.0-rc.5.
  • Removes our dependency on memmap; all commands are now streaming.
  • Removes hack to add newlines between per-file outputs from dump.
  • Overhauls the inspect command to take advantage of new tooling access APIs in the streaming reader. The new version:
    • shows opcodes and VarUInt lengths in a style that is distinct from that of the body of the value
    • uses Unicode box drawing to render its table
    • colors annotations and field names in the text Ion column
    • shows the symbol ID assigned to each string in a local symbol

Fixes issues #34 and #36.


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@zslayton zslayton changed the title Upgrade to rc4 Upgrade to rc5 Jun 3, 2024
@zslayton zslayton changed the title Upgrade to rc5 Upgrade to ion_rs dependency to v1.0.0-rc.5 Jun 3, 2024
let Some(raw_value) = symtab.as_value().raw() else {
// This symbol table came from a macro expansion; there are no encoded bytes
// to pass through.
bail!("found an ephemeral symbol table, which is not yet supported")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is "ephemeral" going to be an official-ish term for this case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the phrase I've been using for it, but admittedly mostly to myself :)

If it resonates with you, then I'd say let's do it. 👍

Copy link
Contributor Author

@zslayton zslayton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗺️ PR tour

Comment on lines 50 to +55
"When specified, the inspector will skip ahead `n` bytes before
beginning to display the contents of the stream. System values like
Ion version markers and symbol tables in the bytes being skipped will
still be displayed. If the requested number of bytes falls in the
middle of a value, the whole value (complete with field ID and
annotations if applicable) will be displayed. If the value is nested
in one or more containers, those containers will be displayed too.",
beginning to display the contents of the stream. If the requested number
of bytes falls in the middle of a scalar, the whole value (complete with
field ID and annotations if applicable) will be displayed. If the value
is nested in one or more containers, the opening delimiters of those
containers be displayed.",
Copy link
Contributor Author

@zslayton zslayton Jun 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗺️ Here's the inspect output for a simple data stream, and the output for the same stream with --skip-bytes 29 specified:
image

Notice that the ends of the containers that byte 29 falls within are still displayed for context.

Comment on lines 67 to +73
"When specified, the inspector will stop printing values after
processing `n` bytes of Ion data. If `n` falls within a value, the
complete value will be displayed.",
processing `n` bytes of Ion data. If `n` falls within a scalar, the
complete value will be displayed. If `n` falls within one or more containers,
the closing delimiters for those containers will be displayed. If this flag
is used with `--skip-bytes`, `n` is counted from the beginning of the first
value start after `--skip-bytes`.
",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗺️ Here's the inspect output for a simple data stream, and the output for the same stream with --limit-bytes 29 specified:
image

Notice that the starts of the containers that byte 29 falls within are still displayed for context.

let Some(raw_value) = symtab.as_value().raw() else {
// This symbol table came from a macro expansion; there are no encoded bytes
// to pass through.
bail!("found an ephemeral symbol table, which is not yet supported")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the phrase I've been using for it, but admittedly mostly to myself :)

If it resonates with you, then I'd say let's do it. 👍

Comment on lines 222 to +223
#[cfg(feature = "experimental-code-gen")]
#[rstest]
#[case::simple_struct(
r#"
mod code_gen_tests {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗺️ All of the changes in this file come from introducing a new module that could be more easily feature gated behind experimental-code-gen. There are no logic changes.

@@ -1,12 +1,12 @@
#![cfg(feature = "experimental-code-gen")]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗺️ Similarly, I moved the feature gates in this file to the module level to avoid needing to repeat them.

Copy link
Contributor

@jobarr-amzn jobarr-amzn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

src/bin/ion/commands/beta/symtab/filter.rs Show resolved Hide resolved
Comment on lines -181 to -227
if reader.is_null() {
writer.write_null(ion_type)?;
continue;
}

use IonType::*;
match ion_type {
Null => unreachable!("null values are handled prior to this match"),
Bool => writer.write_bool(reader.read_bool()?)?,
Int => writer.write_int(&reader.read_int()?)?,
Float => {
let float64 = reader.read_f64()?;
let float32 = float64 as f32;
if float32 as f64 == float64 {
// No data lost during cast; write it as an f32
writer.write_f32(float32)?;
} else {
writer.write_f64(float64)?;
}
}
Decimal => writer.write_decimal(&reader.read_decimal()?)?,
Timestamp => writer.write_timestamp(&reader.read_timestamp()?)?,
Symbol => writer.write_symbol(reader.read_symbol()?)?,
String => writer.write_string(reader.read_string()?)?,
Clob => writer.write_clob(reader.read_clob()?)?,
Blob => writer.write_blob(reader.read_blob()?)?,
List => {
reader.step_in()?;
writer.step_in(List)?;
}
SExp => {
reader.step_in()?;
writer.step_in(SExp)?;
}
Struct => {
reader.step_in()?;
writer.step_in(Struct)?;
}
}
}
StreamItem::Nothing if reader.depth() > 0 => {
reader.step_out()?;
writer.step_out()?;
}
StreamItem::Nothing => break,
}
if reader.depth() == 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. What a good change. Way to go ion-rs!

src/bin/ion/commands/dump.rs Show resolved Hide resolved
src/bin/ion/commands/mod.rs Show resolved Hide resolved
Comment on lines +144 to +146
let stdin_lock = io::stdin().lock();
// If no input file was specified, run the inspector on STDIN.

// The inspector expects its input to be a byte array or mmap()ed file acting as a byte
// array. If the user wishes to provide data on STDIN, we'll need to copy those bytes to
// a temporary file and then read from that.

// Create a temporary file that will delete itself when the program ends.
let mut input_file = tempfile::tempfile().with_context(|| {
concat!(
"Failed to create a temporary file to store STDIN.",
"Try passing an --input flag instead."
)
})?;

// Pipe the data from STDIN to the temporary file.
let mut writer = BufWriter::new(input_file);
io::copy(&mut io::stdin(), &mut writer)
.with_context(|| "Failed to copy STDIN to a temp file.")?;
// Get our file handle back from the BufWriter
input_file = writer
.into_inner()
.with_context(|| "Failed to read from temp file containing STDIN data.")?;
// Read from the now-populated temporary file.
inspect_file(
"STDIN temp file",
input_file,
&mut output,
bytes_to_skip,
limit_bytes,
)?;
inspect_input("STDIN", stdin_lock, &mut output, bytes_to_skip, limit_bytes)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! 🎉

Comment on lines +332 to 343
/// Convenience method to set the output stream to the specified color/style for the duration of `write_fn`
/// and then reset it upon completion.
fn with_style(
&mut self,
style: ColorSpec,
write_fn: impl FnOnce(&mut OutputRef) -> Result<()>,
) -> Result<()> {
self.output.set_color(&style)?;
write_fn(&mut self.output)?;
self.output.reset()?;
Ok(())
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little surprised this doesn't already exist in termcolor, since this is usually the idiom I reach for for colorized text.
Indeed, though, it's not there: https://docs.rs/termcolor/latest/termcolor/trait.WriteColor.html

@zslayton zslayton merged commit 19e5ea9 into master Jun 3, 2024
7 checks passed
@zslayton zslayton deleted the upgrade-to-rc4 branch June 3, 2024 18:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants