catbufferのファイルの読み方

# catbufferのファイルの読み方

https://github.com/symbol/symbol/blob/dev/catbuffer/parser/docs/cats_dsl.md

こちらの日本語訳をまずします。

## CATS DSL
CATS are composed of three primary declarations: using, enum, struct. Schemas are whitespace significant.

## CATS DSL 日本語訳
CATS DSL
CATSは、using、enum、structの3つの主要な宣言から構成されています。スキーマは、空白が重要です。

### 補足
DSL 【Domain-Specific Language】 ドメイン固有言語 / ドメイン特化言語
https://e-words.jp/w/DSL.html

## import
CATS files can include other files by using the import statement. For example, to import a file called "other.cats":

```
import "other.cats"
```

All imported filenames are relative to the include path passed to the parser. Using the CLI tool, this can be specified by the --include command line argument.

## import 日本語訳

CATSファイルは、import文を使って他のファイルを含めることができます。例えば、"other.cats "というファイルをインポートするには、以下のようにします。


```
import "other.cats"
```

インポートされるファイル名はすべて、パーサーに渡されたインクルードパスからの相対パスとなります。CLIツールを使用する場合は、--includeコマンドライン引数で指定することができます。

### 補足

```
symbol/catbuffer/schemas/symbol/
```

インクルードパスがこれに該当するのかな？

とりあえずsymbolのcatbufferでは
symbol/catbuffer/schemas/symbolを基準にそこからの相対パスで宣言してimportをすることができるみたい。

それをどうやっているかは知らん。

https://github.com/symbol/symbol/tree/dev/catbuffer/parser

ここのReadmeっぽいな。

https://github.com/symbol/symbol/tree/dev/catbuffer/parser#usage

https://github.com/symbol/symbol/tree/dev/catbuffer/parser#examples

## using

Alias statements can be used to name a unique POD type. CATS supports two types of built-ins:

- Integer types: unsigned ("uint") and signed ("int") for sizes { 1, 2, 4, 8 }. For example, to define a Height type that is represented by a 8 byte unsigned integer:

```
using Height = uint64
```

- Fixed buffer types: unsigned byte buffer of any length. For example, to define a PublicKey type that is represented by a 32 byte unsigned buffer:

```
using PublicKey = binary_fixed(32)
```

Importantly, each alias will be treated as a unique type and cannot be used interchangeably. For example, Weight cannot be used where Height is expected and vice versa.

```
using Height = uint64
using Weight = uint64
```

## using（日本語訳）

Aliasステートメントは、ユニークなPODタイプに名前を付けるために使用することができます。CATS は、2 種類の組み込み型をサポートしています。:

- 整数型：符号なし（"uint"）と符号あり（"int"）、サイズは { 1, 2, 4, 8 } です。例えば、8 バイトの符号なし整数で表現される Height 型を定義するには、次のようにします。:

```
using Height = uint64
```

uint64ということは64ビット演算子での8バイト分ってことか。

- 固定バッファタイプ: 任意の長さの符号なしバイトバッファ。例えば、32バイトの符号なしバッファで表現されるPublicKey型を定義するには、以下のようになります。:

```
using PublicKey = binary_fixed(32)
```

重要なことは、それぞれの別名はユニークな型として扱われ、互換性を持って使用することはできないということです。例えば、WeightはHeightと同じように使うことはできませんし、その逆も同様です。

```
using Height = uint64
using Weight = uint64
```

POD（Plain Old Data)？？
これで合っているんかな？

う〜ん難しいなぁ。
一つ宣言したものは使い回しはでけへんぞということかな？

## enum

Enumeration statements can be used to define a set of possible values. Each enumeration specifies an integer backing type.

For example, to define a TransportMode enumeration backed by a 2 byte unsigned integer:

```
enum TransportMode : uint16
```

Values making up an enumeration follow the enumeration declaration on indented lines. For example, to add three values to the TransportMode enumeration named ROAD (value 0x0001) and SEA (0x0002) and SKY (0x0004):

```
enum TransportMode : uint32
	ROAD = 0x0001
	SEA = 0x0002
	SKY = 0x0004
```

## enum（日本語訳）

