aboutsummaryrefslogtreecommitdiff
path: root/docs/source
diff options
context:
space:
mode:
authormustiikhalil <mustii@mmk.one>2020-01-09 23:12:10 +0300
committerWouter van Oortmerssen <aardappel@gmail.com>2020-01-09 12:12:10 -0800
commit04d80f255d1c2fa7a466e8465a119c0eaef26d59 (patch)
tree3bbb6d92e6d006a733ba04c638d6eecce228ad9a /docs/source
parent55686100aa6f8b4867e8de62768d8fc0ecc5a541 (diff)
downloadflatbuffers-04d80f255d1c2fa7a466e8465a119c0eaef26d59.tar.gz
[Swift] Swift implementation 🎉🎉 (#5603)
* Implemented the swift version of Flatbuffers Implemented serailzing, reading, and mutating data from object monster Fixes mis-aligned pointer issue Fixes issue when shared strings are removed from table Adds swift enum, structs code gen Fixed namespace issues + started implementing the table gen Added Mutate function to the code generator Generated linux test cases Fixed an issue with bools, and structs readers in table writer Swift docker image added Updated the test cases, and removed a method parameters in swift Fixed createVector api when called with scalars Fixed issues with scalar arrays, and fixed the code gen namespaces, added sample_binary.swift Cleaned up project Added enum vectors, and their readers Refactored code Added swift into the support document Added documentation in docs, and fixed a small issue with Data() not being returned correctly Fixes Lowercase issue, and prevents generating lookups for deprecated keys * Made all the required funcs to have const + removed unneeded code + fix lowercase func * Removed transform from lowercased and moved it to function * Fixes an issue with iOS allocation from read * Refactored cpp code to be more readable * casts position into int for position * Fix enums issue, moves scalar writer code to use memcpy * Removed c_str from struct function * Fixed script to generate new objects when ran on travis ci: fix * Handles deallocating space allocated for structs * Updated the test cases to adhere to the fileprivate lookup, no mutation for unions, and updated the names of the vector functions
Diffstat (limited to 'docs/source')
-rw-r--r--docs/source/Compiler.md2
-rw-r--r--docs/source/FlatBuffers.md4
-rw-r--r--docs/source/Support.md36
-rw-r--r--docs/source/SwiftUsage.md93
-rw-r--r--docs/source/Tutorial.md187
5 files changed, 303 insertions, 19 deletions
diff --git a/docs/source/Compiler.md b/docs/source/Compiler.md
index c5768bd2..9061051b 100644
--- a/docs/source/Compiler.md
+++ b/docs/source/Compiler.md
@@ -47,6 +47,8 @@ For any schema input files, one or more generators can be specified:
- `--rust`, `-r` : Generate Rust code.
+- `--swift`: Generate Swift code.
+
For any data input files:
- `--binary`, `-b` : If data is contained in this file, generate a
diff --git a/docs/source/FlatBuffers.md b/docs/source/FlatBuffers.md
index a9d637ac..45ffbf22 100644
--- a/docs/source/FlatBuffers.md
+++ b/docs/source/FlatBuffers.md
@@ -4,7 +4,7 @@ FlatBuffers {#flatbuffers_index}
# Overview {#flatbuffers_overview}
[FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform
-serialization library for C++, C#, C, Go, Java, Kotlin, JavaScript, Lobster, Lua, TypeScript, PHP, Python, and Rust.
+serialization library for C++, C#, C, Go, Java, Kotlin, JavaScript, Lobster, Lua, TypeScript, PHP, Python, Rust and Swift.
It was originally created at Google for game development and other
performance-critical applications.
@@ -148,6 +148,8 @@ sections provide a more in-depth usage guide.
own programs.
- How to [use the generated Rust code](@ref flatbuffers_guide_use_rust) in your
own programs.
+- How to [use the generated Swift code](@ref flatbuffers_guide_use_swift) in your
+ own programs.
- [Support matrix](@ref flatbuffers_support) for platforms/languages/features.
- Some [benchmarks](@ref flatbuffers_benchmarks) showing the advantage of
using FlatBuffers.
diff --git a/docs/source/Support.md b/docs/source/Support.md
index c8ac7f7e..1e435a66 100644
--- a/docs/source/Support.md
+++ b/docs/source/Support.md
@@ -18,23 +18,23 @@ In general:
NOTE: this table is a start, it needs to be extended.
-Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Dart | Lobster | Rust
------------------------------- | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ------- | ------- | ----
-Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | Yes | Yes | Yes
-JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | Yes | No
-Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No | No
-Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No | No
-Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No | No
-Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes
-Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No | Yes
-Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | Great | Superb
-Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | Yes | Yes | Yes
-Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes
-Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes
-Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ?
-Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ?
-Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | No | ?
-Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | evanw/ev* | kr* | mik* | ch* | dnfield | aard* | rw
+Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Dart | Lobster | Rust | Swift
+------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ------- | ------- | ------- | ------
+Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | Yes | Yes | Yes | Yes
+JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | Yes | No | No
+Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No | No | No
+Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No | No | No
+Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No | No | No
+Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes | Yes
+Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No | Yes | No
+Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | Great | Superb | ?
+Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | Yes | Yes | Yes | No
+Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes | Yes
+Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes | Yes
+Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ? | No
+Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ? | Yes
+Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | No | ? | No
+Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | evanw/ev* | kr* | mik* | ch* | dnfield | aard* | rw | mi*/mz*
* aard = aardappel (previously: gwvo)
* ev = evolutional
@@ -42,5 +42,7 @@ Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | ev
* mik = mikkelfj
* ch = chobie
* kr = krojew
+ * mi = mustiikhalil
+ * mz = mzaks
<br>
diff --git a/docs/source/SwiftUsage.md b/docs/source/SwiftUsage.md
new file mode 100644
index 00000000..fb8b1fd9
--- /dev/null
+++ b/docs/source/SwiftUsage.md
@@ -0,0 +1,93 @@
+Use in Swift {#flatbuffers_guide_use_swift}
+=========
+
+## Before you get started
+
+Before diving into the FlatBuffers usage in Swift, it should be noted that
+the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
+to general FlatBuffers usage in all of the supported languages (including Swift).
+This page is designed to cover the nuances of FlatBuffers usage, specific to
+Swift.
+
+You should also have read the [Building](@ref flatbuffers_guide_building)
+documentation to build `flatc` and should be familiar with
+[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
+[Writing a schema](@ref flatbuffers_guide_writing_schema).
+
+## FlatBuffers Swift library code location
+
+The code for the FlatBuffers Swift library can be found at
+`flatbuffers/swift`. You can browse the library code on the [FlatBuffers
+GitHub page](https://github.com/google/flatbuffers/tree/master/swift).
+
+## Testing the FlatBuffers Swift library
+
+The code to test the Swift library can be found at `flatbuffers/Flatbuffers.Test.Swift`.
+The test code itself is located in [Flatbuffers.Test.Swift](https://github.com/google/
+flatbuffers/blob/master/tests/FlatBuffers.Test.Swift).
+
+To run the tests, use the [SwiftTest.sh](https://github.com/google/flatbuffers/
+blob/master/tests/FlatBuffers.Test.Swift/SwiftTest.sh) shell script.
+
+*Note: The shell script requires [Swift](https://swift.org) to
+be installed.*
+
+## Using the FlatBuffers Swift library
+
+*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
+example of how to use FlatBuffers in Swift.*
+
+FlatBuffers supports reading and writing binary FlatBuffers in Swift.
+
+To use FlatBuffers in your own code, first generate Swift structs from your
+schema with the `--swift` option to `flatc`. Then include FlatBuffers using `SPM` in
+by adding the path to `FlatBuffers/swift` into it. The generated code should also be
+added to xcode or the path of the package you will be using. Note: sometimes xcode cant
+and wont see the generated files, so it's better that you copy them to xcode.
+
+For example, here is how you would read a FlatBuffer binary file in Swift: First,
+include the library and copy thegenerated code. Then read a FlatBuffer binary file or
+a data object from the server, which you can pass into the `GetRootAsMonster` function.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
+ import FlatBuffers
+
+ typealias Monster1 = MyGame.Sample.Monster
+ typealias Vec3 = MyGame.Sample.Vec3
+
+ let path = FileManager.default.currentDirectoryPath
+ let url = URL(fileURLWithPath: path, isDirectory: true).appendingPathComponent("monsterdata_test").appendingPathExtension("mon")
+ guard let data = try? Data(contentsOf: url) else { return }
+
+ let monster = Monster.getRootAsMonster(bb: ByteBuffer(data: data))
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Now you can access values like this:
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
+ let hp = monster.hp
+ let pos = monster.pos
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+In some cases it's necessary to modify values in an existing FlatBuffer in place (without creating a copy). For this reason, scalar fields of a Flatbuffer table or struct can be mutated.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
+ let monster = Monster.getRootAsMonster(bb: ByteBuffer(data: data))
+
+ if !monster.mutate(hp: 10) {
+ fatalError("couldn't mutate")
+ }
+ // mutate a struct field
+ let vec = monster.pos.mutate(z: 4)
+
+ // This mutation will fail because the mana field is not available in
+ // the buffer. It should be set when creating the buffer.
+ if !monster.mutate(mana: 20) {
+ fatalError("couldn't mutate")
+ }
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The term `mutate` is used instead of `set` to indicate that this is a special use case. All mutate functions return a boolean value which is false if the field we're trying to mutate is not available in the buffer.
+
+<br>
diff --git a/docs/source/Tutorial.md b/docs/source/Tutorial.md
index e8d8519b..00408b52 100644
--- a/docs/source/Tutorial.md
+++ b/docs/source/Tutorial.md
@@ -35,6 +35,7 @@ Please select your desired language for our quest:
<input type="radio" name="language" value="lua">Lua</input>
<input type="radio" name="language" value="lobster">Lobster</input>
<input type="radio" name="language" value="rust">Rust</input>
+ <input type="radio" name="language" value="swift">Swift</input>
</form>
\endhtmlonly
@@ -152,6 +153,9 @@ For your chosen language, please cross-reference with:
<div class="language-rust">
[sample_binary.rs](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.rs)
</div>
+<div class="language-swift">
+[sample_binary.swift](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.swift)
+</div>
## Writing the Monsters' FlatBuffer Schema
@@ -363,6 +367,12 @@ Please be aware of the difference between `flatc` and `flatcc` tools.
./../flatc --rust monster.fbs
~~~
</div>
+<div class="language-swift">
+~~~{.sh}
+ cd flatbuffers/samples
+ ./../flatc --swift monster.fbs
+~~~
+</div>
For a more complete guide to using the `flatc` compiler, please read the
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
@@ -523,6 +533,21 @@ The first step is to import/include the library, generated files, etc.
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ /**
+ // make sure that monster_generated.swift is included in your project
+ */
+ import Flatbuffers
+
+ // typealiases for convenience
+ typealias Monster = MyGame1.Sample.Monster
+ typealias Weapon = MyGame1.Sample.Weapon
+ typealias Color = MyGame1.Sample.Color
+ typealias Vec3 = MyGame1.Sample.Vec3
+~~~
+</div>
+
Now we are ready to start building some buffers. In order to start, we need
to create an instance of the `FlatBufferBuilder`, which will contain the buffer
as it grows. You can pass an initial size of the buffer (here 1024 bytes),
@@ -627,6 +652,12 @@ which will grow automatically if needed:
let mut builder = flatbuffers::FlatBufferBuilder::new_with_capacity(1024);
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ // create a `FlatBufferBuilder`, which will be used to serialize objects
+ let builder = FlatBufferBuilder(initialSize: 1024)
+~~~
+</div>
After creating the `builder`, we can start serializing our data. Before we make
our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
@@ -878,6 +909,25 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ let weapon1Name = builder.create(string: "Sword")
+ let weapon2Name = builder.create(string: "Axe")
+
+ // start creating the weapon by calling startWeapon
+ let weapon1Start = Weapon.startWeapon(builder)
+ Weapon.add(name: weapon1Name, builder)
+ Weapon.add(damage: 3, builder)
+ // end the object by passing the start point for the weapon 1
+ let sword = Weapon.endWeapon(builder, start: weapon1Start)
+
+ let weapon2Start = Weapon.startWeapon(builder)
+ Weapon.add(name: weapon2Name, builder)
+ Weapon.add(damage: 5, builder)
+ let axe = Weapon.endWeapon(builder, start: weapon2Start)
+~~~
+</div>
+
Now let's create our monster, the `orc`. For this `orc`, lets make him
`red` with rage, positioned at `(1.0, 2.0, 3.0)`, and give him
a large pool of hit points with `300`. We can give him a vector of weapons
@@ -1068,6 +1118,16 @@ traversal. This is generally easy to do on any tree structures.
let inventory = builder.create_vector(&[0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ // Name of the Monster.
+ let name = builder.create(string: "Orc")
+
+ // create inventory
+ let inventory: [Byte] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ let inventoryOffset = builder.createVector(inventory)
+~~~
+</div>
We serialized two built-in data types (`string` and `vector`) and captured
their return values. These values are offsets into the serialized data,
@@ -1212,6 +1272,13 @@ offsets.
let weapons = builder.create_vector(&[sword, axe]);
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ // Create a FlatBuffer `vector` that contains offsets to the sword and axe
+ // we created above.
+ let weaponsOffset = builder.createVector(ofOffsets: [sword, axe])
+~~~
+</div>
<br>
Note there's additional convenience overloads of `CreateVector`, allowing you
@@ -1348,6 +1415,15 @@ for the `path` field above:
// let path = builder.create_vector(&[&x, &y]);
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ //
+ let points = builder.createVector(structs: [MyGame.Sample.createVec3(x: 1, y: 2, z: 3),
+ MyGame.Sample.createVec3(x: 4, y: 5, z: 6)],
+ type: Vec3.self)
+~~~
+</div>
+
We have now serialized the non-scalar components of the orc, so we
can serialize the monster itself:
@@ -1621,6 +1697,20 @@ can serialize the monster itself:
});
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ let start = Monster.startMonster(builder)
+ Monster.add(pos: pos, builder)
+ Monster.add(hp: 300, builder)
+ Monster.add(name: name, builder)
+ Monster.add(inventory: inventoryOffset, builder)
+ Monster.add(color: .red, builder)
+ Monster.add(weapons: weaponsOffset, builder)
+ Monster.add(equippedType: .weapon, builder)
+ Monster.add(equipped: axe, builder)
+ var orc = Monster.endMonster(builder, start: start)
+~~~
+</div>
Note how we create `Vec3` struct in-line in the table. Unlike tables, structs
are simple combinations of scalars that are always stored inline, just like
@@ -1789,6 +1879,13 @@ Here is a repetition these lines, to help highlight them more clearly:
monster_builder.add_equipped(axe.as_union_value()); // Union data
~~~
</div>
+<div class="language-swift">
+ ~~~{.swift}
+ Monster.add(equippedType: .weapon, builder) // Type of union
+ Monster.add(equipped: axe, builder) // Union data
+ ~~~
+</div>
+
After you have created your buffer, you will have the offset to the root of the
data in the `orc` variable, so you can finish the buffer by calling the
@@ -1884,6 +1981,12 @@ appropriate `finish` method.
builder.finish(orc, None);
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ // Call `finish(offset:)` to instruct the builder that this monster is complete.
+ builder.finish(offset: orc)
+~~~
+</div>
The buffer is now ready to be stored somewhere, sent over the network, be
compressed, or whatever you'd like to do with it. You can access the buffer
@@ -2012,6 +2115,15 @@ like so:
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ // This must be called after `finish()`.
+ // `sizedByteArray` returns the finished buf of type [UInt8].
+ let buf = builder.sizedByteArray
+ // or you can use to get an object of type Data
+ let bufData = ByteBuffer(data: builder.data)
+~~~
+</div>
Now you can write the bytes to a file, send them over the network..
**Make sure your file mode (or transfer protocol) is set to BINARY, not text.**
@@ -2312,6 +2424,16 @@ myGame.Monster monster = new myGame.Monster(data);
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ // create a ByteBuffer(:) from an [UInt8] or Data()
+ let buf = // Get your data
+
+ // Get an accessor to the root object inside the buffer.
+ let monster = Monster.getRootAsMonster(bb: ByteBuffer(bytes: buf))
+~~~
+</div>
+
If you look in the generated files from the schema compiler, you will see it generated
accessors for all non-`deprecated` fields. For example:
@@ -2419,6 +2541,14 @@ accessors for all non-`deprecated` fields. For example:
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ let hp = monster.hp
+ let mana = monster.mana
+ let name = monster.name // returns an optional string
+~~~
+</div>
+
These should hold `300`, `150`, and `"Orc"` respectively.
*Note: The default value `150` wasn't stored in `mana`, but we are still able to retrieve it.*
@@ -2544,6 +2674,15 @@ To access sub-objects, in the case of our `pos`, which is a `Vec3`:
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ let pos = monster.pos
+ let x = pos.x
+ let y = pos.y
+ let z = pos.z
+~~~
+</div>
+
`x`, `y`, and `z` will contain `1.0`, `2.0`, and `3.0`, respectively.
*Note: Had we not set `pos` during serialization, it would be a `NULL`-value.*
@@ -2644,6 +2783,20 @@ FlatBuffers `vector`.
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ // Get a the count of objects in the vector
+ let count = monster.inventoryCount
+
+ // get item at index 4
+ let object = monster.inventory(at: 4)
+
+ // or you can fetch the entire array
+ let inv = monster.inventory
+ // inv[4] should equal object
+~~~
+</div>
+
For `vector`s of `table`s, you can access the elements like any other vector,
except your need to handle the result as a FlatBuffer `table`:
@@ -2756,6 +2909,16 @@ except your need to handle the result as a FlatBuffer `table`:
let second_weapon_damage = wep2.damage();
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ // Get the count of weapon objects
+ let wepsCount = monster.weaponsCount
+
+ let weapon2 = monster.weapons(at: 1)
+ let weaponName = weapon2.name
+ let weaponDmg = weapon2.damage
+~~~
+</div>
Last, we can access our `Equipped` FlatBuffer `union`. Just like when we created
the `union`, we need to get both parts of the `union`: the type and the data.
@@ -2943,6 +3106,17 @@ We can access the type to dynamically cast the data as needed (since the
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ // Get and check if the monster has an equipped item
+ if monster.equippedType == .weapon {
+ let _weapon = monster.equipped(type: Weapon.self)
+ let name = _weapon.name // should return "Axe"
+ let dmg = _weapon.damage // should return 5
+ }
+~~~
+</div>
+
## Mutating FlatBuffers
As you saw above, typically once you have created a FlatBuffer, it is read-only
@@ -3046,6 +3220,15 @@ mutators like so:
~~~
</div>
+<div class="language-swift">
+~~~{.swift}
+ let monster = Monster.getRootAsMonster(bb: ByteBuffer(bytes: buf))
+ monster.mutate(hp: 10) // mutates a value in a table
+ monster.pos.mutate(z: 4) // mutates a value in a struct
+ monster.mutate(inventory: 6, at index: 0) // mutates a value in an Scalar array
+~~~
+</div>
+
We use the somewhat verbose term `mutate` instead of `set` to indicate that this
is a special use case, not to be confused with the default way of constructing
FlatBuffer data.
@@ -3215,5 +3398,7 @@ For your chosen language, see:
<div class="language-rust">
[Use in Rust](@ref flatbuffers_guide_use_rust)
</div>
-
+<div class="language-swift">
+[Use in Swift](@ref flatbuffers_guide_use_swift)
+</div>
<br>