Skip to content

Commit 187a8c8

Browse files
authored
Update deps ion-rs and ion-schema to support arbitrary-sized integers and decimals (#217)
* Bump ion-rs and ion-schema to latest versions * clippy fixes
1 parent 9ef1058 commit 187a8c8

11 files changed

Lines changed: 93 additions & 67 deletions

File tree

Cargo.lock

Lines changed: 21 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ flate2 = "1.0"
2121
infer = "0.15.0"
2222
# ion-rs version must be pinned because we are using experimental features
2323
# See https://github.com/amazon-ion/ion-cli/issues/155
24-
ion-rs = { version = "1.0.0-rc.11", features = ["experimental", "experimental-ion-hash"] }
24+
ion-rs = { version = "1.0.0-rc.12", features = ["experimental", "experimental-ion-hash", "experimental-tooling-apis"] }
25+
ion-schema = { version = "0.16.0" }
2526
tempfile = "3.2.0"
26-
ion-schema = "0.15.0"
2727
lowcharts = "0.5.8"
2828
serde = { version = "1.0.163", features = ["derive"] }
2929
serde_json = { version = "1.0.81", features = ["arbitrary_precision", "preserve_order"] }

src/bin/ion/commands/inspect.rs

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::output::CommandOutput;
1111
use anyhow::{bail, Context, Result};
1212
use clap::builder::ValueParser;
1313
use clap::{Arg, ArgAction, ArgMatches, Command};
14-
use ion_rs::v1_0::{EncodedBinaryValue, RawValueRef};
14+
use ion_rs::v1_0::{BinaryValueLiteral, RawValueRef};
1515
use ion_rs::*;
1616
use termcolor::{Color, ColorSpec, WriteColor};
1717

@@ -265,8 +265,8 @@ impl<'a, 'b> IonInspector<'a, 'b> {
265265
limit_bytes: usize,
266266
hide_expansion: bool,
267267
) -> IonResult<IonInspector<'a, 'b>> {
268-
let text_writer = WriteConfig::<v1_0::Text>::new(TextFormat::Compact)
269-
.build_raw_writer(Vec::with_capacity(TEXT_WRITER_INITIAL_BUFFER_SIZE))?;
268+
let text_writer =
269+
v1_0::RawTextWriter::new(Vec::with_capacity(TEXT_WRITER_INITIAL_BUFFER_SIZE))?;
270270
let inspector = IonInspector {
271271
output: out,
272272
bytes_to_skip,
@@ -365,11 +365,11 @@ impl<'a, 'b> IonInspector<'a, 'b> {
365365
}
366366

367367
/// If `maybe_item` is:
368-
/// * `Some(entity)`, checks to see if the entity's final byte offset is beyond the configured
369-
/// number of bytes to skip.
370-
/// * `None`, then there is no stream-level entity backing the item (that is: it was the result
371-
/// of a macro expansion). Checks to see if the inspector has already completed its
372-
/// skipping phase on an earlier item.
368+
/// * `Some(entity)`, checks to see if the entity's final byte offset is beyond the configured
369+
/// number of bytes to skip.
370+
/// * `None`, then there is no stream-level entity backing the item (that is: it was the result
371+
/// of a macro expansion). Checks to see if the inspector has already completed its
372+
/// skipping phase on an earlier item.
373373
fn should_skip<T: HasRange>(&mut self, maybe_item: &Option<T>) -> bool {
374374
match maybe_item {
375375
// If this item came from an input literal, see if the input literal ends after
@@ -382,11 +382,11 @@ impl<'a, 'b> IonInspector<'a, 'b> {
382382
}
383383

384384
/// If `maybe_item` is:
385-
/// * `Some(entity)`, checks to see if the entity's final byte offset is beyond the configured
386-
/// number of bytes to inspect.
387-
/// * `None`, then there is no stream-level entity backing the item. These will always be
388-
/// inspected; if the e-expression that produced the value was not beyond the limit,
389-
/// none of the ephemeral values it produces are either.
385+
/// * `Some(entity)`, checks to see if the entity's final byte offset is beyond the configured
386+
/// number of bytes to inspect.
387+
/// * `None`, then there is no stream-level entity backing the item. These will always be
388+
/// inspected; if the e-expression that produced the value was not beyond the limit,
389+
/// none of the ephemeral values it produces are either.
390390
fn is_past_limit<T: HasRange>(&self, maybe_item: &Option<T>) -> bool {
391391
let limit = self.bytes_to_skip.saturating_add(self.limit_bytes);
392392
maybe_item
@@ -491,7 +491,7 @@ impl<'a, 'b> IonInspector<'a, 'b> {
491491
self.write_comment("End of stream")
492492
}
493493

494-
fn inspect_macro_invocation<'x>(
494+
fn inspect_macro_invocation(
495495
&mut self,
496496
depth: usize,
497497
trailing_delimiter: &str,
@@ -513,7 +513,7 @@ impl<'a, 'b> IonInspector<'a, 'b> {
513513
Ok(())
514514
}
515515

516-
fn inspect_eexp<'x>(
516+
fn inspect_eexp(
517517
&mut self,
518518
depth: usize,
519519
trailing_delimiter: &str,
@@ -588,7 +588,7 @@ impl<'a, 'b> IonInspector<'a, 'b> {
588588
Ok(())
589589
}
590590

591-
fn inspect_eexp_arg_group<'x>(
591+
fn inspect_eexp_arg_group(
592592
&mut self,
593593
depth: usize,
594594
arg_group: EExpArgGroup<AnyEncoding>,
@@ -955,7 +955,7 @@ impl<'a, 'b> IonInspector<'a, 'b> {
955955
&mut self,
956956
depth: usize,
957957
value: LazyValue<'x, AnyEncoding>,
958-
encoded_value: impl EncodedBinaryValue<'x, D>,
958+
encoded_value: impl BinaryValueLiteral<'x, D>,
959959
) -> Result<()> {
960960
if !value.has_annotations() {
961961
return Ok(());
@@ -1036,7 +1036,7 @@ impl<'a, 'b> IonInspector<'a, 'b> {
10361036
fn inspect_literal_container_header<'x, D: Decoder>(
10371037
&mut self,
10381038
depth: usize,
1039-
encoded_value: impl EncodedBinaryValue<'x, D>,
1039+
encoded_value: impl BinaryValueLiteral<'x, D>,
10401040
) -> Result<()> {
10411041
let opcode_bytes: &[u8] = encoded_value.value_opcode_span().bytes();
10421042
let mut formatter = BytesFormatter::new(
@@ -1057,7 +1057,7 @@ impl<'a, 'b> IonInspector<'a, 'b> {
10571057
fn inspect_literal_container_footer<'x, D: Decoder>(
10581058
&mut self,
10591059
depth: usize,
1060-
encoded_value: impl EncodedBinaryValue<'x, D>,
1060+
encoded_value: impl BinaryValueLiteral<'x, D>,
10611061
closing_delimiter: &str,
10621062
trailing_delimiter: &str,
10631063
) -> Result<()> {
@@ -1091,7 +1091,7 @@ impl<'a, 'b> IonInspector<'a, 'b> {
10911091
depth: usize,
10921092
delimiter: &str,
10931093
sexp: LazySExp<'x, AnyEncoding>,
1094-
encoded_value: impl EncodedBinaryValue<'x, D>,
1094+
encoded_value: impl BinaryValueLiteral<'x, D>,
10951095
) -> Result<()> {
10961096
self.inspect_literal_sequence(
10971097
depth,
@@ -1114,7 +1114,7 @@ impl<'a, 'b> IonInspector<'a, 'b> {
11141114
closing_delimiter: &str,
11151115
trailing_delimiter: &str,
11161116
nested_values: impl IntoIterator<Item = IonResult<ValueExpr<'x, AnyEncoding>>>,
1117-
encoded_value: impl EncodedBinaryValue<'x, D>,
1117+
encoded_value: impl BinaryValueLiteral<'x, D>,
11181118
value_comment_fn: impl CommentFn<'x>,
11191119
) -> Result<()> {
11201120
self.inspect_literal_container_header(depth, encoded_value)?;
@@ -1305,7 +1305,7 @@ impl<'a, 'b> IonInspector<'a, 'b> {
13051305
depth: usize,
13061306
trailing_delimiter: &str,
13071307
struct_: LazyStruct<AnyEncoding>,
1308-
encoded_value: impl EncodedBinaryValue<'x, D>,
1308+
encoded_value: impl BinaryValueLiteral<'x, D>,
13091309
kind: StructKind,
13101310
) -> Result<()> {
13111311
self.inspect_literal_container_header(depth, encoded_value)?;
@@ -1421,7 +1421,7 @@ impl<'a, 'b> IonInspector<'a, 'b> {
14211421
depth: usize,
14221422
delimiter: &str,
14231423
value: LazyValue<'x, AnyEncoding>,
1424-
encoded_value: impl EncodedBinaryValue<'x, D>,
1424+
encoded_value: impl BinaryValueLiteral<'x, D>,
14251425
mut comment_fn: impl CommentFn<'x>,
14261426
) -> Result<()> {
14271427
let range = encoded_value.value_span().range();

src/bin/ion/commands/jq.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// The JAQ errors are large and it's out of our control.
2+
#![allow(clippy::result_large_err)]
3+
14
use crate::commands::jq::ion_math::DecimalMath;
25
use crate::commands::{CommandIo, IonCliCommand, WithIonCliArgument};
36
use crate::input::CommandInput;
@@ -118,10 +121,12 @@ fn filter_and_print(
118121
writer: &mut CommandOutputWriter,
119122
item: JaqElement,
120123
) -> anyhow::Result<()> {
124+
// TODO: See if we can avoid a mutable interior constant here
125+
#[allow(clippy::declare_interior_mutable_const)]
121126
const EMPTY_ITER: RcIter<Empty<Result<JaqElement, String>>> = RcIter::new(core::iter::empty());
122127

123-
let inputs = &EMPTY_ITER; // filter evaluation starts here, no other contextual inputs exist
124-
let ctx = Ctx::new([], inputs); // manages variables etc., use one per filter execution
128+
let inputs = EMPTY_ITER; // filter evaluation starts here, no other contextual inputs exist
129+
let ctx = Ctx::new([], &inputs); // manages variables etc., use one per filter execution
125130
let out = filter.run((ctx, item));
126131

127132
for value in out {
@@ -207,10 +212,12 @@ impl FromIterator<Self> for JaqElement {
207212

208213
impl PartialEq<Self> for JaqElement {
209214
fn eq(&self, other: &Self) -> bool {
215+
// TODO: Should this use IonData::eq instead?
210216
self.0.eq(&other.0)
211217
}
212218
}
213219

220+
#[allow(clippy::non_canonical_partial_ord_impl)]
214221
impl PartialOrd for JaqElement {
215222
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
216223
Some(IonData::from(self).cmp(&IonData::from(other)))
@@ -332,9 +339,9 @@ impl Sub for JaqElement {
332339
// Number types, only lossless operations
333340
(Int(a), Int(b)) => (a + -b).into(), //TODO: use bare - with ion-rs > rc.11
334341
(Float(a), Float(b)) => a.sub(b).into(),
335-
(Decimal(a), Decimal(b)) => a.sub(b).into(),
336-
(Decimal(a), Int(b)) => a.sub(b).into(),
337-
(Int(a), Decimal(b)) => a.sub(b).into(),
342+
(Decimal(a), Decimal(b)) => DecimalMath::sub(a, b).into(),
343+
(Decimal(a), Int(b)) => DecimalMath::sub(a, b).into(),
344+
(Int(a), Decimal(b)) => DecimalMath::sub(a, b).into(),
338345

339346
// Only try potentially lossy Float conversions when we've run out of the other options
340347
(a @ Int(_) | a @ Decimal(_), Float(b)) => (a.to_f64().unwrap() - b).into(),
@@ -564,7 +571,9 @@ impl jaq_core::ValT for JaqElement {
564571
let elt: Element = match (self.value(), index.value()) {
565572
(List(seq) | SExp(seq), Int(i)) => index_i128(seq, i.as_i128()),
566573
(List(seq) | SExp(seq), Float(f)) => index_i128(seq, Some(*f as i128)),
567-
(List(seq) | SExp(seq), Decimal(d)) => index_i128(seq, d.into_big_decimal().to_i128()),
574+
(List(seq) | SExp(seq), Decimal(d)) => {
575+
index_i128(seq, d.clone().into_big_decimal().to_i128())
576+
}
568577
(Struct(strukt), String(name)) => strukt.get(name).or_owned_null(),
569578
(Struct(strukt), Symbol(name)) => strukt.get(name).or_owned_null(),
570579

@@ -616,10 +625,7 @@ impl jaq_core::ValT for JaqElement {
616625
/// > `if A then B else C end` will act the same as `B` if `A` produces a value other than
617626
/// > `false` or `null`, but act the same as `C` otherwise.
618627
fn as_bool(&self) -> bool {
619-
match self.0.value() {
620-
Value::Null(_) | Value::Bool(false) => false,
621-
_ => true,
622-
}
628+
!matches!(self.0.value(), Value::Null(_) | Value::Bool(false))
623629
}
624630

625631
// If the element is a text value, return its text.
@@ -642,7 +648,7 @@ impl jaq_std::ValT for JaqElement {
642648
fn as_isize(&self) -> Option<isize> {
643649
match self.0.value() {
644650
Value::Int(i) => i.expect_i64().unwrap().to_isize(),
645-
Value::Decimal(d) => d.into_big_decimal().to_isize(),
651+
Value::Decimal(d) => d.clone().into_big_decimal().to_isize(),
646652
_ => None,
647653
}
648654
}
@@ -661,7 +667,7 @@ impl jaq_std::ValT for JaqElement {
661667
/// 1. Decimal can express any Int, so any binary operation involving a Decimal and an Int produces
662668
/// a Decimal.
663669
/// 2. Floats have less precision than a Decimal and less range than an Int, so any binary operation
664-
///. involving a Float produces a Float. A Decimal may degrade and lose precision when converted
670+
/// involving a Float produces a Float. A Decimal may degrade and lose precision when converted
665671
/// a Float for arithmetic, but the operation will fail if an operand is out of range for Float.
666672
pub(crate) mod ion_math {
667673
use bigdecimal::num_bigint::BigInt;

src/bin/ion/commands/mod.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ pub trait IonCliCommand {
9696

9797
if !self.is_stable() {
9898
let about = base_command.get_about().map(|x| x.to_string());
99-
if about.is_some() {
100-
base_command = base_command.about(format!("(UNSTABLE) {}", about.unwrap()))
99+
if let Some(about) = about {
100+
base_command = base_command.about(format!("(UNSTABLE) {}", about))
101101
}
102102
base_command = base_command
103103
.before_help("WARNING: This command is unstable and requires explicit opt-in using '--unstable' or '-X'.");
@@ -240,7 +240,7 @@ pub struct CommandIo<'a> {
240240
}
241241

242242
impl CommandIo<'_> {
243-
fn new(args: &ArgMatches) -> Result<CommandIo> {
243+
fn new(args: &ArgMatches) -> Result<CommandIo<'_>> {
244244
// --format pretty|text|lines|binary
245245
let format = args
246246
.try_get_one("format")
@@ -375,7 +375,10 @@ impl CommandIo<'_> {
375375
match self.color {
376376
ColorChoice::Never => CommandOutput::StdOut(stdout_lock, spec),
377377
ColorChoice::Auto if !stdout_tty => CommandOutput::StdOut(stdout_lock, spec),
378-
_ => CommandOutput::HighlightedOut(HighlightedStreamWriter::new(stdout_lock), spec),
378+
_ => CommandOutput::HighlightedOut(
379+
Box::new(HighlightedStreamWriter::new(stdout_lock)),
380+
spec,
381+
),
379382
}
380383
};
381384

src/bin/ion/commands/schema/mod.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -96,28 +96,28 @@ impl IonSchemaCommandInput {
9696
// to treat it as an inline type.
9797
type_definition = schema.get_type(type_name_or_inline_type);
9898

99-
if type_definition.is_none() && empty_schema_version.is_some() {
100-
let version = empty_schema_version.unwrap();
101-
// There is no convenient way to add a type to an existing schema, so we'll
102-
// construct a new one.
99+
if type_definition.is_none() {
100+
if let Some(version) = empty_schema_version {
101+
// There is no convenient way to add a type to an existing schema, so we'll
102+
// construct a new one.
103103

104-
// Create a symbol element so that ion-rs handle escaping any special characters.
105-
let type_name = Element::symbol(type_name_or_inline_type);
104+
// Create a symbol element so that ion-rs handle escaping any special characters.
105+
let type_name = Element::symbol(type_name_or_inline_type);
106106

107-
let new_schema = format!(
108-
r#"
107+
let new_schema = format!(
108+
r#"
109109
{version}
110110
type::{{
111111
name: {type_name},
112112
type: {type_name_or_inline_type}
113113
}}
114114
"#
115-
);
116-
// And finally update the schema and type.
117-
schema = schema_system.new_schema(new_schema.as_bytes(), "new-schema")?;
118-
type_definition = schema.get_type(type_name_or_inline_type);
115+
);
116+
// And finally update the schema and type.
117+
schema = schema_system.new_schema(new_schema.as_bytes(), "new-schema")?;
118+
type_definition = schema.get_type(type_name_or_inline_type);
119+
}
119120
}
120-
121121
// Validate that the user didn't pass in an invalid type
122122
type_definition
123123
.as_ref()

src/bin/ion/commands/structural_recursion.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ pub fn visit_structure<V: ValueVisitor<T>, T>(
9292

9393
while let Some((current_value, depth)) = stack.pop() {
9494
let value_ref = current_value.read()?;
95-
visitor.visit(value_ref, depth)?;
95+
visitor.visit(value_ref.clone(), depth)?;
9696

9797
// For container types, add children to the stack with incremented depth
9898
match value_ref {

0 commit comments

Comments
 (0)