+
+/**
+ * ION writer API.
+ */
+interface Writer {
+ public function writeNull() : void;
+ public function writeTypedNull(Type $type) : void;
+ public function writeBool(bool $value) : void;
+ public function writeInt(int|string $value) : void;
+ public function writeFloat(float $value) : void;
+ public function writeDecimal(Decimal|string $value) : void;
+ public function writeTimestamp(Timestamp|string $value) : void;
+ public function writeSymbol(Symbol|string $value) : void;
+ public function writeString(string $value) : void;
+ public function writeCLob(string $value) : void;
+ public function writeBLob(string $value) : void;
+
+ public function startLob(Type $type) : void;
+ public function appendLob(string $data) : void;
+ public function finishLob() : void;
+
+ public function startContainer(Type $type) : void;
+ public function finishContainer() : void;
+
+ public function writeFieldName(string $name) : void;
+
+ public function writeAnnotation(Symbol|string ...$annotation) : void;
+
+ public function getDepth() : int;
+ public function flush() : int;
+ public function finish() : int;
+
+ // public function writeOne(Reader $reader) : void;
+ // public function writeAll(Reader $reader) : void;
+
+ // public function getCatalog() : Catalog;
+ // public function setCatalog(Catalog $catalog) : void;
+
+ // public function getSymbolTable() : Symbol\Table;
+ // puvlic function setSymbolTable(Symbol\Table $table) : void;
+}
+
+namespace ion\Symbol;
+
+/**
+ * The import location (referring to a shared table) of a symbol.
+ */
+class ImportLocation {
+ /**
+ * Create a new import location.
+ */
+ public function __construct(
+ /**
+ * The name of the shared symbol table.
+ */
+ public readonly string $name,
+ /**
+ * The location (sid) of the symbol within the table.
+ */
+ public readonly int $location,
+ ) {}
+}
+
+/**
+ * Base interface of built-in shared symbol tables.
+ */
+interface Enum {
+ /**
+ * @return \ion\Symbol Instance of the symbol.
+ */
+ public function toSymbol() : \ion\Symbol;
+
+ /**
+ * @return int The symbol id.
+ */
+ public function toSID() : int;
+
+ /**
+ * @return string The symbol's textual representation.
+ */
+ public function toString() : string;
+}
+
+/**
+ * Base interface of an ION symbol table.
+ */
+interface Table {
+ /**
+ * Get the maximum symbol ID within the symbol table.
+ * @return int The maximum symbol ID.
+ */
+ public function getMaxId() : int;
+
+ /**
+ * Add a symbol to the table.
+ *
+ * @param \ion\Symbol|string $symbol The symbol (value) to add.
+ * @return int The symbol ID.
+ */
+ public function add(\ion\Symbol|string $symbol) : int;
+
+ /**
+ * Find a symbol within the symbol table, including imports.
+ *
+ * @param string|int $id The ID or text of the symbol to find.
+ * @return \ion\Symbol|null The symbol found, if any.
+ */
+ public function find(string|int $id) : ?\ion\Symbol;
+
+ /**
+ * Find a symbol within **only this** symbol table, ignoring imports.
+ *
+ * @param string|int $id The ID or text of the symbol to find.
+ * @return \ion\Symbol|null The symbol found, if any.
+ */
+ public function findLocal(string|int $id) : ?\ion\Symbol;
+}
+
+/**
+ * The built-in ION system symbols.
+ */
+enum System : string implements \ion\Symbol\Enum {
+ case Ion = '$ion';
+ case Ivm_1_0 = '$ion_1_0';
+ case IonSymbolTable = '$ion_symbol_table';
+ case Name = 'name';
+ case Version = 'version';
+ case Imports = 'imports';
+ case Symbols = 'symbols';
+ case MaxId = 'max_id';
+ case SharedSymbolTable = '$ion_shared_symbol_table';
+
+ /** @alias ion\Symbol\Enum::toSymbol */
+ public function toSymbol() : \ion\Symbol {}
+ /** @alias ion\Symbol\Enum::toSID */
+ public function toSID() : int {}
+ /** @alias ion\Symbol\Enum::toString */
+ public function toString() : string {}
+
+ /**
+ * Get the built-in ION system shared symbol table.
+ *
+ * @return Table\Shared The system symbol table.
+ */
+ public static function asTable() : Table\Shared {}
+}
+
+/**
+ * The built-in PHP symbols.
+ */
+enum PHP : string implements \ion\Symbol\Enum {
+ case PHP = 'PHP';
+ case Reference = 'R';
+ case Backref = 'r';
+ case Property = 'p';
+ case Object = 'o';
+ case ClassObject = 'c';
+ case MagicObject = 'O';
+ case CustomObject = 'C';
+ case Enum = 'E';
+ case Serializable = 'S';
+
+ /** @alias ion\Symbol\Enum::toSymbol */
+ public function toSymbol() : \ion\Symbol {}
+ /** @alias ion\Symbol\Enum::toSID */
+ public function toSID() : int {}
+ /** @alias ion\Symbol\Enum::toString */
+ public function toString() : string {}
+
+ /**
+ * Get the built-in PHP shared symbol table.
+ *
+ * @return Table\Shared The builtin PHP shared symbol table.
+ */
+ public static function asTable() : Table\Shared {}
+}
+
+namespace ion\Symbol\Table;
+
+/**
+ * A local symbol table.
+ *
+ * @see https://amzn.github.io/ion-docs/guides/symbols-guide.html the ION spec's symbol guide
+ * @see https://amzn.github.io/ion-docs/guides/cookbook.html#using-a-local-symbol-table the ION doc's cookbook
+ */
+class Local implements \ion\Symbol\Table {
+ /** Internal cache. */
+ private array $imports = [];
+ /** Internal cache. */
+ private array $symbols = [];
+
+ /**
+ * Create a local symbol table.
+ */
+ public function __construct() {}
+
+ /**
+ * Import a symbol table.
+ *
+ * @param \ion\Symbol\Table $table The symbol table to import.
+ * @return void
+ */
+ public function import(\ion\Symbol\Table $table) : void {}
+
+ /** @alias ion\Symbol\Table::getMaxId */
+ public function getMaxId() : int {}
+
+ /** @alias ion\Symbol\Table::add */
+ public function add(\ion\Symbol|string $symbol) : int {}
+ /** @alias ion\Symbol\Table::find */
+ public function find(string|int $id) : ?\ion\Symbol {}
+ /** @alias ion\Symbol\Table::findLocal */
+ public function findLocal(string|int $id) : ?\ion\Symbol {}
+}
+
+/**
+ * A shared symbol table.
+ *
+ * @see https://amzn.github.io/ion-docs/guides/symbols-guide.html the ION spec's symbol guide
+ * @see https://amzn.github.io/ion-docs/guides/cookbook.html#using-a-shared-symbol-table the ION doc's cookbook
+ */
+class Shared implements \ion\Symbol\Table {
+ /**
+ * Create a shared symbol table.
+ */
+ public function __construct(
+ /**
+ * The name of the shared symbol table.
+ */
+ public readonly string $name,
+ /**
+ * The version of the shared symbol table.
+ */
+ public readonly int $version = 1,
+ /**
+ * Predefined list of symbols as array of strings.
+ */
+ ?array $symbols = null,
+ ) {}
+
+ /** Internal cache. */
+ private array $symbols = [];
+
+ /** @alias ion\Symbol\Table::getMaxId */
+ public function getMaxId() : int {}
+
+ /** @alias ion\Symbol\Table::add */
+ public function add(\ion\Symbol|string $symbol) : int {}
+ /** @alias ion\Symbol\Table::find */
+ public function find(string|int $id) : ?\ion\Symbol {}
+ /** @alias ion\Symbol\Table::findLocal */
+ public function findLocal(string|int $id) : ?\ion\Symbol {}
+}
+
+namespace ion\Decimal;
+
+/**
+ * An ion\Decimal's context.
+ */
+class Context {
+ /**
+ * Create a new decimal context.
+ */
+ public function __construct(
+ /**
+ * Maximum digits.
+ */
+ public readonly int $digits,
+ /**
+ * Maximum exponent.
+ */
+ public readonly int $eMax,
+ /**
+ * Minimum exponent.
+ */
+ public readonly int $eMin,
+ /**
+ * Rounding mode.
+ */
+ public readonly Context\Rounding|int $round,
+ /**
+ * Whether to clamp.
+ */
+ public readonly bool $clamp,
+ ) {}
+
+ /**
+ * Create a context suitable for 32bit decimals.
+ */
+ public static function Dec32() : Context {}
+
+ /**
+ * Create a context suitable for 64bit decimals.
+ */
+ public static function Dec64() : Context {}
+
+ /**
+ * Create a context suitable for 128bit decimals.
+ */
+ public static function Dec128() : Context {}
+
+ /**
+ * Create a context with maximum settings.
+ * @param Context\Rounding|int $round Rounding mode.
+ */
+ public static function DecMax(Context\Rounding|int $round = Context\Rounding::HalfEven) : Context {}
+}
+
+namespace ion\Decimal\Context;
+
+/**
+ * Rounding mode.
+ */
+enum Rounding : int {
+ case Ceiling = 0;
+ case Up = 1;
+ case HalfUp = 2;
+ case HalfEven = 3;
+ case HalfDown = 4;
+ case Down = 5;
+ case Floor = 6;
+ case Down05Up = 7;
+}
+
+namespace ion\Timestamp;
+
+/**
+ * Timestamp precision.
+ */
+enum Precision : int {
+ case Year = 0x1;
+ case Month = 0x1|0x2;
+ case Day = 0x1|0x2|0x4;
+ case Min = 0x1|0x2|0x4|0x10;
+ case Sec = 0x1|0x2|0x4|0x10|0x20;
+ case Frac = 0x1|0x2|0x4|0x10|0x20|0x40;
+ case MinTZ = 0x1|0x2|0x4|0x10|0x80;
+ case SecTZ = 0x1|0x2|0x4|0x10|0x20|0x80;
+ case FracTZ = 0x1|0x2|0x4|0x10|0x20|0x40|0x80;
+}
+
+/**
+ * Timestamp format.
+ */
+enum Format : string {
+ case Year = "Y\T";
+ case Month = "Y-m\T";
+ case Day = "Y-m-d\T";
+ case Min = "Y-m-d\TH:i";
+ case Sec = "Y-m-d\TH:i:s";
+ case Frac = "Y-m-d\TH:i:s.v";
+ case MinTZ = "Y-m-d\TH:iP";
+ case SecTZ = "Y-m-d\TH:i:sP";
+ case FracTZ = "Y-m-d\TH:i:s.vP";
+}
+