Expand description

Provides basic bindings for Ion C

These bindings are created with bindgen and are considerably low-level.

Examples

Using ion-c-sys directly can be a pretty verbose affair, and requires checking the error code for most calls. This crate provides the result module to make it easier to integrate with std::result::Result with respect to the iERR that Ion C functions generally return. Specifically, any low-level IonC function that returns iERR should be called with the ionc! macro to facilitate Result<(), IonCError> conversion.

This library provides smart pointers over the low-level reader/writer pointers, and should generally be used, especially with Result handling code. These types provide some facade over Ion C, but only for the most generally used APIs. See:

Ion Reader

Here is an end-to-end example of reading some Ion data.

let mut reader = IonCReaderHandle::try_from("{a:2}")?;

// step to the struct
assert_eq!(ION_TYPE_STRUCT, reader.next()?);
// step into the struct
reader.step_in()?;
// step to the field
assert_eq!(ION_TYPE_INT, reader.next()?);
// retrieve the field name
assert_eq!("a", reader.get_field_name()?.as_str());
// read the integer value
assert_eq!(2, reader.read_i64()?);
// step to the end of the struct
assert_eq!(ION_TYPE_EOF, reader.next()?);
// step out of the struct
reader.step_out()?;
// step to the end of the stream
assert_eq!(ION_TYPE_EOF, reader.next()?);

Ion Writer

Here is an end-to-end example of writing some Ion data.

// output buffer
let mut buf: Vec<u8> = vec![0; 128];
let len = {
    let mut writer = IonCWriterHandle::new_buf_mode(buf.as_mut(), WriterMode::Binary)?;
    // start a list
    writer.start_container(ION_TYPE_LIST)?;
    // write some integers
    for n in 0..4 {
        writer.write_i64(n * 2)?;
    }
    // end the list
    writer.finish_container()?;
    // start a struct
    writer.start_container(ION_TYPE_STRUCT)?;
    {
        // write a string
        writer.field("name").annotations(&["version"]).write_string("💩")?;
    }
    // end the struct
    writer.finish_container()?;
    // finish writing
    writer.finish()?
};

// make sure the bytes match what we expect
let expected: &[u8] = &[
    0xE0, 0x01, 0x00, 0xEA,         // IVM
    0xB7,                           // LIST size 7
    0x20,                           // INT 0
    0x21, 0x02,                     // INT 2
    0x21, 0x04,                     // INT 4
    0x21, 0x06,                     // INT 6
    0xD9,                           // STRUCT size 8
    0x84,                           // field "name" (sid 4)
    0xE7, 0x81, 0x85,               // annotation "version" (sid 5)
    0x84, 0xF0, 0x9F, 0x92, 0xA9,   // STRING 💩
];
assert_eq!(expected.len(), len);
assert_eq!(expected, &buf[0..len]);

Re-exports

pub use self::ion_error_code as iERR;
pub use self::_ION_SYMBOL_TABLE_TYPE as ION_SYMBOL_TABLE_TYPE;

Modules

Provides higher-level APIs for ION_DECIMAL

Provides higher-level APIs for ION_INT

Provides higher-level APIs for Ion C’s hREADER.

Provides convenient integration with Error and Result for Ion C.

Provides higher-level APIs for borrowing str slices safely from Ion C.

Provides integration between ION_TIMESTAMP and chrono::DateTime.

Provides higher-level APIs for Ion C’s hWRITER.

Macros

Macro to transform Ion C error code expressions into Result<(), IonCError>. Higher-level facades over Ion C functions could map this to Result<T, IonCError> or the like.

Structs

The collections used by the parser are linked lists which are managed by the collection header. the memory used for the nodes is allocated on the parent, which is passed in when the user initializes the collection

The node allocation scheme depends on this layout ! currently that there are only 2 members so it uses the size of the ptr as the base to allocate

Reader configuration data, could be supplied by user during reader creation time. All fields in the structure are defaulted to 0, except for the following:

Structure to store time information. time_t only has up to second precision, and time zone support is OS dependent. _ion_timestamp uses decimal to store fraction of a second

