Crate ion_rs

source ·
Expand description

Reading and writing Elements

The Element API offers a convenient way to read and write Ion data when its exact shape is not known ahead of time.

Each Element represents an (annotations, value) pair. If the value is a container (an Ion list, sexp, or struct), then it will contain its own collection of Elements. Elements can be nested to arbitrary depth.

Constructing an Element

From text Ion

The Element::read_one method will parse the provided data and requires that it contain exactly one Ion value.

use ion_rs::element::Element;
use ion_rs::IonType;
let ion_data = "[1, 2, 3]";
let element = Element::read_one(ion_data)?;
assert_eq!(element.ion_type(), IonType::List);

Element::read_all will read any number of Ion values and return them as a Vec<Element>.

Element::read_first will read the first Ion value without requiring that the stream have exactly one value.

From a Rust value

Most Rust primitives implement Into<Element>, allowing them to be converted to an Ion Element directly.

use ion_rs::element::Element;

let int: Element = 5.into();
assert_eq!(Element::read_one("5")?, int);

let boolean: Element = true.into();
assert_eq!(Element::read_one("true")?, boolean);

let string: Element = "hello".into();
assert_eq!(Element::read_one("\"hello\"")?, string);

let ion_version_marker: &[u8] = &[0xE0, 0x01, 0x00, 0xEA]; // Ion 1.0 version marker
let blob: Element = ion_version_marker.into();
assert_eq!(Element::read_one("{{4AEA6g==}}")?, blob);

Using macros

When constructing a container Element, you can use the ion_list!, ion_sexp!, and ion_struct! macros.

use ion_rs::element::Element;
use ion_rs::{ion_list, ion_sexp, ion_struct};

// Variable names are allowed
let six = 6i64;
let list: Element = ion_list! [true, six, "foo"].into();
assert_eq!(Element::read_one("[true, 6, \"foo\"]")?, list);

// Nested use of macros is allowed
// Notice that ion_sexp! uses ()s without commas
let sexp: Element = ion_sexp! (true six ion_list!["foo", "bar"]).into();
assert_eq!(Element::read_one("(true 6 [\"foo\", \"bar\"])")?, sexp);

let field_name = "bar";
let struct_: Element = ion_struct! {
  "foo": six,
  field_name: false
assert_eq!(Element::read_one("{foo: 6, bar: false}")?, struct_);

From a stream

use ion_rs::element::reader::ElementReader;
use ion_rs::element::Element;
use ion_rs::ReaderBuilder;
use std::fs::File;
let ion_file = File::open("/foo/bar/baz.ion").unwrap();
let mut reader = ReaderBuilder::default().build(ion_file)?;
// A simple pretty-printer
for element in reader.elements() {
    println!("{}", element?)

Traversing an Element

use ion_rs::IonResult;
use ion_rs::element::{Element, IntoAnnotatedElement, Value};
use ion_rs::{ion_list, ion_struct};
let element: Element = ion_struct! {
  "foo": "hello",
  "bar": true,
  "baz": ion_list! [4, 5, 6]

if let Value::Struct(s) = element.value() {
    if let Some(Value::List(l)) = s.get("baz").map(|b| b.value()) {
        for (index, element) in l.elements().enumerate() {
            println!("{}. {}", index + 1, element);
            // 1) 4
            // 2) 5
            // 3) 6

Writing an Element to an io::Write

use ion_rs::IonResult;
use ion_rs::element::writer::ElementWriter;
use ion_rs::element::{Element, IntoAnnotatedElement, Value};
use ion_rs::{ion_list, ion_struct, IonWriter, TextWriterBuilder};
let element: Element = ion_struct! {
  "foo": "hello",
  "bar": true,
  "baz": ion_list! [4, 5, 6]

let mut buffer: Vec<u8> = Vec::new();
let mut writer = TextWriterBuilder::default().build(&mut buffer)?;
    "{foo: \"hello\", bar: true, baz: [4, 5, 6]}".as_bytes(),



  • This module provides the necessary structures and logic to read values from a binary Ion data stream.
  • Provides a dynamically typed, materialized representation of an Ion value.
  • Re-exports of third party dependencies that are part of our public API.
  • This module provides an implementation of the data types described by the Ion Data Model section of the Ion 1.0 spec.



  • The BlockingRawReader wraps a non-blocking RawReader that implements the BufferedReader trait, providing a blocking RawReader.
  • A wrapper for lifting Ion compatible data into using Ion-oriented comparisons (versus the Rust value semantics). This enables the default semantics to be what a Rust user expects for native values, but allows a user to opt-in to Ion’s structural equivalence/order.
  • A reference to a fully resolved symbol. Like Symbol (a fully resolved symbol with a static lifetime), a SymbolRef may have known or undefined text (i.e. $0).
  • Stores mappings from Symbol IDs to text and vice-versa.
  • A streaming Ion reader that:
  • An application-level text Ion writer. This writer manages a symbol table and so can convert symbol IDs to their corresponding text. However, unlike the BinaryWriter, it is capable of writing text to the output stream without first adding it to the symbol table.


  • A symbol token encountered in a text or binary Ion stream. RawSymbolTokens do not store import source information for the token encountered. Similarly, a RawSymbolToken cannot store both a symbol ID and text, which means that it is not suitable for representing a resolved symbol.
  • Like RawSymbolToken, but the Text variant holds a borrowed reference instead of a String.
  • Raw stream elements that a SystemReader may encounter.


  • Optimized read operations for parsing Ion.
  • This trait captures the format-agnostic parser functionality needed to navigate within an Ion stream and read the values encountered into native Rust data types.
  • This trait captures the format-agnostic encoding functionality needed to write native Rust types to a stream as Ion values.

Type Definitions