I have a nodejs application that uses google flat buffers.
the fbs file for the drinks schema:
namespace MyAlcoholist;
table Drink {
drink_type_name: string;
drink_company_name: string;
drink_brand_name: string;
drink_flavor_type_name : string;
liquid_color_type_name : string;
liquid_color_is_transparent : bool;
alcohol_vol : float;
calories_for_100g : uint;
global_image_id: uint;
drink_flavor_id: uint;
}
table Drinks { drinks:[Drink]; }
root_type Drinks;
compiled it with flatc -s drinks.fbs
, it generated the js file drinks_generated.js. so far so good.
I use the following code in my nodejs server to prepare and create the flat buffer out of an array:
flatBuffersUtil.js
var flatbuffers = require('../js/flatbuffers').flatbuffers;
var builder = new flatbuffers.Builder();
var drinks = require('../fbs/drinks_generated').MyAlcoholist; // Generated by `flatc`.
function drinkArrayToBuffer(drinkArray) {
var drinksVectArray = [];
drinkArray.forEach(function (element, index, array) {
var drinkObj = element;
var drinkBrandName = builder.createString(drinkObj.drink_brand_name);
var drinkCompanyName = builder.createString(drinkObj.drink_company_name);
var drinkflavorTypeName = builder.createString(drinkObj.drink_flavor_type_name);
var drinkTypeName = builder.createString(drinkObj.drink_type_name);
var liquidColorTypeName = builder.createString(drinkObj.liquid_color_type_name);
drinks.Drink.startDrink(builder);
drinks.Drink.addAlcoholVol(builder, drinkObj.alcohol_vol);
drinks.Drink.addCaloriesFor100g(builder, drinkObj.calories_for_100g);
drinks.Drink.addDrinkBrandName(builder, drinkBrandName);
drinks.Drink.addDrinkCompanyName(builder, drinkCompanyName);
drinks.Drink.addDrinkFlavorId(builder, drinkObj.drink_flavor_id);
drinks.Drink.addDrinkFlavorTypeName(builder, drinkflavorTypeName);
drinks.Drink.addDrinkTypeName(builder, drinkTypeName);
drinks.Drink.addGlobalImageId(builder, drinkObj.global_image_id);
drinks.Drink.addLiquidColorIsTransparent(builder, drinkObj.is_transparent);
drinks.Drink.addLiquidColorTypeName(builder, liquidColorTypeName);
var drink = drinks.Drink.endDrink(builder);
drinksVectArray.push(drink);
})
var drinksVect = drinks.Drinks.createDrinksVector(builder, drinksVectArray);
builder.finish(drinksVect);
var buf = builder.dataBuffer();
var drinksArray = drinks.Drinks.getRootAsDrinks(buf);
return buf;
}
module.exports.drinkArrayToBuffer = drinkArrayToBuffer;
usage of flatBuffersUtil.js:
...
var data = flatBuffersUtil.drinkArrayToBuffer(result);
res.send(data);
the client is done with angularjs 1.5.0 when I receive the buffer I try to create an object out of it using the following code:
in main index file:
<script type="text/javascript" src="js/flatbuffers.js"></script>
<script type="text/javascript" src="js/fbs/drinks_generated.js"></script>
then in angular controller:
$http({
data: data,
method: 'POST',
url: 'https://myalcoholist.com:8888/drink/get_list/all_drinks',
}).then(function successCallback(response) {
var buffer = response.data;
var drinks = MyAlcoholist.Drinks.getRootAsDrinks(buffer);
deferred.resolve(drinks);
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
the problem is that the function MyAlcoholist.Drinks.getRootAsDrinks(buffer);
fails with the following error:
TypeError: bb.position is not a function
at Function.MyAlcoholist.Drinks.getRootAsDrinks (drinks_generated.js:256)
at successCallback (admin-drinks-controller.js:22)
at angular.js:15552
at m.$eval (angular.js:16820)
at m.$digest (angular.js:16636)
at m.$apply (angular.js:16928)
at g (angular.js:11266)
at t (angular.js:11464)
at XMLHttpRequest.u.onload (angular.js:11405)
now.. the function's code in the generated drinks_generated.js file is the following:
MyAlcoholist.Drinks.getRootAsDrinks = function(bb, obj) {
return (obj || new MyAlcoholist.Drinks).__init(bb.readInt32(bb.position()) + bb.position(), bb);
};
so bb is supposed to a bytebuffer type with the function position(), but what I receive is an Object of bytes. I guess I need to typecast it first or somehow... but this is just a guess.
any ideas?
update
ok first i revised my drinksArrayToBuffer function to the following code:
function drinkArrayToBuffer(drinkArray) {
var drinksVectArray = [];
drinkArray.forEach(function (element, index, array) {
var drinkObj = element;
var drinkBrandName = builder.createString(drinkObj.drink_brand_name);
var drinkCompanyName = builder.createString(drinkObj.drink_company_name);
var drinkflavorTypeName = builder.createString(drinkObj.drink_flavor_type_name);
var drinkTypeName = builder.createString(drinkObj.drink_type_name);
var liquidColorTypeName = builder.createString(drinkObj.liquid_color_type_name);
drinks.Drink.startDrink(builder);
drinks.Drink.addAlcoholVol(builder, drinkObj.alcohol_vol);
drinks.Drink.addCaloriesFor100g(builder, drinkObj.calories_for_100g);
drinks.Drink.addDrinkBrandName(builder, drinkBrandName);
drinks.Drink.addDrinkCompanyName(builder, drinkCompanyName);
drinks.Drink.addDrinkFlavorId(builder, drinkObj.drink_flavor_id);
drinks.Drink.addDrinkFlavorTypeName(builder, drinkflavorTypeName);
drinks.Drink.addDrinkTypeName(builder, drinkTypeName);
drinks.Drink.addGlobalImageId(builder, drinkObj.global_image_id);
drinks.Drink.addLiquidColorIsTransparent(builder, drinkObj.is_transparent);
drinks.Drink.addLiquidColorTypeName(builder, liquidColorTypeName);
var drink = drinks.Drink.endDrink(builder);
drinksVectArray.push(drink);
})
var drinksVect = drinks.Drinks.createDrinksVector(builder, drinksVectArray);
drinks.Drinks.startDrinks(builder);
drinks.Drinks.addDrinks(builder, drinksVect);
var endDrinksOffset = drinks.Drinks.endDrinks(builder);
drinks.Drinks.finishDrinksBuffer(builder, endDrinksOffset);
var buf = builder.dataBuffer();
return buf;
}
now in the server side i am able to deserialise the buffer and use the data properly. the problem is with deserialising on the client side.
after i'm sending the buffer, the client side receives the following object:
Object
bytes_: Object
position_: 7148
__proto__: Object
now.. I created the following function to convert the buffer to json object on the client side:
function drinksByteArrayToArray(buffer) {
var res = [];
var byteBuffer =new flatbuffers.ByteBuffer(buffer);
var drinks = MyAlcoholist.Drinks.getRootAsDrinks(byteBuffer);
var drinksLength = drinks.drinksLength();
for (var i=0;i<drinksLength;i++) {
var drink = drinks.drinks(i);
var drinkObj = {
drink_flavor_id: drink.drinkFlavorId(),
drink_type_name: drink.drinkTypeName(),
drink_company_name: drink.drinkCompanyName(),
drink_brand_name: drink.drinkBrandName(),
drink_flavor_type_name: drink.drinkFlavorTypeName(),
liquid_color_type_name: drink.liquidColorTypeName(),
is_transparent: drink.liquidColorIsTransparent(),
alcohol_vol: drink.alcoholVol(),
calories_for_100g: drink.caloriesFor100g(),
global_image_id: drink.globalImageId
}
res.push(drinkObj);
}
return res;
}
when I excute this function, the length of drinks is zero. so the buffer seems to be empty.
now I think that the problem is with the following code:
var byteBuffer =new flatbuffers.ByteBuffer(buffer);
I think i need convert the data to bytebuffer in some other way.
I understood that I need to give flatbuffers.ByteBuffer
an array of bytes, so I tried doing the following thing:
var byteBuffer =new flatbuffers.ByteBuffer(buffer.bytes_);
but the results are the same.
any ideas?