How do you explain building nested table to coworkers?

381 views
Skip to first unread message

Shuhei Tanuma

unread,
Nov 15, 2015, 9:02:40 AM11/15/15
to FlatBuffers

Hi, Sometimes I struggled how to explain building a nested flatbuffers table which contains vector to my coworkers as it is difficult.
Do you guys have any good instructions? I'm looking for good one.


Let assume we were making recipe application.

```
namespace MyRecipe.Sample;

// describe a task: (e.g at first, make the sponge)
table RecipeTask{
  title:string;
  description:string;
}

// describe how to cook food (e.g making the bread)
table Recipe{
  id:int;
  name:string;
  description:string;
  duration:int;
  tasks:[RecipeTask];
}

// root table.includes several recipe which contains how to cook food.
table RecipeResults{
  results:[Recipe];
}

root_type RecipeResults;
```


then how do you build this results to flatbuffer?


```
[
    {
        "id": 1,
        "name": "recipe1",
        "description": "desc",
        "duration": 1,
        "tasks": [
            {
                "title": "hello1",
                "description": "world1"
            },
            {
                "title": "hello2",
                "description": "world2"
            },
            {
                "title": "hello3",
                "description": "world3"
            }
        ]
    },
    {
        "id": 2,
        "name": "recipe2",
        "description": "desc",
        "duration": 1,
        "tasks": [
            {
                "title": "hello4",
                "description": "world4"
            },
            {
                "title": "hello5",
                "description": "world5"
            },
            {
                "title": "hello6",
                "description": "world6"
            }
        ]
    },
    {
        "id": 1,
        "name": "recipe3",
        "description": "desc",
        "duration": 1,
        "tasks": [
            {
                "title": "hello7",
                "description": "world7"
            },
            {
                "title": "hello8",
                "description": "world8"
            },
            {
                "title": "hello9",
                "description": "world9"
            }
        ]
    }
]
```


My current answer is below (PHP example)

I think mixing create API and Start/Add API are really difficult for beginner.  so I recommend to use Create API or define own Create function.
(Actually, I spent several hours to build this kind of tasks as I've mixed StartXXX, CreateString, StartVector APIs. In some cases, it will outputs corrupted flatbuffers with no errors (at least PHP implementation).)


```
<?php

// manual load for testing. please use PSR style autoloader when you use flatbuffers.                                
require join(DIRECTORY_SEPARATOR, array(dirname(dirname(__FILE__)), "php", "Constants.php"));                        
require join(DIRECTORY_SEPARATOR, array(dirname(dirname(__FILE__)), "php", "ByteBuffer.php"));                       
require join(DIRECTORY_SEPARATOR, array(dirname(dirname(__FILE__)), "php", "FlatbufferBuilder.php"));                
require join(DIRECTORY_SEPARATOR, array(dirname(dirname(__FILE__)), "php", "Table.php"));                            
require join(DIRECTORY_SEPARATOR, array(dirname(dirname(__FILE__)), "php", "Struct.php"));                           
foreach (glob(join(DIRECTORY_SEPARATOR, array(dirname(__FILE__), "MyRecipe", "Sample", "*.php"))) as $file) {
     require $file;
}

use MyRecipe\Sample\RecipeResults;
use MyRecipe\Sample\Recipe;
use MyRecipe\Sample\RecipeTask;

$results = json_decode(file_get_contents("results.json"), true /* parse as hash */);


// building buffers
$fbb = new Google\FlatBuffers\FlatbufferBuilder(1);
$recipeOfffsets = array();
foreach ($results as $recipe) {
     $taskOffsets = array();
     foreach ($recipe["tasks"] as $task) {
          $taskOffsets[] = RecipeTask::createRecipeTask($fbb, 
          $fbb->createString($task["title"]), 
          $fbb->createString($task["description"]));
     }
     $recipeOfffsets[] = Recipe::createRecipe($fbb, 
               $recipe["id"],
               $fbb->createString($recipe["name"]),
               $fbb->createString($recipe["description"]),
               $recipe["duration"],
               Recipe::createTasksVector($fbb, $taskOffsets)
          );
}
$fbb->finish(RecipeResults::createRecipeResults($fbb, 
     RecipeResults::createResultsVector($fbb, $recipeOfffsets)));


// make sure results.
$r = RecipeResults::getRootAsRecipeResults(
     Google\FlatBuffers\ByteBuffer::wrap($fbb->sizedByteArray()));

echo "# MyRecipes:" . $r->getResultsLength() . PHP_EOL;
$results = array();
for ($i = 0; $i < $r->getResultsLength(); $i++) {
     $recipe = $r->getResults($i);
     $tmp = array(
          "id" => $recipe->getId(),
          "name" => $recipe->getName(),
          "description" => $recipe->getDescription(),
          "duration" => $recipe->getDuration(),
          "tasks" => array(),
     );
     printf("recipe_id: %d\n", $recipe->getId());
     printf("recipe_name: %s\n", $recipe->getName());
     printf("description: %s\n", $recipe->getDescription());
     for ($x = 0; $x < $recipe->getTasksLength(); $x++) {
          $task = $recipe->getTasks($x);
         printf("  task: %s\n", $task->getTitle());
         printf("  task_description: %s\n", $task->getDescription());
          
          $tmp["tasks"][] = array(
               "title" => $task->getTitle(),
               "description" => $task->getDescription(), 
          );
     }
     $results[] = $tmp;
}

```

Thanks,
Shuhei

Wouter van Oortmerssen

unread,
Nov 25, 2015, 4:36:14 PM11/25/15
to Shuhei Tanuma, FlatBuffers
Yes, the FlatBuffers building API is not the nicest it could possibly be, since it was all designed for maximum speed first. Nicer APIs are possible, but would have to be less efficient.

Your code looks good to me.

The most important thing to explain is that object construction is "depth first post order", i.e. all children strings/vectors/tables have to be created before their parents.


--
You received this message because you are subscribed to the Google Groups "FlatBuffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to flatbuffers...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages