Skip to content

Commit

Permalink
Makes Writer symbol table experimentally pub
Browse files Browse the repository at this point in the history
  • Loading branch information
zslayton committed Dec 26, 2024
1 parent 4e0d272 commit fd4e853
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 11 deletions.
8 changes: 7 additions & 1 deletion src/element/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use std::cmp::Ordering;
use std::fmt::{Display, Formatter};
use std::io;

use crate::{ion_data, Decimal, Int, IonResult, IonType, Str, Symbol, Timestamp};
use crate::{ion_data, Decimal, Int, IonResult, IonType, Str, Symbol, SymbolRef, Timestamp};
use crate::{Blob, Bytes, Clob, List, SExp, Struct};
// Re-export the Value variant types and traits so they can be accessed directly from this module.
use crate::element::builders::{SequenceBuilder, StructBuilder};
Expand Down Expand Up @@ -251,6 +251,12 @@ impl From<Symbol> for Value {
}
}

impl From<SymbolRef<'_>> for Value {
fn from(sym_val: SymbolRef<'_>) -> Self {
Value::Symbol(sym_val.to_owned())
}
}

impl From<&[u8]> for Value {
fn from(value: &[u8]) -> Self {
Value::Blob(value.into())
Expand Down
30 changes: 30 additions & 0 deletions src/lazy/encoder/value_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,3 +481,33 @@ pub trait SequenceWriter: MakeValueWriter {
Ok(self)
}
}

#[cfg(test)]
#[cfg(feature = "experimental-reader-writer")]
mod tests {
use crate::symbol_ref::AsSymbolRef;
use crate::IonResult;
use crate::{ion_seq, v1_1, Element, SequenceWriter, Writer};
#[test]
fn save_and_reuse_symbol_id() -> IonResult<()> {
let mut writer = Writer::new(v1_1::Binary, vec![])?;
let name_symbol = writer
.value_writer()
.symbol_table()
.sid_for("name")
.unwrap();
writer
.write_symbol(name_symbol)?
.write_symbol(name_symbol)?
.write_symbol(name_symbol)?;
let bytes = writer.close()?;
let actual = Element::read_all(&bytes)?;
let expected = ion_seq!(
"name".as_symbol_ref()
"name".as_symbol_ref()
"name".as_symbol_ref()
);
assert_eq!(actual, expected);
Ok(())
}
}
38 changes: 31 additions & 7 deletions src/lazy/encoder/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,18 @@ impl<E: Encoding, Output: Write> Writer<E, Output> {
Ok(self.output)
}

#[cfg(feature = "experimental-reader-writer")]
#[inline]
pub fn symbol_table(&self) -> &SymbolTable {
&self.context.symbol_table
}

#[cfg(not(feature = "experimental-reader-writer"))]
#[inline]
pub(crate) fn symbol_table(&self) -> &SymbolTable {
&self.context.symbol_table
}

/// Helper method to encode an LST append containing pending symbols.
fn write_lst_append(&mut self) -> IonResult<()> {
let Self {
Expand Down Expand Up @@ -235,9 +247,21 @@ impl<'a, V: ValueWriter> ApplicationValueWriter<'a, V> {
}
}

fn symbol_table(&mut self) -> &mut SymbolTable {
fn symbol_table_mut(&mut self) -> &mut SymbolTable {
&mut self.encoding.symbol_table
}

#[cfg(feature = "experimental-reader-writer")]
#[inline]
pub fn symbol_table(&self) -> &SymbolTable {
&self.encoding.symbol_table
}

#[cfg(not(feature = "experimental-reader-writer"))]
#[inline]
pub(crate) fn symbol_table(&self) -> &SymbolTable {
&self.encoding.symbol_table
}
}

impl ApplicationValueWriter<'_, BinaryValueWriter_1_1<'_, '_>> {
Expand Down Expand Up @@ -326,15 +350,15 @@ impl<V: ValueWriter> ApplicationValueWriter<'_, V> {
}
// The token is text...
RawSymbolRef::Text(text) => {
let sid = match self.symbol_table().sid_for(&text) {
let sid = match self.symbol_table().sid_for(text) {
Some(sid) => {
//...that was already in the symbol table.
sid
}
None => {
// ...that we need to add to the symbol table.
self.encoding.num_pending_symbols += 1;
self.symbol_table().add_symbol_for_text(text)
self.symbol_table_mut().add_symbol_for_text(text)
}
};
*annotation = RawSymbolRef::SymbolId(sid);
Expand Down Expand Up @@ -389,7 +413,7 @@ impl<V: ValueWriter> ApplicationValueWriter<'_, V> {
}
// The token is text...
RawSymbolRef::Text(text) => {
match self.symbol_table().sid_for(&text) {
match self.symbol_table_mut().sid_for(text) {
Some(sid) => {
//...that was already in the symbol table.
*annotation = RawSymbolRef::SymbolId(sid);
Expand Down Expand Up @@ -454,7 +478,7 @@ impl<'value, V: ValueWriter> ValueWriter for ApplicationValueWriter<'value, V> {
match value_writer_config.symbol_value_encoding() {
WriteAsSymbolIds => {
// Map the text to a symbol ID.
match encoding.symbol_table.sid_for(&text) {
match encoding.symbol_table.sid_for(text) {
// If it's already in the symbol table, use that SID.
Some(symbol_id) => SymbolId(symbol_id),
// Otherwise, add it to the symbol table.
Expand All @@ -466,7 +490,7 @@ impl<'value, V: ValueWriter> ValueWriter for ApplicationValueWriter<'value, V> {
}
WriteNewSymbolsAsInlineText => {
// If the text is in the symbol table, use the symbol ID. Otherwise, use the text itself.
match encoding.symbol_table.sid_for(&text) {
match encoding.symbol_table.sid_for(text) {
Some(symbol_id) => SymbolId(symbol_id),
None => Text(text),
}
Expand Down Expand Up @@ -590,7 +614,7 @@ impl<V: ValueWriter> FieldEncoder for ApplicationStructWriter<'_, V> {
}

// Otherwise, see if the symbol is already in the symbol table.
let token: RawSymbolRef<'_> = match self.encoding.symbol_table.sid_for(&text) {
let token: RawSymbolRef<'_> = match self.encoding.symbol_table.sid_for(text) {
// If so, use the existing ID.
Some(sid) => sid.into(),
// If it's not but the struct writer is configured to intern new text, add it to the
Expand Down
2 changes: 1 addition & 1 deletion src/symbol_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ impl SymbolTable {
}

/// If defined, returns the Symbol ID associated with the provided text.
pub fn sid_for<A: AsRef<str>>(&self, text: &A) -> Option<SymbolId> {
pub fn sid_for<A: AsRef<str>>(&self, text: A) -> Option<SymbolId> {
self.ids_by_text.get(text.as_ref()).copied()
}

Expand Down
2 changes: 1 addition & 1 deletion tests/conformance_dsl/fragment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ impl<T: ion_rs::Decoder> PartialEq<ion_rs::LazyValue<'_, T>> for ProxyElement<'_
let shared_symbol_txt =
shared_symbol.text().unwrap_or("");
let shared_id = symbol_table
.sid_for(&shared_symbol_txt)
.sid_for(shared_symbol_txt)
.unwrap_or(0);
actual_field.matches_sid_or_text(
shared_id,
Expand Down
2 changes: 1 addition & 1 deletion tests/conformance_dsl/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ pub(crate) fn compare_values<T: ion_rs::Decoder>(
let shared_text = shared_symbol.text().unwrap_or("");
(
shared_text.to_string(),
other.symbol_table().sid_for(&shared_text).unwrap_or(0),
other.symbol_table().sid_for(shared_text).unwrap_or(0),
)
}
}
Expand Down

0 comments on commit fd4e853

Please sign in to comment.