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

Adds trait implementations #730

Merged
merged 4 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/element/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1494,7 +1494,7 @@ mod value_tests {
let list: Element = ion_list![1, 2, 3].into();
thread::scope(|_| {
// Move `list` into this scope, demonstrating `Send`
let elements = vec![list];
let elements = [list];
Copy link
Contributor Author

Choose a reason for hiding this comment

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

🗺️ Clippy noticed that this vec! (and the associated heap allocation) is not necessary.

// Trivial assertion to use `elements`
assert_eq!(elements.len(), 1);
});
Expand Down
2 changes: 1 addition & 1 deletion src/lazy/encoder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ mod tests {
use crate::lazy::encoder::annotate::Annotate;
use crate::lazy::encoder::text::LazyRawTextWriter_1_0;
use crate::lazy::encoder::value_writer::internal::MakeValueWriter;
use crate::lazy::encoder::value_writer::{AnnotatableValueWriter, StructWriter};
use crate::lazy::encoder::value_writer::{StructWriter, ValueWriter};
use crate::symbol_ref::AsSymbolRef;
use crate::{Element, IonData, IonResult, Timestamp};

Expand Down
54 changes: 14 additions & 40 deletions src/lazy/encoder/value_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,46 +38,6 @@ pub trait AnnotatableValueWriter: Sized {

/// Performs no operations and returns a [`ValueWriter`].
fn without_annotations(self) -> Self::ValueWriter;

// Users can call `ValueWriter` methods on the `AnnotatedValueWriter` directly. Doing so
// will implicitly call `without_annotations`.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

🗺️ These default delegated methods mimicked those on ValueWriter, allowing users to call them on an AnnotatableValueWriter without first calling with_annotations or without_annotations. However, an AnnotatableValueWriter could not be passed to methods that required an implementation of ValueWriter.


delegate! {
to self.without_annotations() {
fn write_null(self, ion_type: IonType) -> IonResult<()>;
fn write_bool(self, value: bool) -> IonResult<()>;
fn write_i64(self, value: i64) -> IonResult<()>;
fn write_int(self, value: &Int) -> IonResult<()>;
fn write_f32(self, value: f32) -> IonResult<()>;
fn write_f64(self, value: f64) -> IonResult<()>;
fn write_decimal(self, value: &Decimal) -> IonResult<()>;
fn write_timestamp(self, value: &Timestamp) -> IonResult<()>;
fn write_string<A: AsRef<str>>(self, value: A) -> IonResult<()>;
fn write_symbol<A: AsRawSymbolTokenRef>(self, value: A) -> IonResult<()>;
fn write_clob<A: AsRef<[u8]>>(self, value: A) -> IonResult<()>;
fn write_blob<A: AsRef<[u8]>>(self, value: A) -> IonResult<()>;
fn write_list<F: for<'a> FnOnce(&mut <Self::ValueWriter as ValueWriter>::ListWriter<'a>) -> IonResult<()>>(
self,
list_fn: F,
) -> IonResult<()>;
fn write_sexp<F: for<'a> FnOnce(&mut <Self::ValueWriter as ValueWriter>::SExpWriter<'a>) -> IonResult<()>>(
self,
sexp_fn: F,
) -> IonResult<()>;
fn write_struct<
F: for<'a> FnOnce(&mut <Self::ValueWriter as ValueWriter>::StructWriter<'a>) -> IonResult<()>,
>(
self,
struct_fn: F,
) -> IonResult<()>;
fn write(self, value: impl WriteAsIonValue) -> IonResult<()>;
fn write_eexp<'macro_id, F: for<'a> FnOnce(&mut <Self::ValueWriter as ValueWriter>::MacroArgsWriter<'a>) -> IonResult<()>>(
self,
_macro_id: impl Into<MacroIdRef<'macro_id>>,
_macro_fn: F,
) -> IonResult<()>;
}
}
}

