Skip to content

言語リファレンス

wirespec 言語の完全なリファレンスです。入門的な解説は 言語ツアー を参照してください。


プリミティブ整数型

ビット幅符号C マッピング
u88 ビット符号なしuint8_t
u1616 ビット符号なしuint16_t
u2424 ビット符号なしuint32_t(下位 24 ビット)
u3232 ビット符号なしuint32_t
u6464 ビット符号なしuint64_t
i88 ビット符号ありint8_t
i1616 ビット符号ありint16_t
i3232 ビット符号ありint32_t
i6464 ビット符号ありint64_t

u24 は 3 バイトの符号なし整数で、uint32_t に格納されます。パース時は 3 バイト読み取り、シリアライズ時は 3 バイト書き込みます。TLS レコードヘッダなどで使われます。

明示的エンディアンネス整数型

ビット幅エンディアンネスC マッピング
u16be16 ビットビッグエンディアンuint16_t
u16le16 ビットリトルエンディアンuint16_t
u24be24 ビットビッグエンディアンuint32_t
u24le24 ビットリトルエンディアンuint32_t
u32be32 ビットビッグエンディアンuint32_t
u32le32 ビットリトルエンディアンuint32_t
u64be64 ビットビッグエンディアンuint64_t
u64le64 ビットリトルエンディアンuint64_t
i16be16 ビットビッグエンディアンint16_t
i16le16 ビットリトルエンディアンint16_t
i32be32 ビットビッグエンディアンint32_t
i32le32 ビットリトルエンディアンint32_t
i64be64 ビットビッグエンディアンint64_t
i64le64 ビットリトルエンディアンint64_t

明示的エンディアン型は @endian モジュールアノテーションの設定によらず、常に宣言されたエンディアンで読み書きします。1 つの構造体内でエンディアンを混在させたい場合に使います。

ビット型

ビット幅C マッピング
bit1 ビットBitGroup の一部 → uint8_t / uint16_t / uint32_t
bits[N]N ビットBitGroup の一部 → uint8_t / uint16_t / uint32_t

bitbits[1] と等価です。連続する bit / bits[N] フィールドは自動的に 1 回の読み取り操作にまとめられます。詳細は BitGroup パッキング を参照してください。

バイト型

構文セマンティクスC マッピング
bytes[N]固定 N バイトwirespec_bytes_t(ゼロコピー)
bytes[length: EXPR]EXPR バイト(EXPR は整数類似型が必須)wirespec_bytes_t
bytes[remaining]現在のスコープの残りバイトすべてwirespec_bytes_t
bytes[length_or_remaining: EXPR]EXPR が Some の場合はその値、None の場合は残りを消費wirespec_bytes_t

いずれの形式も、入力バッファへのゼロコピービューである wirespec_bytes_t を生成します。

c
typedef struct { const uint8_t *ptr; size_t len; } wirespec_bytes_t;

ヒープアロケーションは発生しません。ポインタは元の入力バッファを直接指します。

セマンティック型

種類使用可能な位置C マッピング
boolセマンティック型(ワイヤ型ではない)let バインディング、guard 条件bool

bool はワイヤフィールドには使えません。let バインディングにおける比較・論理式の結果型として使います。型チェッカーは bool を予約済みの組み込み名として扱うため、ユーザーが bool という名前で型やフィールドを定義することはできません。


bytes スペックバリアント

bytes[...] には 4 つの形式があり、一般的なプロトコルパターンを網羅します。

bytes[N] — 固定長

ちょうど N バイトを読み書きします。N はコンパイル時定数(整数リテラル)です。

wire
reset_token: bytes[16],   # 常に 16 バイト
random:      bytes[32],   # 常に 32 バイト

bytes[length: EXPR] — 長さプレフィックス付き

EXPR で指定されたバイト数を読み書きします。EXPR はパース/シリアライズ時に評価され、整数類似の値(先行フィールドまたはその算術式)でなければなりません。

