IonCursor.java

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package com.amazon.ion;

import java.io.Closeable;

/**
 * A cursor over a stream of Ion data. NOTE: this interface is not considered part of the public API.
 */
public interface IonCursor extends Closeable {

    /**
     * Conveys the type of event that occurred as a result of operating on the cursor.
     */
    enum Event {

        /**
         * There is not enough data in the stream to complete the requested operation. The operation should be retried
         * when more data is available. Note that there is no way to "cancel" a previously requested operation;
         * requesting a different operation after a `NEEDS_DATA` event has undefined behavior.
         */
        NEEDS_DATA,

        /**
         * The cursor has completed an operation (e.g. `stepIntoContainer()`) and requires another instruction in order
         * to position itself on the next value.
         */
        NEEDS_INSTRUCTION,

        /**
         * The cursor is positioned on a scalar value.
         */
        START_SCALAR,

        /**
         * The cursor has successfully buffered the entirety of the value on which it is currently positioned, as
         * requested by an invocation of `fillValue()`.
         */
        VALUE_READY,

        /**
         * The cursor is positioned on a container value.
         */
        START_CONTAINER,

        /**
         * The cursor has reached the end of the current container, and requires an instruction to proceed.
         */
        END_CONTAINER
    }

    /**
     * Advances the cursor to the next value, skipping the current value (if any). This method may return:
     * <ul>
     *     <li>NEEDS_DATA, if not enough data is available in the stream</li>
     *     <li>START_SCALAR, if the reader is now positioned on a scalar value</li>
     *     <li>START_CONTAINER, if the reader is now positioned on a container value</li>
     *     <li>END_CONTAINER, if the reader is now positioned at the end of a container value, or</li>
     *     <li>NEEDS_INSTRUCTION, if the reader skipped a value for exceeding the configured maximum buffer size</li>
     * </ul>
     * @return an Event conveying the result of the operation.
     */
    Event nextValue();

    /**
     * Steps the cursor into the container value on which the cursor is currently positioned. This method may return:
     * <ul>
     *     <li>NEEDS_DATA, if not enough data is available in the stream</li>
     *     <li>NEEDS_INSTRUCTION, when successful, indicating that the caller must invoke another method on the cursor
     *     in order to position it on a value
     *     </li>
     * </ul>
     * @return an Event conveying the result of the operation.
     */
    Event stepIntoContainer();

    /**
     * Steps the cursor out of the current container, skipping any values in the container that may follow. This method
     * may return:
     * <ul>
     *     <li>NEEDS_DATA, if not enough data is available in the stream</li>
     *     <li>NEEDS_INSTRUCTION, when successful, indicating that the caller must invoke another method on the cursor
     *     in order to position it on a value
     *     </li>
     * </ul>
     * @return an Event conveying the result of the operation.
     */
    Event stepOutOfContainer();

    /**
     * Buffers the entirety of the value on which the cursor is currently positioned. This method may return:
     * <ul>
     *     <li>NEEDS_DATA, if not enough data is available in the stream</li>
     *     <li>VALUE_READY, if the value was successfully filled</li>
     *     <li>NEEDS_INSTRUCTION, if the value exceeded the configured maximum buffer size and could not be buffered</li>
     * </ul>
     * @return an Event conveying the result of the operation.
     */
    Event fillValue();

    /**
     * Conveys the result of the previous operation.
     * @return an Event conveying the result of the previous operation.
     */
    Event getCurrentEvent();

    /**
     * Causes the cursor to force completion of the value on which it is currently positioned, if any. This method may
     * return:
     * <ul>
     *     <li>NEEDS_DATA, if called when the reader is not positioned on a value, or</li>
     *     <li>START_SCALAR, if ending the stream at the current position unambiguously results in a complete value</li>
     * </ul>
     * Note: in binary Ion, it is never ambiguous whether a value is complete. Therefore, binary IonCursor
     * implementations will only return NEEDS_DATA or throw from this method. In text Ion, ambiguity is possible.
     * For example, the stream <code>true</code> will initially return NEEDS_DATA from {@link #nextValue()} because
     * it cannot yet be known whether the stream contains the boolean value <code>true</code> or, e.g., the symbol
     * value <code>trueNorth</code>. In this example, calling this method will return START_SCALAR, with the cursor
     * positioned on a boolean value.
     * @return an Event conveying the result of the operation.
     * @throws IonException if this method is called below the top level or when the cursor is positioned on an
     * incomplete value.
     */
    Event endStream();
}