Skip to content

Commit

Permalink
Add docs on bit_field and field tags
Browse files Browse the repository at this point in the history
  • Loading branch information
gingerBill committed Apr 10, 2024
1 parent 7b3db89 commit 1ffcd3a
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 7 deletions.
55 changes: 49 additions & 6 deletions content/docs/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -1861,14 +1861,34 @@ Foo :: struct {
}
```

#### Struct tags
Structs can be tagged with different memory layout and alignment requirements:
#### Struct directives
Structs can be annotated with different memory layout and alignment requirements:
```odin
struct #align 4 {...} // align to 4 bytes
struct #align(4) {...} // align to 4 bytes
struct #packed {...} // remove padding between fields
struct #raw_union {...} // all fields share the same offset (0). This is the same as C's union
```

#### Struct field tags
Struct fields can be tagged with a string literal to attach meta-infomration which can be used with runtime-type information. Usually this is used to provide transactional information info on how a struct field is encoded to or decoded from another format, but you can store whatever you want within the string literal
```odin
User :: struct {
flag: bool, // untagged field
age: int "custom whatever information",
name: string `json:"username" xml:"user-name" fmt:"q"`, // `core:reflect` layout
}
```

Within Odin's core library, the standard convention is to store a `key` that denotes the package and then a subsequence `"value"`. For example, `json` keys are processed and used by `core:encoding/json` package, `fmt` keys are processed by `core:fmt`.

If multiple information is to be passed in the `"value"`, usually it is specified by separating it with a common (`,`), e.g.

```odin
name: string `json:"username,omitempty",
```

n.b. Field tags also exist for [`bit_field` record types](#bit-fields).

### Unions
A `union` in Odin is a discriminated union, also known as a tagged union or sum type. The zero value of a union is `nil`.
```odin
Expand Down Expand Up @@ -1951,7 +1971,7 @@ shared_nil_example :: proc() {
Unions also have the `#align` tag, like structures:

```odin
union #align 4 {...} // align to 4 bytes
union #align(4) {...} // align to 4 bytes
```

### Maps
Expand Down Expand Up @@ -2052,6 +2072,29 @@ a = proc() -> int { return 100 }
fmt.println(a()) // 100
```

### Bit Fields

A `bit_field` is a record type in Odin that is akin to a bit-packed struct. **Note:** `bit_field` is __not__ equivalent to `bit_set` as it has different semantics and use cases. A `bit_field`'s field can be access using a do:
```odin
Foo :: bit_field u16 { // backing type must be an integer or array of integers
x: i32 | 3, // signed integers will be signed extended on use
y: u16 | 2 + 3, // general expressions
z: My_Enum | foo.SOME_CONSTANT, // ability to define the bit-width elsewhere
w: bool | foo.SOME_CONSTANT > 10 ? 2 : 1,
}
v := Foo{}
v.x = 4 // truncates the value to fit into 3 bits
fmt.println(v.x) // accessing will convert `v.x` to an `i32` and do an appropriate sign extension
```

A `bit_field` is different from a `struct` in that you must specify the backing type. This backing type must be an integer or a fixed-length array of integers. This is useful if there needs to be a specific alignment or access pattern for the record.

```odin
Foo :: bit_field u32 {...}
Foo :: bit_field [4]u8 {...}
```

#### Calling conventions
Odin supports the following calling conventions:

Expand Down Expand Up @@ -3586,10 +3629,10 @@ struct #raw_union {u: u32, i: i32, f: f32}
#### `#align`
This tag can be applied to a `struct` or `union`. When `#align` is passed an integer `N` (as in `#align N`), it specifies that the `struct` will be aligned to `N` bytes. The `struct`'s fields will remain in source-order.
```odin
Foo :: struct #align 4 {
Foo :: struct #align(4) {
b: bool,
}
Bar :: union #align 4 {
Bar :: union #align(4) {
i32,
u8,
}
Expand Down
2 changes: 1 addition & 1 deletion themes/odin/layouts/partials/head.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
return {
aliases: ["odin", "odinlang", "odin-lang"],
keywords: {
keyword: "auto_cast bit_set break case cast context continue defer distinct do dynamic else enum fallthrough for foreign if import in map matrix not_in or_else or_return package proc return struct switch transmute type_of typeid union using when where",
keyword: "auto_cast bit_field bit_set break case cast context continue defer distinct do dynamic else enum fallthrough for foreign if import in map matrix not_in or_else or_return package proc return struct switch transmute type_of typeid union using when where",
literal: "true false nil",
built_in: "abs align_of cap clamp complex conj expand_to_tuple imag jmag kmag len max min offset_of quaternion real size_of soa_unzip soa_zip swizzle type_info_of type_of typeid_of"
},
Expand Down

0 comments on commit 1ffcd3a

Please sign in to comment.