Enumerationステートメントは、可能な値のセットを定義するために使用することができます。
各列挙は、整数のバックタイプを指定します。

例えば、TransportMode 列挙を定義する場合、2 バイトの符号なし整数をバックにしています。

```
enum TransportMode : uint16
```

列挙型を構成する値は、インデントされた行の列挙型宣言に従います。
例えば、TransportMode列挙型にROAD（値0x0001）、SEA（0x0002）、SKY（0x0004）という
3つの値を追加する場合、以下のようになります。

```
enum TransportMode : uint32
	ROAD = 0x0001
	SEA = 0x0002
	SKY = 0x0004
```

ここは難しい。

enumは条件指定みたいな認識、縛りを持たせていろんなこと

TransportMode.ROAD = 0x0001
TransportMode.SEA = 0x0002
TransportMode.SKY = 0x0004

https://doc.rust-jp.rs/book-ja/ch06-01-defining-an-enum.html

多分これに近いのかな？
この辺りよくわからん。

## attributes

Hints can be attached to enumerations using attributes.

Enumerations support the following attributes:

is_bitwise: indicates that the enumeration represents flags and should support bitwise operations.
For example, to set the is_bitwise attribute on the TransportMode enumeration:


```
@is_bitwise
enum TransportMode : uint32
	ROAD = 0x0001
	SEA = 0x0002
	SKY = 0x0004
```

## 属性
ヒントは、属性を使用して列挙に添付できます。

列挙型は、次の属性をサポートします。

is_bitwise：列挙がフラグを表し、ビット演算をサポートする必要があることを示します。
たとえば、列挙型にis_bitwise属性を設定するには、次のようにします。TransportMode

```
@is_bitwise
enum TransportMode : uint32
	ROAD = 0x0001
	SEA = 0x0002
	SKY = 0x0004
```

は？何書いてあるねん。

@以降のis_bitwiseところでenumに対してis_bitwiseという属性ができることを意味する

is_bitwise：列挙がフラグを表し、ビット演算をサポートする必要があることを示します。

https://doc.rust-jp.rs/rust-by-example-ja/attribute.html

要素に対するメタデータ（この場合はTransportModeに対するメタデータとしてis_bitwiseを当てている）


## struct
Structure statements are used to define structured binary payloads. Structure definition are comprehensive. Unlike other formats, the CATS parser will never add extraneous data or padding.

Structures can have any of the following modifiers:

1. None: Generators are recommended to include the type in final output.
2. abstract: Generators are recommended to include the type in final output and produce corresponding factory.
3. inline: Generators are recommended to discard the structure from final output.


For example, to define a Vehicle struct with the abstract modifier:

```
abstract struct Vehicle
```

Fields making up a structure follow the structure declaration on indented lines. For example, to add an 8 byte unsigned weight field of type to the Vehicle structure:

```
abstract struct Vehicle
	weight = uint32
```

make_const can be used to define a const field, which does not appear in the struct layout. For example, to define a 2 byte unsigned constant TRANSPORT_MODE with value ROAD:

```
struct Car
	TRANSPORT_MODE = make_const(TransportMode, ROAD)
```

make_reserved can be used to define a reserved field, which does appear in the layout and specifies a default value. For example, to define a 1 byte unsigned constant wheel_count with value 4:

```
inline struct Car
	wheel_count = make_reserved(uint8, 4)
```

sizeof can be used to define a field that is filled with the size of another field. For example, to define a 2 byte unsigned car_size that is filled with the size of the car field:

```
inline struct SingleCarGarage
	car_size = sizeof(uint16, car)

	car = Car
```


## struct（構造体）
Structureステートメントは、構造化されたバイナリペイロードを定義するために使用されます。構造体の定義は包括的です。他のフォーマットとは異なり、CATSパーサーは余計なデータやパディングを追加することはありません。

構造体は、以下のいずれかの修飾子を持つことができます。