Constants

The _ion_decimal holds an unowned decNumber.

The _ion_decimal holds a decNumber whose memory is managed by an owner.

The _ion_decimal holds a decQuad.

Statics

Functions

If the given catalog is its own memory owner, its memory and everything it owns is freed. If the given catalog has an external owner and that owner has not been freed, this does nothing; this catalog will be freed when its memory owner is freed. If the given symbol table has an external owner which has been freed, the behavior of this function is undefined.

Allocates a new catalog with itself as its memory owner. Must be freed using ion_catalog_close. @param p_hcatalog - Pointer to a handle to the newly-allocated catalog.

Allocates a new catalog with the given owner as its memory owner. @param p_hcatalog - Pointer to a handle to the newly-allocated catalog. @param owner - Handle to the new catalog’s memory owner. If NULL, the resulting catalog is its own memory owner and must be freed using ion_catalog_close.

If necessary, copies the given decimal’s internal data so that owner of that data may safely go out of scope. This is useful, for example, when it is necessary to keep the value in scope after the reader that produced it is closed. Values produced through calls to ion_decimal_* APIs (with the possible exception of ion_decimal_from_number) do NOT need to be claimed.

Compares ION_DECIMALs for ordering and equivalence under the Ion data model. A negative result indicates that left is less than right. A positive result indicates that left is greater than right. A result of zero indicates that left and right are equivalent under the Ion data model. Non-equivalent values are ordered according to the IEEE 754 total ordering.

Compares ION_DECIMALs for equivalence under the Ion data model. That is, the sign, coefficient, and exponent must be equivalent for the normalized values (even for zero).

Compares decQuads for equivalence under the Ion data model. That is, the sign, coefficient, and exponent must be equivalent for the normalized values (even for zero).

Frees any memory that was allocated when constructing this value. This should be called to clean up all ION_DECIMALs.

Represents the given int32 as an ION_DECIMAL.

Converts the given ION_INT to its ION_DECIMAL representation.

Represents the given decNumber as an ION_DECIMAL. This function does not allocate or copy any memory, so the caller IS required to keep the given decNumber in scope for the lifetime of the resulting ION_DECIMAL. If desired, the caller can alleviate this requirement by calling ion_decimal_claim on the resulting ION_DECIMAL (note that this forces a copy). It is the caller’s responsibility to eventually free any dynamically allocated memory used by the given decNumber (calling ion_decimal_free will not free this memory).

Represents the given decQuad as an ION_DECIMAL. The caller IS NOT required to keep the given decQuad in scope for the lifetime of the resulting ION_DECIMAL.

Converts the given string to its ION_DECIMAL representation.

Represents the given uint32 as an ION_DECIMAL.

Converts the given ION_DECIMAL to its ION_INT representation. If the given ION_DECIMAL is not an integer, IERR_INVALID_ARG will be returned; rounding will never occur. If rounding is desired, use ion_decimal_to_integral_exact or ion_decimal_to_integral_value first.

Converts the given ION_DECIMAL to a string. ION_DECIMAL_STRLEN may be used to determine the amount of space required to hold the string representation.

Zeroes the given ION_DECIMAL in-place. NOTE: this has better performance than memset in certain environments.

Gets a static string representation of an error code.

@deprecated use of decQuads directly is deprecated. ION_DECIMAL should be used. See ion_decimal_to_ion_int.

@deprecated use of decQuads directly is deprecated. ION_DECIMAL should be used. See ion_decimal_from_ion_int.

Closes a reader and releases associated memory. The caller is responsible for releasing the underlying buffer (if any). After calling this method the given handle will no longer be value.

Determines the content of the current text value, which must be an Ion string or symbol. The reader retains ownership of the returned byte array, and the caller must copy the data out (if necessary) before moving the cursor.

returns the current symbol table the value the reader is currently positioned on. This can be used to reset the readers symbol table is you wish to seek in a stream which contains multiple symbol tables. This symbol table handle can be used to call ion_reader_set_symbol_table.