wire
packet MqttString {
    length: u16,
    data: bytes[length],           # 正確に 'length' バイトを読み取る
}

# 先行フィールドへの算術演算も許可
data: bytes[length: length - 8],  # ヘッダオーバーヘッドを引く

EXPR は整数類似型(u8u16u32u64VarInt 等のセマンティック整数コーデック)でなければなりません。それ以外の型を使うとコンパイルエラーです。

bytes[remaining] — スコープ残り

現在のスコープの残りバイトをすべて消費します。スコープ内の最後のワイヤフィールドである必要があります。後に letrequire を書くのは問題ありませんが、ワイヤフィールドは続けられません。

wire
_ => Unknown { data: bytes[remaining] },   # キャッチオールブランチ
0x0b => ReadRsp  { value: bytes[remaining] },

bytes[length_or_remaining: EXPR] — オプション長さ

EXPR は Option[T](T は整数類似型)でなければなりません。EXPR が非 null ならそのバイト数だけ読み取り、null ならスコープの残りをすべて消費します。

wire
0x08..=0x0f => Stream {
    length_raw: if frame_type & 0x02 { VarInt },
    data: bytes[length_or_remaining: length_raw],
    # ↑ length_raw が存在する場合はその値を使用、そうでなければ残りを消費
},

非オプションの整数を length_or_remaining に渡すとコンパイルエラーです。その場合は bytes[length: EXPR] を使ってください。


継続ビット VarInt

varint { } ブロックは、各バイトの継続フラグで長さが決まる可変長整数型を定義します。MQTT Remaining Length、Protocol Buffers varint、LEB128 などに対応します。

wire
type MqttLength = varint {
    continuation_bit: msb,   # 継続フラグのビット位置
    value_bits: 7,           # 1 バイトあたりのデータビット数
    max_bytes: 4,            # 最大エンコードバイト数(超過 → エラー)
    byte_order: little,      # 下位グループが先
}

パラメータ

パラメータ説明
continuation_bitmsb または lsb各バイト内の継続フラグのビット位置
value_bits正の整数1 バイトあたりのデータビット数
max_bytes正の整数WIRESPEC_ERR_OVERFLOW が返されるまでの最大バイト数
byte_orderlittle または bigバイト重要度順:little = 下位グループが先(MQTT、Protobuf);big = 上位グループが先

max_bytes バイトを読み終えても継続ビットがセットされたままの場合、パーサーは WIRESPEC_ERR_OVERFLOW を返します。

C では、最大値を格納できる最小の符号なし整数型にデコードされます。MqttLength(最大 4 バイト、28 データビット)の場合は uint32_t です。


式言語

優先順位テーブル

結合力の低い順に並べています。同じ行の演算子は同じ優先順位です。

レベル演算子結合性備考
1??コアレス:Option[T] ?? T → T
2or論理 OR
3and論理 AND
4== != < <= > >=なし(非結合)比較
5|ビット OR
6^ビット XOR
7&ビット AND
8<< >>ビットシフト
9+ -加算・減算
10* / %乗算・除算・剰余
11! -単項論理 NOT・単項否定
12. [] [..]メンバアクセス・インデックス・スライス
13() リテラル 名前一次式

ビット演算子と比較演算子の優先順位

wirespec では、ビット演算子(& | ^)は比較演算子(== != < <= > >=)より強く結合します。これは C および Java とは逆です。

wirespec の解析C の解析
a & mask == 0(a & mask) == 0a & (mask == 0)
flags | 0x04 != 0(flags | 0x04) != 0flags | (0x04 != 0)

wirespec のルールはプログラマの意図に沿っています。ビットマスクのテストでは、マスク結果に対して比較を行いたいケースがほとんどです。C のルールはバグの温床として有名で、実質的に毎回余分な括弧が必要になります。

?? コアレス演算子

?? はフォールバック値を指定して Option[T] をアンラップします。

