1*890232f2SAndroid Build Coastguard Worker/* 2*890232f2SAndroid Build Coastguard Worker * Copyright 2015 Google Inc. All rights reserved. 3*890232f2SAndroid Build Coastguard Worker * 4*890232f2SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*890232f2SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*890232f2SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*890232f2SAndroid Build Coastguard Worker * 8*890232f2SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*890232f2SAndroid Build Coastguard Worker * 10*890232f2SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*890232f2SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*890232f2SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*890232f2SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*890232f2SAndroid Build Coastguard Worker * limitations under the License. 15*890232f2SAndroid Build Coastguard Worker */ 16*890232f2SAndroid Build Coastguard Worker 17*890232f2SAndroid Build Coastguard Worker// To run, use the `go_sample.sh` script. 18*890232f2SAndroid Build Coastguard Worker 19*890232f2SAndroid Build Coastguard Workerpackage main 20*890232f2SAndroid Build Coastguard Worker 21*890232f2SAndroid Build Coastguard Workerimport ( 22*890232f2SAndroid Build Coastguard Worker sample "MyGame/Sample" 23*890232f2SAndroid Build Coastguard Worker "fmt" 24*890232f2SAndroid Build Coastguard Worker flatbuffers "github.com/google/flatbuffers/go" 25*890232f2SAndroid Build Coastguard Worker "strconv" 26*890232f2SAndroid Build Coastguard Worker) 27*890232f2SAndroid Build Coastguard Worker 28*890232f2SAndroid Build Coastguard Worker// Example how to use Flatbuffers to create and read binary buffers. 29*890232f2SAndroid Build Coastguard Workerfunc main() { 30*890232f2SAndroid Build Coastguard Worker builder := flatbuffers.NewBuilder(0) 31*890232f2SAndroid Build Coastguard Worker 32*890232f2SAndroid Build Coastguard Worker // Create some weapons for our Monster ("Sword" and "Axe"). 33*890232f2SAndroid Build Coastguard Worker weaponOne := builder.CreateString("Sword") 34*890232f2SAndroid Build Coastguard Worker weaponTwo := builder.CreateString("Axe") 35*890232f2SAndroid Build Coastguard Worker 36*890232f2SAndroid Build Coastguard Worker sample.WeaponStart(builder) 37*890232f2SAndroid Build Coastguard Worker sample.WeaponAddName(builder, weaponOne) 38*890232f2SAndroid Build Coastguard Worker sample.WeaponAddDamage(builder, 3) 39*890232f2SAndroid Build Coastguard Worker sword := sample.WeaponEnd(builder) 40*890232f2SAndroid Build Coastguard Worker 41*890232f2SAndroid Build Coastguard Worker sample.WeaponStart(builder) 42*890232f2SAndroid Build Coastguard Worker sample.WeaponAddName(builder, weaponTwo) 43*890232f2SAndroid Build Coastguard Worker sample.WeaponAddDamage(builder, 5) 44*890232f2SAndroid Build Coastguard Worker axe := sample.WeaponEnd(builder) 45*890232f2SAndroid Build Coastguard Worker 46*890232f2SAndroid Build Coastguard Worker // Serialize the FlatBuffer data. 47*890232f2SAndroid Build Coastguard Worker name := builder.CreateString("Orc") 48*890232f2SAndroid Build Coastguard Worker 49*890232f2SAndroid Build Coastguard Worker sample.MonsterStartInventoryVector(builder, 10) 50*890232f2SAndroid Build Coastguard Worker // Note: Since we prepend the bytes, this loop iterates in reverse. 51*890232f2SAndroid Build Coastguard Worker for i := 9; i >= 0; i-- { 52*890232f2SAndroid Build Coastguard Worker builder.PrependByte(byte(i)) 53*890232f2SAndroid Build Coastguard Worker } 54*890232f2SAndroid Build Coastguard Worker inv := builder.EndVector(10) 55*890232f2SAndroid Build Coastguard Worker 56*890232f2SAndroid Build Coastguard Worker sample.MonsterStartWeaponsVector(builder, 2) 57*890232f2SAndroid Build Coastguard Worker // Note: Since we prepend the weapons, prepend in reverse order. 58*890232f2SAndroid Build Coastguard Worker builder.PrependUOffsetT(axe) 59*890232f2SAndroid Build Coastguard Worker builder.PrependUOffsetT(sword) 60*890232f2SAndroid Build Coastguard Worker weapons := builder.EndVector(2) 61*890232f2SAndroid Build Coastguard Worker 62*890232f2SAndroid Build Coastguard Worker pos := sample.CreateVec3(builder, 1.0, 2.0, 3.0) 63*890232f2SAndroid Build Coastguard Worker 64*890232f2SAndroid Build Coastguard Worker sample.MonsterStart(builder) 65*890232f2SAndroid Build Coastguard Worker sample.MonsterAddPos(builder, pos) 66*890232f2SAndroid Build Coastguard Worker sample.MonsterAddHp(builder, 300) 67*890232f2SAndroid Build Coastguard Worker sample.MonsterAddName(builder, name) 68*890232f2SAndroid Build Coastguard Worker sample.MonsterAddInventory(builder, inv) 69*890232f2SAndroid Build Coastguard Worker sample.MonsterAddColor(builder, sample.ColorRed) 70*890232f2SAndroid Build Coastguard Worker sample.MonsterAddWeapons(builder, weapons) 71*890232f2SAndroid Build Coastguard Worker sample.MonsterAddEquippedType(builder, sample.EquipmentWeapon) 72*890232f2SAndroid Build Coastguard Worker sample.MonsterAddEquipped(builder, axe) 73*890232f2SAndroid Build Coastguard Worker orc := sample.MonsterEnd(builder) 74*890232f2SAndroid Build Coastguard Worker 75*890232f2SAndroid Build Coastguard Worker builder.Finish(orc) 76*890232f2SAndroid Build Coastguard Worker 77*890232f2SAndroid Build Coastguard Worker // We now have a FlatBuffer that we could store on disk or send over a network. 78*890232f2SAndroid Build Coastguard Worker 79*890232f2SAndroid Build Coastguard Worker // ...Saving to file or sending over a network code goes here... 80*890232f2SAndroid Build Coastguard Worker 81*890232f2SAndroid Build Coastguard Worker // Instead, we are going to access this buffer right away (as if we just received it). 82*890232f2SAndroid Build Coastguard Worker 83*890232f2SAndroid Build Coastguard Worker buf := builder.FinishedBytes() 84*890232f2SAndroid Build Coastguard Worker 85*890232f2SAndroid Build Coastguard Worker // Note: We use `0` for the offset here, since we got the data using the 86*890232f2SAndroid Build Coastguard Worker // `builder.FinishedBytes()` method. This simulates the data you would store/receive in your 87*890232f2SAndroid Build Coastguard Worker // FlatBuffer. If you wanted to read from the `builder.Bytes` directly, you would need to 88*890232f2SAndroid Build Coastguard Worker // pass in the offset of `builder.Head()`, as the builder actually constructs the buffer 89*890232f2SAndroid Build Coastguard Worker // backwards. 90*890232f2SAndroid Build Coastguard Worker monster := sample.GetRootAsMonster(buf, 0) 91*890232f2SAndroid Build Coastguard Worker 92*890232f2SAndroid Build Coastguard Worker // Note: We did not set the `mana` field explicitly, so we get the 93*890232f2SAndroid Build Coastguard Worker // default value. 94*890232f2SAndroid Build Coastguard Worker assert(monster.Mana() == 150, "`monster.Mana()`", strconv.Itoa(int(monster.Mana())), "150") 95*890232f2SAndroid Build Coastguard Worker assert(monster.Hp() == 300, "`monster.Hp()`", strconv.Itoa(int(monster.Hp())), "300") 96*890232f2SAndroid Build Coastguard Worker assert(string(monster.Name()) == "Orc", "`string(monster.Name())`", string(monster.Name()), 97*890232f2SAndroid Build Coastguard Worker "\"Orc\"") 98*890232f2SAndroid Build Coastguard Worker assert(monster.Color() == sample.ColorRed, "`monster.Color()`", 99*890232f2SAndroid Build Coastguard Worker strconv.Itoa(int(monster.Color())), strconv.Itoa(int(sample.ColorRed))) 100*890232f2SAndroid Build Coastguard Worker 101*890232f2SAndroid Build Coastguard Worker // Note: Whenever you access a new object, like in `Pos()`, a new temporary accessor object 102*890232f2SAndroid Build Coastguard Worker // gets created. If your code is very performance sensitive, you can pass in a pointer to an 103*890232f2SAndroid Build Coastguard Worker // existing `Vec3` instead of `nil`. This allows you to reuse it across many calls to reduce 104*890232f2SAndroid Build Coastguard Worker // the amount of object allocation/garbage collection. 105*890232f2SAndroid Build Coastguard Worker assert(monster.Pos(nil).X() == 1.0, "`monster.Pos(nil).X()`", 106*890232f2SAndroid Build Coastguard Worker strconv.FormatFloat(float64(monster.Pos(nil).X()), 'f', 1, 32), "1.0") 107*890232f2SAndroid Build Coastguard Worker assert(monster.Pos(nil).Y() == 2.0, "`monster.Pos(nil).Y()`", 108*890232f2SAndroid Build Coastguard Worker strconv.FormatFloat(float64(monster.Pos(nil).Y()), 'f', 1, 32), "2.0") 109*890232f2SAndroid Build Coastguard Worker assert(monster.Pos(nil).Z() == 3.0, "`monster.Pos(nil).Z()`", 110*890232f2SAndroid Build Coastguard Worker strconv.FormatFloat(float64(monster.Pos(nil).Z()), 'f', 1, 32), "3.0") 111*890232f2SAndroid Build Coastguard Worker 112*890232f2SAndroid Build Coastguard Worker // For vectors, like `Inventory`, they have a method suffixed with 'Length' that can be used 113*890232f2SAndroid Build Coastguard Worker // to query the length of the vector. You can index the vector by passing an index value 114*890232f2SAndroid Build Coastguard Worker // into the accessor. 115*890232f2SAndroid Build Coastguard Worker for i := 0; i < monster.InventoryLength(); i++ { 116*890232f2SAndroid Build Coastguard Worker assert(monster.Inventory(i) == byte(i), "`monster.Inventory(i)`", 117*890232f2SAndroid Build Coastguard Worker strconv.Itoa(int(monster.Inventory(i))), strconv.Itoa(int(byte(i)))) 118*890232f2SAndroid Build Coastguard Worker } 119*890232f2SAndroid Build Coastguard Worker 120*890232f2SAndroid Build Coastguard Worker expectedWeaponNames := []string{"Sword", "Axe"} 121*890232f2SAndroid Build Coastguard Worker expectedWeaponDamages := []int{3, 5} 122*890232f2SAndroid Build Coastguard Worker weapon := new(sample.Weapon) // We need a `sample.Weapon` to pass into `monster.Weapons()` 123*890232f2SAndroid Build Coastguard Worker // to capture the output of that function. 124*890232f2SAndroid Build Coastguard Worker for i := 0; i < monster.WeaponsLength(); i++ { 125*890232f2SAndroid Build Coastguard Worker if monster.Weapons(weapon, i) { 126*890232f2SAndroid Build Coastguard Worker assert(string(weapon.Name()) == expectedWeaponNames[i], "`weapon.Name()`", 127*890232f2SAndroid Build Coastguard Worker string(weapon.Name()), expectedWeaponNames[i]) 128*890232f2SAndroid Build Coastguard Worker assert(int(weapon.Damage()) == expectedWeaponDamages[i], 129*890232f2SAndroid Build Coastguard Worker "`weapon.Damage()`", strconv.Itoa(int(weapon.Damage())), 130*890232f2SAndroid Build Coastguard Worker strconv.Itoa(expectedWeaponDamages[i])) 131*890232f2SAndroid Build Coastguard Worker } 132*890232f2SAndroid Build Coastguard Worker } 133*890232f2SAndroid Build Coastguard Worker 134*890232f2SAndroid Build Coastguard Worker // For FlatBuffer `union`s, you can get the type of the union, as well as the union 135*890232f2SAndroid Build Coastguard Worker // data itself. 136*890232f2SAndroid Build Coastguard Worker assert(monster.EquippedType() == sample.EquipmentWeapon, "`monster.EquippedType()`", 137*890232f2SAndroid Build Coastguard Worker strconv.Itoa(int(monster.EquippedType())), strconv.Itoa(int(sample.EquipmentWeapon))) 138*890232f2SAndroid Build Coastguard Worker 139*890232f2SAndroid Build Coastguard Worker unionTable := new(flatbuffers.Table) 140*890232f2SAndroid Build Coastguard Worker if monster.Equipped(unionTable) { 141*890232f2SAndroid Build Coastguard Worker // An example of how you can appropriately convert the table depending on the 142*890232f2SAndroid Build Coastguard Worker // FlatBuffer `union` type. You could add `else if` and `else` clauses to handle 143*890232f2SAndroid Build Coastguard Worker // other FlatBuffer `union` types for this field. (Similarly, this could be 144*890232f2SAndroid Build Coastguard Worker // done in a switch statement.) 145*890232f2SAndroid Build Coastguard Worker if monster.EquippedType() == sample.EquipmentWeapon { 146*890232f2SAndroid Build Coastguard Worker unionWeapon := new(sample.Weapon) 147*890232f2SAndroid Build Coastguard Worker unionWeapon.Init(unionTable.Bytes, unionTable.Pos) 148*890232f2SAndroid Build Coastguard Worker 149*890232f2SAndroid Build Coastguard Worker assert(string(unionWeapon.Name()) == "Axe", "`unionWeapon.Name()`", 150*890232f2SAndroid Build Coastguard Worker string(unionWeapon.Name()), "Axe") 151*890232f2SAndroid Build Coastguard Worker assert(int(unionWeapon.Damage()) == 5, "`unionWeapon.Damage()`", 152*890232f2SAndroid Build Coastguard Worker strconv.Itoa(int(unionWeapon.Damage())), strconv.Itoa(5)) 153*890232f2SAndroid Build Coastguard Worker } 154*890232f2SAndroid Build Coastguard Worker } 155*890232f2SAndroid Build Coastguard Worker 156*890232f2SAndroid Build Coastguard Worker fmt.Printf("The FlatBuffer was successfully created and verified!\n") 157*890232f2SAndroid Build Coastguard Worker} 158*890232f2SAndroid Build Coastguard Worker 159*890232f2SAndroid Build Coastguard Worker// A helper function to print out if an assertion failed. 160*890232f2SAndroid Build Coastguard Workerfunc assert(assertPassed bool, codeExecuted string, actualValue string, expectedValue string) { 161*890232f2SAndroid Build Coastguard Worker if assertPassed == false { 162*890232f2SAndroid Build Coastguard Worker panic("Assert failed! " + codeExecuted + " (" + actualValue + 163*890232f2SAndroid Build Coastguard Worker ") was not equal to " + expectedValue + ".") 164*890232f2SAndroid Build Coastguard Worker } 165*890232f2SAndroid Build Coastguard Worker} 166