Returns the type of the current value, or tid_none if no value has been assigned. (before next() is called)

returns the length of the value the reader is currently positioned on. This length is appropriate to use later when calling ion_reader_seek to limit “over-reading” in the underlying stream which could result in errors that are not really of interest. NOTE: readers of text data will always set *p_length to -1 because text Ion data is not length-prefixed. When the reader may be reading text Ion data, the correct way to calculate a value’s length is by subtracting the current value’s offset (see ion_reader_get_value_offset) from the next value’s offset. This technique will work for both binary and text Ion data.

returns the offset of the value the reader is currently positioned on. This offset is appropriate to use later to seek to.

Returns the next ION_TYPE in the stream. In case of EOF, IERR_OK will be returned. p_value_type = tid_EOF. @param hreader @param p_value_type ION_TYPE (tid_EOF, tid_BOOL, etc, defined in ion_const.h). tid_EOF if EOF.

Allocates a new reader consuming a given buffer of data.

Create hREADER object, and associate it with the stream for reading.

@deprecated use of decQuads directly is deprecated. ION_DECIMAL should be used. See ion_reader_read_ion_decimal.

Read integer value from Ion stream. The size of the integer is sizeof(int) If the value in the Ion stream does not fit into the variable, it will return with IERR_NUMERIC_OVERFLOW.

Read integer value from Ion stream. The size of the integer is sizeof(int32_t) If the value in the Ion stream does not fit into the variable, it will return with IERR_NUMERIC_OVERFLOW.

Read integer value from Ion stream. The size of the integer is sizeof(int64_t) If the value in the Ion stream does not fit into the variable, it will return with IERR_NUMERIC_OVERFLOW.

Read integer value from Ion stream. This supports arbitary length integers defined by ion_int.

Read the current symbol value as an ION_SYMBOL.

Read integer value from Ion stream. The size of the integer is sizeof(long), which is 4 or 8 bytes depends on the OS If the value in the Ion stream does not fit into the variable, it will return with IERR_NUMERIC_OVERFLOW.

@return IERR_NULL_VALUE if the current value is null.timestamp.

Resets input stream for given reader.

Resets input user-managed stream for given reader.

moves the stream position to the specified offset. Resets the the state of the reader to be at the top level. As long as the specified position is at the first byte of a top-level value (just before the type description byte) this will work neatly. Do not attempt to seek to a value below the top level, as the view of the data is likely to be invalid.

set the current symbol table to the table passed in. This can be used to reset the readers symbol table is you wish to seek in a stream which contains multiple symbol tables. This symbol table handle should be a handle returned by ion_reader_get_symbol_table.

Returns -1 is idx is out of range or str is null

Gets a pointer to the UTF-8 bytes held by the string. The number of bytes in the string is determined via ion_string_get_length().

Gets the number of UTF-8 bytes held by the string.

Copies an ION_SYMBOL to a new memory owner.

Compares the two given ION_SYMBOLs for equality under the Ion data model.

Imports a shared symbol table into a local symbol table, given a description of the import and the catalog in which it can be found. NOTE: the best match for the described shared symbol table import that is available in the catalog will be used. If no match is found, all of the import’s symbols will be considered to have unknown text. @param hsymtab - The local symbol table into which the imported symbol table will be incorporated. @param pimport - The description of the shared symbol table to be imported. @param catalog - The catalog to query for the matching shared symbol table.

Clones the given symbol table, using that symbol table’s memory owner as the owner of the newly allocated symbol table. @param hsymtab - They symbol table to clone. @param p_hclone - Pointer to a handle to the newly-allocated symbol table clone.

Clones the given symbol table, using the given owner as the newly-allocated symbol table’s memory owner. @param hsymtab - They symbol table to clone. @param p_hclone - Pointer to a handle to the newly-allocated symbol table clone. @param owner - Handle to the new symbol table’s memory owner. If NULL, the resulting symbol table is its own memory owner and must be freed using ion_symbol_table_close.