pub trait MacroArgsWriter: SequenceWriter {
Expand Down Expand Up @@ -239,6 +199,20 @@ macro_rules! delegate_value_writer_to_self {
pub(crate) use delegate_value_writer_to;
pub(crate) use delegate_value_writer_to_self;

impl<V> ValueWriter for V
where
V: AnnotatableValueWriter,
{
type ListWriter<'a> = <V::ValueWriter as ValueWriter>::ListWriter<'a>;
type SExpWriter<'a> = <V::ValueWriter as ValueWriter>::SExpWriter<'a>;
type StructWriter<'a> = <V::ValueWriter as ValueWriter>::StructWriter<'a>;
type MacroArgsWriter<'a> = <V::ValueWriter as ValueWriter>::MacroArgsWriter<'a>;

delegate_value_writer_to!(closure |self_: Self| {
self_.without_annotations()
});
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

🗺️ The new blanket implementation of ValueWriter for all AnnotatableValueWriters.


pub trait StructWriter {
/// Writes a struct field using the provided name/value pair.
fn write<A: AsRawSymbolTokenRef, V: WriteAsIon>(
Expand Down
10 changes: 10 additions & 0 deletions src/lazy/encoder/write_as_ion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,21 @@ macro_rules! impl_write_as_ion_value {
};
}

// TODO: For the moment, `i8` and `u8` do not directly implement `WriteAsIon` because this causes
// the desired serialization for `&[u8]` and `&[i8]` to be ambiguous. They could be serialized
// either as blobs or as lists of integers. We should use the same trick that `SExpTypeHint`
// employs to make it possible for users to override the default blob serialization by writing:
// writer.write(&[1u8, 2, 3].as_list())
impl_write_as_ion_value!(
Null => write_null with self as self.0,
bool => write_bool with self as *self,
i16 => write_i64 with self as *self as i64,
i32 => write_i64 with self as *self as i64,
i64 => write_i64 with self as *self,
isize => write_i64 with self as *self as i64,
u16 => write_i64 with self as i64::from(*self),
u32 => write_i64 with self as i64::from(*self),
u64 => write_int with self as &Int::from(*self),
usize => write_int with self as &Int::from(*self),
f32 => write_f32 with self as *self,
f64 => write_f64 with self as *self,
Expand Down
88 changes: 2 additions & 86 deletions src/lazy/never.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ use std::fmt::Debug;
use crate::lazy::decoder::{LazyDecoder, LazyRawValueExpr};
use crate::lazy::encoder::value_writer::internal::MakeValueWriter;
use crate::lazy::encoder::value_writer::{
AnnotatableValueWriter, MacroArgsWriter, SequenceWriter, StructWriter, ValueWriter,
AnnotatableValueWriter, MacroArgsWriter, SequenceWriter, StructWriter,
};
use crate::lazy::encoder::write_as_ion::WriteAsIon;
use crate::lazy::expanded::macro_evaluator::{MacroExpr, RawEExpression};
use crate::lazy::text::raw::v1_1::reader::MacroIdRef;
use crate::raw_symbol_token_ref::AsRawSymbolTokenRef;
use crate::{Decimal, Int, IonResult, IonType, Timestamp};
use crate::IonResult;

/// An uninhabited type that signals to the compiler that related code paths are not reachable.
#[derive(Debug, Copy, Clone)]
Expand Down Expand Up @@ -78,87 +78,3 @@ impl MakeValueWriter for Never {
}

impl MacroArgsWriter for Never {}

impl ValueWriter for Never {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

🗺️ Never implements many traits so it can be used as a marker to statically indicate unreachable/unused code paths. Previously, Never implemented both ValueWriter and AnnotatableValueWriter; the new blanket impl allows us to eliminate the explicit implementation of ValueWriter.

type ListWriter<'a> = Never;
type SExpWriter<'a> = Never;
type StructWriter<'a> = Never;
type MacroArgsWriter<'a> = Never;

fn write_null(self, _ion_type: IonType) -> IonResult<()> {
unreachable!("ValueWriter::write_null in Never")
}

fn write_bool(self, _value: bool) -> IonResult<()> {
unreachable!("ValueWriter::write_bool in Never")
}

fn write_i64(self, _value: i64) -> IonResult<()> {
unreachable!("ValueWriter::write_i64 in Never")
}

fn write_int(self, _value: &Int) -> IonResult<()> {
unreachable!("ValueWriter::write_int in Never")
}

fn write_f32(self, _value: f32) -> IonResult<()> {
unreachable!("ValueWriter::write_f32 in Never")
}

fn write_f64(self, _value: f64) -> IonResult<()> {
unreachable!("ValueWriter::write_f64 in Never")
}

fn write_decimal(self, _value: &Decimal) -> IonResult<()> {
unreachable!("ValueWriter::write_decimal in Never")
}

fn write_timestamp(self, _value: &Timestamp) -> IonResult<()> {
unreachable!("ValueWriter::write_timestamp in Never")
}

fn write_string(self, _value: impl AsRef<str>) -> IonResult<()> {
unreachable!("ValueWriter::write_string in Never")
}

fn write_symbol(self, _value: impl AsRawSymbolTokenRef) -> IonResult<()> {
unreachable!("ValueWriter::write_symbol in Never")
}

fn write_clob(self, _value: impl AsRef<[u8]>) -> IonResult<()> {
unreachable!("ValueWriter::write_clob in Never")
}

fn write_blob(self, _value: impl AsRef<[u8]>) -> IonResult<()> {
unreachable!("ValueWriter::write_blob in Never")
}

fn write_list<F: for<'a> FnOnce(&mut Self::ListWriter<'a>) -> IonResult<()>>(
self,
_list_fn: F,
) -> IonResult<()> {
unreachable!("ValueWriter::write_list in Never")
}

fn write_sexp<F: for<'a> FnOnce(&mut Self::SExpWriter<'a>) -> IonResult<()>>(
self,
_sexp_fn: F,
) -> IonResult<()> {
unreachable!("ValueWriter::write_sexp in Never")
}

fn write_struct<F: for<'a> FnOnce(&mut Self::StructWriter<'a>) -> IonResult<()>>(
self,
_struct_fn: F,
) -> IonResult<()> {
unreachable!("ValueWriter::write_struct in Never")
}

fn write_eexp<'macro_id, F: for<'a> FnOnce(&mut Self::MacroArgsWriter<'a>) -> IonResult<()>>(
self,
_macro_id: impl Into<MacroIdRef<'macro_id>>,
_macro_fn: F,
) -> IonResult<()> {
unreachable!("ValueWriter::write_eexp in Never")
}
}
Loading