Option[T] ?? T → T
wire
let offset: u64 = offset_raw ?? 0,   # offset_raw が存在しない場合は 0

offset_raw が存在すればその値を返し、null なら右オペランドを返します。右オペランドの型は T と一致している必要があります。

範囲演算子

演算子意味文脈
..=閉区間 [start, end]パターンマッチングのみ
..半開区間 [start, end)スライス式・量化子
wire
0x02..=0x03 => Ack { ... },          # 2 と 3(両端含む)にマッチ
paths[0..active_path_count],          # インデックス 0 から count-1 まで

リテラル

形式
十進整数42255整数
十六進整数0x060x1c整数
二進整数0b000b11整数
文字列"hello"文字列(アノテーションのみ)
真偽値truefalsebool
NullnullOption の null リテラル

フィールドの種類

概要テーブル

種類構文ワイヤ上?C 構造体?備考
ワイヤname: TYesYesパース中にバイトを消費
オプションname: if COND { T }条件付きYesC では bool has_name; T name;
導出let name: T = EXPRNoYes先行フィールドから計算
検証require EXPRNoNo実行時チェック;エラー → WIRESPEC_ERR_CONSTRAINT

ワイヤフィールド

ワイヤフィールドは宣言順に入力からバイトを消費します。

wire
src_port: u16,
dst_port: u16,
length:   u16,
checksum: u16,

オプションフィールド

COND が true のときだけワイヤ上に存在するフィールドです。COND では、先に宣言されたワイヤフィールドや let フィールドを参照できます。

wire
ecn_counts: if frame_type == 0x03 { EcnCounts },
offset_raw: if frame_type & 0x04 { VarInt },
packet_id:  if qos > 0 { u16 },

C では:

c
bool has_ecn_counts;
ecn_counts_t ecn_counts;

後続の式でオプションフィールドの値を使うには、同じ条件でガードするか ?? でデフォルトを指定してください。