If the given symbol table is its own memory owner, its memory and everything it owns is freed. If the given symbol table has an external owner and that owner has not been freed, this does nothing; this symbol table will be freed when its memory owner is freed. If the given symbol table has an external owner which has been freed, the behavior of this function is undefined. NOTE: Symbol tables constructed and returned by readers and writers are owned by those readers and writers.

Gets the global system symbol table for the given Ion version. This global system symbol table must never be closed. @param p_hsystem_table - Pointer to a handle to the global system symbol table. @param version - The Ion version. Currently, must be 1.

Imports a shared symbol table into a local symbol table. @param hsymtab - The local symbol table into which the imported symbol table will be incorporated. @param hsymtab_import - The shared symbol table to import.

Deserializes a symbol table (shared or local) from the given reader. @param hreader - The reader, positioned at the start of the symbol table struct. @param owner - Handle to the new symbol table’s memory owner. If NULL, the resulting symbol table is its own memory owner and must be freed using ion_symbol_table_close. @param p_hsymtab - Pointer to a handle to the newly-allocated symbol table.

Allocates a new local symbol table. @param p_hsymtab - Pointer to a handle to the newly-allocated symbol table. @param owner - Handle to the new symbol table’s memory owner. If NULL, the resulting symbol table is its own memory owner and must be freed using ion_symbol_table_close.

Allocates a new local symbol table of the given type (i.e. shared or local). @param p_hsymtab - Pointer to a handle to the newly-allocated symbol table. @param owner - Handle to the new symbol table’s memory owner. If NULL, the resulting symbol table is its own memory owner and must be freed using ion_symbol_table_close.

Serializes a symbol table (shared or local) using the given writer. @param hsymtab - The symbol table to serialize. @param hwriter - The writer (text or binary).

Comparing two timestamps to see whether they represent the same point in time. Two timestamp of different precision will return false

Initialize ION_TIMESTAMP object with value specified. It will have ION_TS_DAY precision

Initialize ION_TIMESTAMP object with value specified. *p_fraction have a range of (0, 1), not including 0 (without significant digit) and 1. 0.0 (0d-1), 0.00(0d-2) is valid, while 0 or 0. is not.

Initialize ION_TIMESTAMP object with value specified. It will have ION_TS_MIN precision

Initialize ION_TIMESTAMP object with value specified. It will have ION_TS_MONTH precision

Initialize ION_TIMESTAMP object with value specified. It will have ION_TS_SEC precision

Initialize ION_TIMESTAMP object with value specified in time_t time_t can be constructed using time() or mktime(), timegm, and it contains ION_TS_SEC precision.

Initialize ION_TIMESTAMP object with value specified. It will have ION_TS_YEAR precision

Gets the effective local offset of a timestamp. The result is zero for timestamps with offsets “Z”, “+00:00”, or “-00:00”. In other words, if ion_timestamp_has_local_offset returns false, this returns zero.

Get the time precision for the given timestamp object. The precision values are defined as ION_TS_YEAR, ION_TS_MONTH, ION_TS_DAY, ION_TS_MIN, ION_TS_SEC and ION_TS_FRAC

Get year, month, day If precision is not up to month/day, 0 will be returned as month/day value.

Get time up to fraction of second precision. If precision is not up to fraction, 0 will be returned.

Get time up to minute precision. If precision is not up to hour/minute, 0 will be returned as hour/minute value.

Get year, month If precision is not up to month, 0 will be returned as month value.

Get time up to second precision. If precision is not up to hour/minute/second, 0 will be returned as hour/minute/second value.

