-
Notifications
You must be signed in to change notification settings - Fork 38
Removes IonElement trait, ElementRef impl #475
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
Conversation
`IonElement` provides a trait abstraction over two flavors of `Element` API: 1. The 'borrowed' API, where each `ElementRef` has a lifetime tied to the lifetime of the source data. 2. The 'owned' API, where each `Element` is self-contained, with no connection to the source data. While the borrowed API should be lighter weight, the current implementation performs materializes nearly the same amount of data as the owned API. Collections (`list`, `sexp`, `struct`) are heap-allocated; only `string`s and `lob`s avoid allocation. The `IonElement` trait was designed before GATs were stabilized and had some rough edges caused by the inherent difficulty in abstracting over lifetime constraints in traits in the absence of GATs. In practice, users that need an `Element` API are exclusively using the `owned` variant. In light of these observations and in anticipation of the upcoming v1.0 release, this PR removes both the `IonElement` trait and the `borrowed` implementation, leaving only the owned `Element` API. These constructs can be reintroduced in the future if and when they are needed.
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #475 +/- ##
==========================================
- Coverage 90.40% 90.15% -0.26%
==========================================
Files 77 76 -1
Lines 14179 13548 -631
==========================================
- Hits 12819 12214 -605
+ Misses 1360 1334 -26
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
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.
🗺️ PR tour
While most of the changes in the diff are pretty mechanical (removing generics in favor of Element
), there are a few other changes that I'll point out below.
match integer_val { | ||
Integer::I64(i64_int) => i64_int.into(), | ||
Integer::BigInt(big_int) => big_int.into(), | ||
} |
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.
🗺️ We already had From<i64>
(e.g. 16.into()
) and From<BigInt>
, adding From<Integer>
allows simple conversions in places where we've already constructed an Integer
enum.
Value::String(string_val.to_owned()).into() | ||
} | ||
} | ||
|
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.
🗺️ Allows let s: Element = "hello".into();
type AnnotationsIterator<'a> = SymbolsIterator<'a>; | ||
|
||
fn ion_type(&self) -> IonType { | ||
impl Element { |
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.
🗺️ For now I've converted the functionality that was associated with the IonElement
trait into concrete methods on the Element
type. I expect to refactor these in a follow-on PR.
match &self.value { | ||
Value::Integer(i) => Some(i), | ||
_ => None, | ||
} | ||
} | ||
|
||
fn as_f64(&self) -> Option<f64> { | ||
pub fn as_float(&self) -> Option<f64> { |
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 renamed this to reflect the Ion type (float
) rather than the Rust type (f64
) as we do in the other methods.
match &self.value { | ||
Value::Timestamp(t) => Some(t), | ||
_ => None, | ||
} | ||
} | ||
|
||
fn as_str(&self) -> Option<&str> { | ||
pub fn as_text(&self) -> Option<&str> { | ||
match &self.value { | ||
Value::String(text) => Some(text), | ||
Value::Symbol(sym) => sym.text(), | ||
_ => None, | ||
} | ||
} |
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.
🗺️ Rather than have a single as_string()
method that returns text for either String
or Symbol
elements, we now have as_string()
for String
elements, as_symbol()
for Symbol
elements, and as_text()
for the old behavior that doesn't care which text type the Element
is.
@@ -110,7 +95,7 @@ where | |||
return Ok(()); | |||
} | |||
|
|||
self.update_escaping(&v.to_be_bytes()); | |||
self.update_escaping(v.to_be_bytes()); |
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.
🗺️ Incorporating a clippy
suggestion.
@@ -154,7 +136,7 @@ where | |||
|
|||
fn write_repr_string(&mut self, value: Option<&str>) -> IonResult<()> { | |||
match value { | |||
Some(s) if s.len() > 0 => self.update_escaping(s.as_bytes()), | |||
Some(s) if !s.is_empty() => self.update_escaping(s.as_bytes()), |
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.
🗺️ Incorporating a clippy
suggestion.
@@ -163,17 +145,14 @@ where | |||
|
|||
fn write_repr_blob(&mut self, value: Option<&[u8]>) -> IonResult<()> { | |||
match value { | |||
Some(bytes) if bytes.len() > 0 => self.update_escaping(bytes), | |||
Some(bytes) if !bytes.is_empty() => self.update_escaping(bytes), |
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.
🗺️ Incorporating a clippy
suggestion.
match &self.value { | ||
Value::Symbol(sym) => Some(sym), | ||
_ => None, | ||
} | ||
} | ||
|
||
fn as_bool(&self) -> Option<bool> { | ||
pub fn as_boolean(&self) -> Option<bool> { |
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.
🗺️ Renaming to reflect the Ion type (boolean
) rather than the Rust type (bool
).
match &self.value { | ||
Value::Boolean(b) => Some(*b), | ||
_ => None, | ||
} | ||
} | ||
|
||
fn as_bytes(&self) -> Option<&[u8]> { | ||
pub fn as_lob(&self) -> Option<&[u8]> { |
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 with the string
/symbol
/text
, I've broken this into clob
/blob
/lob
.
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.
Looks good 🚀
There are still some clippy
warnings for element_stream_reader
though.
Those are related to #472. |
IonElement
provides a trait abstraction over two flavors ofElement
API:The 'borrowed' API, where each
ElementRef
has a lifetime tied to the lifetime of the source data.The 'owned' API, where each
Element
is self-contained, with no connection to the source data.While the borrowed API was intended to be lighter weight, the current implementation materializes nearly the same amount of data as the owned API. Collections (
list
,sexp
,struct
) are heap-allocated. Of the scalar types, onlystring
s andlob
s avoid any allocation in the borrowed API.The
IonElement
trait was designed before GATs were stabilized and had some rough edges caused by the inherent difficulty in abstracting over lifetime constraints in traits in the absence of GATs.In practice, users that need an
Element
API are exclusively using theowned
variant.In light of these observations and in anticipation of the upcoming v1.0 release, this PR removes both the
IonElement
trait and theborrowed
implementation, leaving only the ownedElement
API. These constructs can be reintroduced in the future if and when they are needed.Follow-on pull requests will:
Struct
,List
, andSExpression
more ergonomically.ElementReader
's functionality intoIonReader
.ElementWriter's
functionality intoIonWriter
.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.