導出フィールド(let

let フィールドはバイトを消費せず、先行フィールドから値を計算して構造体に格納します。

wire
let offset: u64  = offset_raw ?? 0,
let fin:   bool  = (frame_type & 0x01) != 0,
let qos:   u8    = (type_and_flags & 0x06) >> 1,

let では同スコープのワイヤフィールドや先行する let フィールドを参照できます。boollet でのみ使えるセマンティック型で、ワイヤフィールドには使えません。

シリアライズ時はワイヤフィールドから式を再計算するため、構造体に格納された let の値は使われません。

検証(require

require EXPR はパース時の実行時チェックです。EXPR が false なら WIRESPEC_ERR_CONSTRAINT を返します。

wire
require length >= 8,
require length <= MAX_CID_LENGTH,
require data_offset >= 5,
require type_and_flags & 0x0F == 0x02,

require はフィールド間のどこにでも書けます。先に宣言されたワイヤフィールドや let フィールドを参照でき、C 構造体には現れません。

コンパイル時アサーション(static_assert

static_assert EXPR はコンパイル時に評価され、失敗するとコード生成前にエラーになります。

wire
const MAX_CID_LENGTH: u8 = 20
static_assert MAX_CID_LENGTH <= 255

フィールドの可視性と順序

packetframe ブランチ、capsule 内のフィールドは、同スコープの後続フィールドから宣言順(上から下)に参照できます。

  • bytes[length: X] は先に宣言されたフィールド X を参照可能。
  • if COND は先に宣言されたフィールドを参照可能。
  • let は先に宣言されたワイヤフィールドまたは先行する let を参照可能。
  • require は先に宣言されたワイヤフィールドや let を参照可能。
  • 自身または後方のフィールドへの参照はコンパイルエラー。

スコープ規則

bytes[remaining][T; fill] は現在のスコープの残りをすべて消費するため、スコープ内の最後のワイヤフィールドでなければなりません。letrequire は後に続けられます。

スコープ境界

以下の構成要素はそれぞれ独立したスコープを形成します。

構成要素スコープ
packet Foo { ... }{ ... } の本体全体
frame の各ブランチ=> Name { ... } の本体
capsule ヘッダフィールドwithin 節より前のフィールド
capsule within の各ブランチ=> Name { ... } の本体
if COND { T }条件内部の単一フィールド T

bytes[remaining] が合法な場所

wire
# ブランチ本体 — OK
frame F = match tag: u8 {
    0 => A { data: bytes[remaining] },
    1 => B { x: u8, data: bytes[remaining] },
}

# capsule within ブランチ — OK
capsule C {
    type: u8, length: u16,
    payload: match type within length {
        0 => D { entries: [Entry; fill] },
        _ => Unknown { data: bytes[remaining] },
    },
}

bytes[remaining] が不正な場所

wire
# NG: remaining の後にワイヤフィールドが続く
packet Bad {
    data: bytes[remaining],  # コンパイルエラー:ワイヤフィールドが後続
    trailer: u8,
}

整数類似型

配列カウント、バイト長(bytes[length: ...])、スコープ長(within EXPR)で使える型です。

  • プリミティブ: u8u16u24u32u64
  • セマンティック整数コーデック: varint { } で定義したユーザー型(VarIntMqttLength 等)。基礎となる符号なし整数に解決されます。

符号あり整数(i8 等)、boolbytes、複合型、非整数の列挙型、非整数の Option は整数類似型ではなく、配列カウントやバイト長に使うとコンパイルエラーです。


BitGroup パッキング

連続する bit / bits[N] フィールドは自動的に 1 回のワイヤ読み取りにまとめられます。

  1. グループ内のビット合計は 8 の倍数(整数バイト)でなければならない(コンパイル時チェック)。
  2. @endian big(デフォルト):先に宣言したフィールドが上位ビットを占める。
  3. @endian little:先に宣言したフィールドが下位ビットを占める。
  4. 各フィールドは生成 C コードでシフト+マスクにより抽出される。
wire
# examples/ip/ipv4.wspec より(ビッグエンディアン)
packet IPv4Header {
    version: bits[4],        # バイト 0 の上位 4 ビット
    ihl:     bits[4],        # バイト 0 の下位 4 ビット
    dscp:    bits[6],        # バイト 1 の上位 6 ビット
    ecn:     bits[2],        # バイト 1 の下位 2 ビット
    total_length: u16,       # 別途の u16 フィールド
    ...
}

生成される C コード:

c
uint8_t _b0 = buf[pos++];
out->version = (_b0 >> 4) & 0x0f;
out->ihl     = (_b0 >> 0) & 0x0f;
uint8_t _b1 = buf[pos++];
out->dscp    = (_b1 >> 2) & 0x3f;
out->ecn     = (_b1 >> 0) & 0x03;

BitGroup はビット型以外のフィールドが出現するか、構造体の末尾で区切られます。


予約済み識別子

以下の名前は wirespec の型チェッカーまたはランタイムで特別な意味を持ちます。ユーザーコードでこれらの名前の型・フィールド・変数・イベントを定義することはできません。

名前種類許可される文脈
bool組み込みセマンティック型let バインディング型、guard 式の結果
null組み込みリテラル値Option[T] 比較、?? の右オペランド
fillキーワードおよび組み込み関数配列サイズ式([T; fill]);イニシャライザ式(fill(value, count)
remainingキーワードbytes_spec のみ:bytes[remaining]
in_state組み込み述語状態機械での guardverifyall()
all組み込み量化子状態機械での guardverify
child_state_changed内部イベントdelegate によって発行される;ユーザー定義イベント名として使用不可
src遷移バインディング状態機械遷移内の guard および action ブロック
dst遷移バインディング状態機械遷移内の action ブロック

これらの識別子で型・定数・フィールド・イベントを定義しようとするとコンパイルエラーです。


トップレベル宣言

module

wire
module quic.varint
module ble.att
module mqtt

現在のファイルのモジュール識別子を宣言します。ドット区切りの名前はファイルパスに対応し、quic.varint はインクルードパス上の quic/varint.wspec(または quic/varint.wspec)に解決されます。1 ファイルにつき module 宣言は最大 1 つで、他の宣言より前に書く必要があります。

import

wire
import quic.varint.VarInt
import quic.varint           # モジュール自体をインポート

別モジュールの名前を現在のファイルに導入します。循環インポートはコンパイルエラー、相対インポートは非対応です。

const

wire
const MAX_CID_LENGTH: u8 = 20
const QUIC_VERSION_1: u32 = 0x00000001

コンパイル時定数を定義します。型はプリミティブ整数型でなければなりません。整数リテラルを書ける場所ならどこでも使えます。

enum

wire
enum ContentType: u8 {
    ChangeCipherSpec = 20,
    Alert            = 21,
    Handshake        = 22,
    ApplicationData  = 23,
}

整数値の名前付きセットを定義します。基礎ワイヤ型を : の後に指定します。enum 型は framecapsule のマッチタグとしても使えます。C では typedef enum に変換されます。

flags

wire
flags PacketFlags: u8 {
    KeyPhase = 0x04,
    SpinBit  = 0x20,
    FixedBit = 0x40,
}

enum と同様ですが、値はビット演算で組み合わせて使うビットマスクです。C では typedef enum になります。enum との違いは意味的な区別のみです。

type

2 つの形式があります。

型エイリアス -- 新しいワイヤレイアウトは導入しません。

wire
type AttHandle = u16le
type Uuid16    = u16le

計算型 -- フィールドの型が先行フィールドの値に依存する依存レコード。

wire
@strict
type VarInt = {
    prefix: bits[2],
    value: match prefix {
        0b00 => bits[6],
        0b01 => bits[14],
        0b10 => bits[30],
        0b11 => bits[62],
    },
}

継続ビット VarInt -- バイトごとの継続フラグで長さが決まる可変長整数。

wire
type MqttLength = varint {
    continuation_bit: msb,
    value_bits: 7,
    max_bytes: 4,
    byte_order: little,
}

packet

名前付きフィールドの固定シーケンスで、プロトコルヘッダを記述する基本的な構成要素です。

wire
packet UdpDatagram {
    src_port: u16,
    dst_port: u16,
    length:   u16,
    checksum: u16,
    require length >= 8,
    data: bytes[length: length - 8],
}

frame

タグ付きユニオンです。まずタグフィールドを読み取り、パターンマッチでペイロードのレイアウトを決定します。

wire
frame AttPdu = match opcode: u8 {
    0x02 => ExchangeMtuReq { client_rx_mtu: u16le },
    0x03 => ExchangeMtuRsp { server_rx_mtu: u16le },
    0x0a => ReadReq  { handle: AttHandle },
    0x0b => ReadRsp  { value: bytes[remaining] },
    _ => Unknown {},
}

パターンの形式:

パターンマッチ
0x06正確な値
0x02..=0x03閉区間 [0x02, 0x03]
_任意の値(キャッチオール、網羅性のために必須)

capsule

TLV(Type-Length-Value)コンテナです。ヘッダ部の後に within EXPR 節があり、ペイロードのパースを EXPR バイトに制約します。

wire
capsule MqttPacket {
    type_and_flags:   u8,
    remaining_length: MqttLength,
    payload: match (type_and_flags >> 4) within remaining_length {
        1  => Connect { ... },
        3  => Publish { ... },
        _  => Unknown { data: bytes[remaining] },
    },
}

タグ式(within の前)は以下のいずれかです。

  • フィールド名をそのまま使う:match content_type within length
  • ヘッダフィールドからの括弧付き式:match (type_and_flags >> 4) within remaining_length

ペイロードブランチが EXPR より少ないバイトしか消費しなかった場合は WIRESPEC_ERR_TRAILING_DATA、超過した場合は WIRESPEC_ERR_SHORT_BUFFER を返します。

static_assert

wire
static_assert MAX_CID_LENGTH <= 255

コンパイル時に評価され、失敗するとコード生成が中断されます。


アノテーション

アノテーションは対象の定義の直前に記述します。

アノテーション適用対象Phase効果
@endian bigモジュール(ファイル先頭)1デフォルトエンディアンネスをビッグエンディアンに設定
@endian littleモジュール(ファイル先頭)1デフォルトエンディアンネスをリトルエンディアンに設定
@stricttype 定義1非正規表現を WIRESPEC_ERR_NONCANONICAL で拒否
@checksum(internet)フィールド(u161RFC 1071 Internet チェックサム:パース時に検証、シリアライズ時に自動計算
@checksum(crc32)フィールド(u321IEEE 802.3 CRC-32:パース時に検証、シリアライズ時に自動計算
@checksum(crc32c)フィールド(u321Castagnoli CRC-32C:パース時に検証、シリアライズ時に自動計算
@checksum(fletcher16)フィールド(u161RFC 1146 Fletcher-16:パース時に検証、シリアライズ時に自動計算
@max_len(N)配列フィールド1フィールドごとの配列キャパシティを N 要素にオーバーライド
@doc("...")任意の定義1ドキュメント文字列(コード生成ではまだ未使用)
@derive(...)定義2+将来の使用のために予約
@verify(bound=N)状態機械3+TLA+ 有界検証の深さ

@checksum は 1 つの packet / frame ブランチにつき最大 1 つです。フィールド型はアルゴリズムの要件と一致する必要があります(上表を参照)。


配列

カウントバインド配列

wire
ack_ranges: [AckRange; ack_range_count],   # 先行フィールドからのカウント
cipher_suites: [u16; cipher_suites_length / 2],  # 算術カウント

カウント式は整数類似型でなければなりません。実行時にフィールドのキャパシティと照合されます。

フィル配列

wire
entries: [Entry; fill],   # 現在のスコープの残りを消費

[T; fill] はスコープの残りから T 要素を可能な限り読み取ります。スコープ内の最後のワイヤフィールドでなければなりません。

フィル within 配列

wire
extensions: [Extension; fill] within extensions_length,

extensions_length バイトのサブスコープを作成し、その中で Extension 要素を読み切るまでパースします。未消費のバイトが残れば WIRESPEC_ERR_TRAILING_DATA、超過すれば WIRESPEC_ERR_SHORT_BUFFER です。

配列キャパシティ(C バックエンド)

配列は固定キャパシティでスタック確保されます。デフォルトは WIRESPEC_MAX_ARRAY_ELEMENTS(64)で、wirespec_runtime.h で定義されています。-DWIRESPEC_MAX_ARRAY_ELEMENTS=N でグローバルに変更できます。

フィールド単位でのオーバーライド:

wire
@max_len(1024)
large_items: [Item; count],   # このフィールドのみキャパシティ 1024

ワイヤ上のカウントがキャパシティを超えた場合、パーサーは WIRESPEC_ERR_CAPACITY を返します。


モジュールとインポート

wire
module quic.varint         # このファイルのモジュール識別子を宣言
import quic.varint.VarInt  # quic/varint.wspec から VarInt をインポート

モジュール名はインクルードパス(-I フラグ)上のファイルパスに対応します。コンパイラがインポートを解決し、循環を検出し、C の #include をトポロジカル順序で生成します。

規則:

  • デフォルトではすべての宣言がパブリック。モジュール内のいずれかのアイテムに export がある場合、エクスポートされたものだけが外部から見える(リゾルバが可視性を強制する)。
  • 循環インポートはコンパイルエラー。
  • 相対インポートは非対応。すべて絶対モジュールパスで指定。
  • module 宣言のないファイルも単一ファイルモードでコンパイル可能。

状態機械宣言

状態機械は state machine Name { } で定義します。完全な構文は 状態機械ガイド を参照してください。ここではキーワードと予約名の概要を示します。

キーワード

キーワード役割
state machine状態機械定義を導入
state状態を宣言(オプションで関連データフィールドを持つ)
initial初期状態を指定
transitionある状態(または *)から別の状態への遷移を宣言
on遷移をトリガーするイベント
guard真偽条件。true のときだけ遷移が発火する
action遷移発火時に実行する代入ブロック
delegateイベントを子状態機械に転送
verify検証プロパティの宣言(Phase 3)
[terminal]終端状態のマーク(出ていく遷移が不要)

src および dst バインディング

遷移内では以下のバインディングが使えます。

  • src -- 遷移元の状態データ(guard / action で読み取り専用)
  • dst -- 遷移先の状態データ(action で書き込み専用)

src / dstguardaction ブロック内でのみ有効です。verify プロパティでは使えません(verify では裸のフィールド名で現在の状態を参照します)。

delegate セマンティクス

delegate src.field <- event はイベントを子状態機械に転送します。

  1. dstsrc のコピーとして暗黙的に初期化される。
  2. dst 内の子フィールドがイベントを受け取り、インプレースで遷移する。
  3. 子が別の状態に遷移した場合、child_state_changed が親に新イベントとして発行される。
  4. child_state_changed に対応する遷移がなければ無音で破棄される(「未処理イベント = エラー」規則の唯一の例外)。

delegate は自己遷移(遷移元と遷移先が同じ状態)でのみ使用可能です。delegateaction は同一遷移内で共存できません。

all() 量化子

wire
guard all(src.paths[0..src.active_path_count], in_state(Closed))

all(collection, predicate)collection の全要素が predicate を満たすとき true を返します。Phase 1 でサポートされる述語は in_state(S) のみです。all() は組み込みの特殊形式であり、汎用的な高階関数ではありません。


エラーコード

C バックエンドの生成関数は wirespec_result_t を返します。取りうる値は以下のとおりです。

コード意味
WIRESPEC_OK成功
WIRESPEC_ERR_SHORT_BUFFER入力のバイトが不足
WIRESPEC_ERR_INVALID_TAGタグ値がどのパターンにもマッチせず _ もない
WIRESPEC_ERR_CONSTRAINTrequire 式が false
WIRESPEC_ERR_OVERFLOW整数オーバーフロー(長さ超過、varint の max_bytes 超過など)
WIRESPEC_ERR_INVALID_STATE状態機械が対応する遷移のないイベントを受信
WIRESPEC_ERR_TRAILING_DATAwithin スコープが完全に消費されていない
WIRESPEC_ERR_NONCANONICAL@strict 型が非正規(非最小長)形式でエンコードされている
WIRESPEC_ERR_CAPACITY配列カウントがフィールドのキャパシティを超過
WIRESPEC_ERR_CHECKSUMパース時の @checksum 検証失敗
WIRESPEC_ERR_SCOPE_UNDERFLOWサブカーソルのアンダーフロー(内部エラー)
WIRESPEC_ERR_ARRAY_OVERFLOW配列インデックスが範囲外(内部エラー)

文法サマリー

完全な形式文法は 文法リファレンス にあります。主要な生成規則を以下に示します。

file        = { annotation | module_decl | import_decl | top_item }
top_item    = const_def | enum_def | flags_def | type_def
            | packet_def | frame_def | capsule_def | static_assert_def

type_expr   = type_ref
            | "match" NAME "{" match_branch { "," match_branch } "}"
            | "if" expr "{" type_expr "}"
            | "[" type_expr ";" array_size "]"
            | "bytes" "[" bytes_spec "]"

bytes_spec  = INTEGER
            | "remaining"
            | "length" ":" expr
            | "length_or_remaining" ":" expr

pattern     = literal | literal "..=" literal | "_"