Determines whether a timestamp has a defined local offset (for example, “+08:00” or “Z”. Otherwise, it’s local offest is unknown (“-00:00”), and effectively zero.

Compare timestamps for instant equality only (i.e. precision and local offsets need not be equivalent). NOTE: if this has any use externally, it could be exposed. If not, it should be removed.

Parse timestamp string and construct timestamp object in ptime. This expects a null terminated string.

Changes the local offset of a timestamp. If the timestamp has less than minute precision, the given offset is ignored and the timestamp is unchanged. If the timestamp is changed, ion_timestamp_has_local_offset will be true, and ion_timestamp_get_local_offset will be the given offset.

Get the string format of timestamp.

Fill time_t with value in ION_TIMESTAMP

Removes any local offset from a timestamp. Afterwards, ion_timestamp_has_local_offset will be false, and ion_timestamp_get_local_offset will be zero.

Adds the given list of imports to the writer’s list of imports. These imports will only be used in the writer’s current symbol table context. To configure the writer to use the same list of imports for each new symbol table context, convey that list of imports through ION_WRITER_OPTIONS.

Finishes the writer, frees the writer’s associated resources, and finally frees the writer itself. The writer may not continue writing to the stream after this function is called. If any value is in-progress, closing any writer raises an error, but still frees the writer and any associated memory.

Flushes pending bytes, ending the current symbol table context and forcing an Ion Version Marker if the writer continues writing to the stream. If writer was created using open_stream, also flushes write buffer to stream. If any value is in-progress, finishing any writer is an error. @param p_bytes_flushed - the number of bytes written into the buffer/stream.

Flushes pending bytes without forcing an Ion Version Marker or ending the current symbol table context. If writer was created using open_stream, also flushes write buffer to stream. If any value is in-progress, flushing any writer is an error. @param p_bytes_flushed - the number of bytes written into the buffer/stream.

Ion Writer interfaces. Takes a byte buffer and length which will contain the text or binary content, returns handle to a writer. @param p_hwriter @param buffer Byte buffer, allocated and provided by caller. @param buf_length size of the buffer (0 or greater). If the buffer is not big enough, ion_write operation will return IERR_EOF rather than IERR_OK. @param p_option writer configuration object.

Open stream to write ion data. @param p_hwriter @param fn_block_handler User provided function to write from handler_state buffer to file, @param handler_state Related to write buffer. ion_writer will write to the buffer provided by the handler_state, fn_block_handler will write the buffer to file. @param p_options writer configuration object. @see ion_reader_open_stream @see ion_writer_open_buffer

Adds the imports from the given collection of ION_SYMBOL_TABLE_IMPORT to the options’ imports list. ion_writer_options_initialize_shared_imports must have been called first. The given collection must not contain a system symbol table.

Adds the given array of ION_SYMBOL_TABLE (which must be shared symbol tables) to the options’ imports list. ion_writer_options_initialize_shared_imports must have been called first. The given array must not contain a system symbol table.

Frees the options’ imports list. This must be done once the options are no longer needed, and only if ion_writer_options_initialize_shared_imports was called.

Initializes the options’ imports list. This must be done before calling ion_writer_options_add_*. NOTE: This does NOT need to be called if the writer does not need to use shared imports. @param options - The writer options containing the imports list to initialize.

Sets the writer’s symbol table.

@deprecated use of decQuads directly is deprecated. ION_DECIMAL should be used. See ion_writer_write_ion_decimal.

Sets the writer’s current field name. Only valid if the writer is currently in a struct. It is the caller’s responsibility to keep name in scope until the writer’s next value is written.

Sets the writer’s current field name from the given Ion symbol. Only valid if the writer is currently in a struct. It is the caller’s responsibility to keep field_name in scope until the writer’s next value is written.

Type Definitions

The collections used by the parser are linked lists which are managed by the collection header. the memory used for the nodes is allocated on the parent, which is passed in when the user initializes the collection

The node allocation scheme depends on this layout ! currently that there are only 2 members so it uses the size of the ptr as the base to allocate

Determines which value of the _ion_decimal’s value field is active.

A function that may be called by the reader upon a change to the stream’s symbol table context.

Reader configuration data, could be supplied by user during reader creation time. All fields in the structure are defaulted to 0, except for the following:

An Ion String.

Structure to store time information. time_t only has up to second precision, and time zone support is OS dependent. _ion_timestamp uses decimal to store fraction of a second

Strong typed enum over pointer type.

define the Ion error code enumeration.

Unions