/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { Type } from "@sinclair/typebox";
import { unionOptions } from "../../../../codec/index.js";
import { Count, IdentifierOrIndex, ShapeIndex } from "./formatGeneric.js";
export const EncodedNestedArrayShape = ShapeIndex;
export const EncodedInlineArrayShape = Type.Object({
    length: Count,
    /**
     * All entries are this shape.
     */
    shape: ShapeIndex,
}, { additionalProperties: false });
export const EncodedAnyShape = Type.Literal(0);
export const EncodedFieldShape = Type.Tuple([
    /**
     * Field key for this field.
     */
    IdentifierOrIndex,
    /**
     * Shape of data in this field.
     */
    ShapeIndex,
]);
/**
 * Used in {@link EncodedValueShape} for special field kind handling.
 */
export var SpecialField;
(function (SpecialField) {
    /**
     * Special case for Identifier field kind.
     */
    SpecialField[SpecialField["Identifier"] = 0] = "Identifier";
})(SpecialField || (SpecialField = {}));
/**
 * Shape of a value on a node.
 *
 * Due to limitations of TypeBox and differences between JavaScript objects, TypeScript types and JSON,
 * the case where no information about the value is captured in the shape is a bit confusing.
 * In TypeBox this is allowed by the user of this type putting it in an optional property.
 * In TypeScript it is modeled using `undefined`.
 * In JavaScript the property may be missing or explicitly `undefined`.
 * In JSON this will serialize as the property being omitted.
 * In this case, the value will be encoded as either:
 * - `false` (when there is no value) OR
 * - `true, value` when there is a value.
 *
 * For a more compact encoding, there are 4 options for the shape:
 * - `true`: there is a value, and it will simply be encoded by putting it in the output buffer (so `value`).
 * - `false`: there is never a value, and it takes up no space in the output buffer.
 * - `[value]`: there is a value, and its always the same.
 * - `SpecialField.Identifier`: special case for node identifier handling.
 * Takes up no space in the output buffer: the value comes from the shape arrays's content.
 * It is wrapped in an array to differentiate value shape types.
 *
 * In the future other value shape formats may be added, likely as objects.
 *
 * @remarks
 * See {@link EncodedNodeShape} for usage.
 */
export const EncodedValueShape = Type.Union([
    Type.Boolean(),
    Type.Array(Type.Any(), { minItems: 1, maxItems: 1 }),
    Type.Enum(SpecialField),
    // TODO: support delta encoding and/or special node identifier handling
    // EncodedCounter,
]);
export const EncodedNodeShape = Type.Object({
    /**
     * If not provided, inlined in data.
     */
    type: Type.Optional(IdentifierOrIndex),
    value: Type.Optional(EncodedValueShape),
    /**
     * Fields with fixed (per key) shapes.
     * They are encoded in the order they are specified here.
     * To ensure the order is preserved, this is an array instead of an object with keys.
     */
    fields: Type.Optional(Type.Array(EncodedFieldShape)),
    /**
     * If undefined, no data. Otherwise, nested array of `[key, ...data]*`
     * Covers any fields beyond those in `fields`.
     */
    extraFields: Type.Optional(ShapeIndex),
}, { additionalProperties: false });
/**
 * The chunk shapes supported by the V1 format.
 * @remarks
 * See {@link EncodedChunkShapeV1}.
 */
export const shapesV1 = {
    /**
     * {@link EncodedNestedArrayShape} union member.
     */
    a: Type.Optional(EncodedNestedArrayShape),
    /**
     * {@link EncodedInlineArrayShape} union member.
     */
    b: Type.Optional(EncodedInlineArrayShape),
    /**
     * {@link EncodedNodeShape} union member.
     */
    c: Type.Optional(EncodedNodeShape),
    /**
     * {@link EncodedAnyShape} union member.
     */
    d: Type.Optional(EncodedAnyShape),
};
export const EncodedChunkShapeV1 = Type.Object({ ...shapesV1, e: Type.Optional(Type.Never()) }, unionOptions);
//# sourceMappingURL=formatV1.js.map