1. None：ジェネレータは、最終出力に型を含めることが推奨されます。
2. abstract:ジェネレータは、最終出力にその型を含め、対応するファクトリーを生成することが推奨されます。(抽象化）
3. inline:ジェネレーターは、最終出力から構造体を破棄することが推奨されます。


例えば、abstract修飾子を持つVehicle構造体を定義する場合、以下のようになります。

```
abstract struct Vehicle
```

構造体を構成するフィールドは、構造体宣言に続いてインデントされた行で記述されます。例えば、Vehicle構造体に8バイトのunsigned weight型のフィールドを追加するには、次のようにします。

```
abstract struct Vehicle
	weight = uint32
```

make_constは、構造体のレイアウトに現れない定数フィールドを定義するために使用することができます。例えば、2バイトの符号なし定数 TRANSPORT_MODE (値は ROAD) を定義するには、次のようにします。

```
struct Car
	TRANSPORT_MODE = make_const(TransportMode, ROAD)
```

make_reservedは、レイアウトに現れる予約フィールドを定義するために使用することができ、デフォルト値を指定します。例えば、1バイトの符号なし定数 wheel_count を値4で定義する場合です。

```
inline struct Car
	wheel_count = make_reserved(uint8, 4)
```

sizeof は、他のフィールドのサイズで満たされるフィールドを定義するために使用することができます。例えば、2 バイトの unsigned car_size を定義すると、car フィールドのサイズが代入されます。

```
inline struct SingleCarGarage
	car_size = sizeof(uint16, car)

	car = Car
```

わからん、誰か解説してほしいです。

## conditionals

Fields can be made conditional on the values of other fields. The approximates the union concept present in some languages. CATS supports the following operators:

1. equals: conditional field is included if reference field value matches condition value exactly
2. not equals: conditional field is included if reference field value does NOT match condition value
3. has: conditional field is included if reference field value has all of the condition flags set
4. not has: conditional field is included if reference field value does NOT have all of the condition flags set

For example, to indicate buoyancy is only present when transport_mode is equal to SEA:

## conditionals（条件）

フィールドは、他のフィールドの値を条件とすることができる。これは、いくつかの言語に存在する和集合の概念に近いものです。CATSは以下の演算子をサポートしています。

1. equal: 参照フィールドの値が条件値と完全に一致する場合、条件フィールドが含まれます。
2. not equals: 参照フィールドの値が条件値と一致しない場合、条件フィールドが含まれる。
3. has：参照フィールドの値にすべての条件フラグが設定されている場合、条件フィールドが含まれる。
4. not has: 参照フィールドの値がすべての条件フラグを持たない場合、条件フィールドが含まれる。

例えば、transport_mode が SEA のときだけ浮力があることを示すには、以下のようにする。

```
abstract struct Vehicle
	transport_mode = TransportMode

	buoyancy = uint32 if SEA equals transport_mode
```

いや、ifはどっから出てきてん。

## arrays
Dynamically sized arrays are supported. Each array has an associated size that can be a constant, a property reference or a special __FILL__ keyword.

For example, to define a Garage with a vehicles field that is composed of vehicles_count Vehicle structures:

```
struct Garage
	vehicles_count = uint32

	vehicles = array(Vehicle, vehicles_count)
```

The special __FILL__ keyword indicates that the array extends until the end of the structure. In order for __FILL__ to be used, the containing structure must contain a field containing its size in bytes, specified via the @size attribute. For example, to indicate the vehicles array composed of Vehicle structures extends to the end of the Garage structure with byte size garage_byte_size:

```
@size(garage_byte_size)
struct Garage
	garage_byte_size = uint32

	vehicles = array(Vehicle, __FILL__)
```

⚠️ Array element types (Vehicle used in the examples) must either be fixed sized structures or variable sized structures with a @size attribute attached.


## 配列
動的なサイズの配列がサポートされています。各配列は、定数、プロパティ参照、または特別な __FILL__ キーワードで指定されたサイズを持ちます。

例えば、Vehiclesフィールドを持つGarageを定義する場合、Vehicles_count Vehicle構造体から構成されます。

```
struct Garage
	vehicles_count = uint32

	vehicles = array(Vehicle, vehicles_count)
```

特別なキーワードである __FILL__ は、配列が構造体の終わりまで拡張されることを示します。FILL__ を使用するためには、構造体の中に @size 属性で指定したサイズをバイト単位で含むフィールドが含まれていなければなりません。例えば、Vehicle構造体からなるVehicles配列が、Garage構造体のバイトサイズgarage_byte_sizeの末尾まで拡張されていることを示すには、以下のようにします。

```
@size(garage_byte_size)
struct Garage
	garage_byte_size = uint32

	vehicles = array(Vehicle, __FILL__)
```

⚠️配列要素の型（例ではVehicle）は、固定サイズの構造体か、@size属性が付いた可変サイズの構造体でなければなりません。


## inlines
A structure can be inlined within another using the inline keyword. For example, to inline Vehicle at the start of a Car structure with two fields:

```
struct Car
	inline Vehicle

	max_clearance = Height
	has_left_steering_wheel = uint8
```

Inlines are expanded where they appear, so the order of Car fields will be: {weight, max_clearance, has_left_steering_wheel}. The expansion will be equivalent to:

```
struct Car
	weight = uint32

	max_clearance = Height
	has_left_steering_wheel = uint8
```

In addition, a named inline will inline a referenced structure's fields with a prefix. For example, in the following SizePrefixedString is inlined in Vehicle as friendly_name:

```
inline struct SizePrefixedString
	size = uint32
	__value__ = array(int8, size)

abstract struct Vehicle
	weight = uint32

	friendly_name = inline SizePrefixedString

	year = uint16
```

The expansion will be equivalent to:

```
abstract struct Vehicle
	weight = uint32

	friendly_name_size = uint32
	friendly_name = array(int8, friendly_name_size)

	year = uint16
```

Within the inlined structure, __value__ is a special field name that will be replaced with the name (friendly_name) used in the containing structure (Vehicle). All other fields in the inlined structure will have names prepended with the name (friendly_name) used in the containing structure (Vehicle) and an underscore. So, __value__ becomes friendly_name and size becomes friendly_name + _ + size or friendly_name_size.


## インライン
構造体は、inlineキーワードを使って、他の構造体の中にインライン化することができます。例えば、2つのフィールドを持つCar構造体の先頭にVehicleをインライン化することができます。

```
struct Car
	inline Vehicle

	max_clearance = Height
	has_left_steering_wheel = uint8
```

インラインは出現したところから展開されるので、Carフィールドの順序は次のようになります。したがって、Carフィールドの順序は次のようになります： {weight, max_clearance, has_left_steering_wheel}. と同じように展開されます。

```
struct Car
	weight = uint32

	max_clearance = Height
	has_left_steering_wheel = uint8
```

さらに、名前付きインラインは、参照される構造体のフィールドに接頭辞を付けてインライン化します。例えば、以下の例では、SizePrefixedStringはVehicleにfriendly_nameとしてインライン化されています

```
inline struct SizePrefixedString
	size = uint32
	__value__ = array(int8, size)

abstract struct Vehicle
	weight = uint32

	friendly_name = inline SizePrefixedString

	year = uint16
```

と同等の拡張を行います。

```
abstract struct Vehicle
	weight = uint32

	friendly_name_size = uint32
	friendly_name = array(int8, friendly_name_size)

	year = uint16
```

インライン構造内の __value__ は、特殊なフィールド名であり、包含構造（Vehicle）で使用されている名前（friendly_name）に置き換えられる。インライン化された構造体内の他の全てのフィールドの名前は、包含構造体（Vehicle）で使用されている名前（friendly_name）の前にアンダースコアが付きます。つまり、__value__ は friendly_name となり、size は friendly_name + _ + size または friendly_name_size となる。


## attributes
Hints can be attached to structures using attributes.

Structures support the following attributes:

is_aligned: indicates that all structure fields are positioned on aligned boundaries.
is_size_implicit: indicates that the structure could be referenced in a sizeof(x) statement and must support a size calculation.
size(x): indicates that the x field contains the full size of the (variable sized) structure.
initializes(x, Y): indicates that the x field should be initialized with the Y constant.
discriminator(x [, y]+): indicates that the (x, ...y) properties should be used as the discriminator when generating a factory (only has meaning for abstract structures).
For example, to link the transport_mode field with the TRANSPORT_MODE constant:

```
@initializes(transport_mode, TRANSPORT_MODE)
abstract struct Vehicle
	transport_mode = TransportMode

struct Car
	TRANSPORT_MODE = make_const(TransportMode, ROAD)

	inline Vehicle
```

Notice that TRANSPORT_MODE can be defined in any derived structure.

Array fields support the following attributes:

is_byte_constrained: indicates the size value should be interpreted as a byte value instead of an element count.
alignment(x, [[not] pad_last]): indicates that elements should be padded so that they start on x-aligned boundaries.
sort_key(x): indicates that elements within the array should be sorted by the x property.
When alignment is specified, by default, the final element is padded to end on an x-aligned boundary. This can be made explicit by including the pad_last qualifier. This can be disabled by including the not pad_last qualifier, which will not pad the last element to an x-aligned boundary.

For example, to sort vehicles by weight:

```
struct Garage
	@sort_key(weight)
	vehicles = array(Vehicle, __FILL__)
```

## 属性
構造体には、属性を用いてヒントを付けることができます。

構造体には以下の属性がある。

is_aligned: すべての構造体フィールドがアライメントされた境界上に配置されていることを示す。
is_size_implicit: 構造体が sizeof(x) 文で参照される可能性があり、サイズの計算をサポートしなければならないことを示す。
size(x): x フィールドが（可変長の）構造体のフルサイズを含むことを示す。
initializes(x, Y): xフィールドがY定数で初期化されるべきであることを示す。
discriminator(x [, y ]+): (x, ...y)プロパティがファクトリー生成時の識別器として使用されるべきであることを示す（抽象構造体に対してのみ意味を持つ）。
例えば、transport_modeフィールドをTRANSPORT_MODE定数とリンクさせる。

```
@initializes(transport_mode, TRANSPORT_MODE)
abstract struct Vehicle
	transport_mode = TransportMode

struct Car
	TRANSPORT_MODE = make_const(TransportMode, ROAD)

	inline Vehicle
```

TRANSPORT_MODEは、任意の派生構造で定義できることに注意。

配列のフィールドは以下の属性をサポートする。

is_byte_constrained: サイズ値が要素数ではなく、バイト値として解釈されるべきであることを示す。
alignment(x, [[not] pad_last]): 要素が x-アラインの境界から始まるようにパディングされるべきであることを示す。
sort_key(x): 配列内の要素を x プロパティでソートすることを示します。
alignment が指定された場合、デフォルトでは、最後の要素は x-アラインの境界で終了するようにパディングされます。これを明示的に行うには pad_last 修飾子を指定します。これを無効にするには、not pad_last 修飾子を指定することで、最後の要素をx-alignedの境界でパッドしないようにすることができる。

例えば、車両を重量でソートする場合。

```
struct Garage
	@sort_key(weight)
	vehicles = array(Vehicle, __FILL__)
```

## comments

Any line starting with a # is treated as a comment. If a comment line is directly above a declaration or sub-declaration it is treated as documentation and preserved by the parser. Otherwise, it is discarded.

For example, in the following "comment 1" is discarded while "comment 2 comment 3" is extracted as the documentation for Height.

```
# comment 1

# comment 2
# comment 3
using Height = uint64
```

##コメント

で始まるすべての行はコメントとして扱われます。コメント行が宣言や副宣言の直上にある場合、それは文書として扱われ、パーサーによって保存されます。そうでない場合は、破棄されます。

例えば、次の例では、「コメント1」は破棄され、「コメント2 コメント3」はHeightのドキュメントとして抽出されます。

```
# comment 1

# comment 2
# comment 3
using Height = uint64
```

## ジャガーさんと話した限りでは

catbufferはsymbolのスキーマ言語です

スキーマ言語とは要するに
symbolの構造体をプログラミング言語のように書き下ろした。

という感じです。
なのでスキーマ言語を理解することがsymbolの構造を全て把握することができます
（日本語によくあるような同じ言語の意味でも異なるような現象が発生しないそうです。）

橋と箸と端みたいな感じで同じ発音だが、意味の違いがないようにすることができるそうです。

スキーマの定義についてはコアデベロッパーたちが設定したものだそうなので、わからない言語は一つずつ確認していく必要があります。
またスキーマの理解についても確認しておく必要があります。

ですので、今後どうするか？という話になりますが、

・スキーマに書かれている用語
・各種スキーマの構成について

この２点を一度解釈して、コアデベロッパーにその都度確認していく必要があります。