Skip to content

Commit

Permalink
Adds implementation for reader builder with catalog (#700)
Browse files Browse the repository at this point in the history
  • Loading branch information
desaikd authored Jan 23, 2024
1 parent 4a9fc91 commit 1d6f250
Showing 1 changed file with 61 additions and 9 deletions.
70 changes: 61 additions & 9 deletions src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use delegate::delegate;
use crate::binary::constants::v1_0::IVM;
use crate::binary::non_blocking::raw_binary_reader::RawBinaryReader;
use crate::blocking_reader::{BlockingRawBinaryReader, BlockingRawTextReader};
use crate::catalog::{Catalog, EmptyCatalog};
use crate::data_source::IonDataSource;
use crate::ion_reader::IonReader;
use crate::raw_reader::{Expandable, RawReader};
Expand All @@ -20,13 +21,24 @@ use std::fmt::{Display, Formatter};

use crate::types::Str;
/// Configures and constructs new instances of [Reader].
pub struct ReaderBuilder {}
pub struct ReaderBuilder {
// This will be set to to `Some` catalog when the reader builder is created with catalog information.
// Default value for this field will be set to `None`.
catalog: Box<dyn Catalog>,
}

impl ReaderBuilder {
/// Constructs a [ReaderBuilder] pre-populated with common default settings.
pub fn new() -> ReaderBuilder {
ReaderBuilder {
// Eventually, this will contain settings like a `Catalog` implementation.
catalog: Box::<EmptyCatalog>::default(),
}
}

/// Constructs a [ReaderBuilder] with catalog information.
pub fn with_catalog(self, catalog: impl Catalog + 'static) -> ReaderBuilder {
ReaderBuilder {
catalog: Box::new(catalog),
}
}

Expand Down Expand Up @@ -58,7 +70,7 @@ impl ReaderBuilder {
// we can move into the reader.
let owned_header = Vec::from(&header[..total_bytes_read]);
// The file was too short to be binary Ion. Construct a text Reader.
return Self::make_text_reader(owned_header);
return self.make_text_reader(owned_header);
}
total_bytes_read += bytes_read;
}
Expand All @@ -69,7 +81,7 @@ impl ReaderBuilder {
[0xe0, 0x01, 0x00, 0xea] => {
// Binary Ion v1.0
let full_input = io::Cursor::new(header).chain(input);
Ok(Self::make_binary_reader(full_input)?)
Ok(self.make_binary_reader(full_input)?)
}
[0xe0, major, minor, 0xea] => {
// Binary Ion v{major}.{minor}
Expand All @@ -80,19 +92,19 @@ impl ReaderBuilder {
_ => {
// It's not binary, assume it's text
let full_input = io::Cursor::new(header).chain(input);
Ok(Self::make_text_reader(full_input)?)
Ok(self.make_text_reader(full_input)?)
}
}
}

fn make_text_reader<'a, I: 'a + IonDataSource>(data: I) -> IonResult<Reader<'a>> {
fn make_text_reader<'a, I: 'a + IonDataSource>(self, data: I) -> IonResult<Reader<'a>> {
let raw_reader = Box::new(BlockingRawTextReader::new(data)?);
Ok(Reader::new(raw_reader))
Ok(Reader::with_catalog(raw_reader, self.catalog))
}

fn make_binary_reader<'a, I: 'a + IonDataSource>(data: I) -> IonResult<Reader<'a>> {
fn make_binary_reader<'a, I: 'a + IonDataSource>(self, data: I) -> IonResult<Reader<'a>> {
let raw_reader = Box::new(BlockingRawBinaryReader::new(data)?);
Ok(Reader::new(raw_reader))
Ok(Reader::with_catalog(raw_reader, self.catalog))
}
}

Expand Down Expand Up @@ -120,6 +132,12 @@ impl<R: RawReader> UserReader<R> {
system_reader: SystemReader::new(raw_reader),
}
}

pub fn with_catalog(raw_reader: R, catalog: Box<dyn Catalog>) -> UserReader<R> {
UserReader {
system_reader: SystemReader::with_catalog(raw_reader, catalog),
}
}
}

// This module exists to allow our integration tests to directly construct a `UserReader`
Expand Down Expand Up @@ -294,7 +312,9 @@ mod tests {
use crate::binary::constants::v1_0::IVM;
use crate::reader::{BlockingRawBinaryReader, StreamItem::Value};

use crate::catalog::MapCatalog;
use crate::result::IonResult;
use crate::shared_symbol_table::SharedSymbolTable;
use crate::types::IonType;

type TestDataSource = io::Cursor<Vec<u8>>;
Expand Down Expand Up @@ -328,6 +348,13 @@ mod tests {
ReaderBuilder::new().build(ion_data(bytes)).unwrap()
}

fn ion_reader_with_catalog_for(bytes: &[u8], catalog: impl Catalog + 'static) -> Reader {
ReaderBuilder::new()
.with_catalog(catalog)
.build(bytes)
.unwrap()
}

const EXAMPLE_STREAM: &[u8] = &[
// $ion_symbol_table::{imports: $ion_symbol_table, symbols: ["foo", "bar", "baz"]}
0xEE, // Var len annotations
Expand Down Expand Up @@ -370,4 +397,29 @@ mod tests {

Ok(())
}

#[test]
fn test_read_symbol_with_catalog() -> IonResult<()> {
let mut map_catalog = MapCatalog::new();
map_catalog.insert_table(SharedSymbolTable::new(
"shared_table",
1,
["foo", "bar", "baz"],
)?);
let mut reader = ion_reader_with_catalog_for(
r#"
$ion_symbol_table::{
imports: [ { name:"shared_table", version: 1 }],
}
$10 // "foo"
$11 // "bar"
$12 // "baz"
"#
.as_bytes(),
map_catalog,
);
assert_eq!(reader.next()?, Value(IonType::Symbol));
assert_eq!(reader.read_symbol()?, "foo");
Ok(())
}
}

0 comments on commit 1d6f250

Please sign in to comment.