Flatbuffers: как разрешить несколько типов для одного поля - PullRequest
0 голосов
/ 30 января 2019

Я пишу схему протокола связи для списка параметров, которые могут иметь несколько значений: uint64, float64, string или bool.

Как настроить поле таблицы на объединение нескольких примитивовскалярный и нескалярный тип примитива?

Я уже пытался использовать объединение этих типов, но я получаю следующую ошибку при сборке:

$ schemas/foobar.fbs:28: 0: error: type referenced but not defined
  (check namespace): uint64, originally at: schemas/request.fbs:5

Вот схема вего текущее состояние:

namespace Foobar;

enum RequestCode : uint16 { Noop, Get, Set, BulkGet, BulkSet }

union ParameterValue { uint64, float64, bool, string }

table Parameter {
  name:string;
  value:ParameterValue;
  unit:string;
}

table Request {
  code:RequestCode = Noop;
  payload:[Parameter];
}

table Result {
  request:Request;
  success:bool = true;
  payload:[Parameter];
}

Конечный результат, который я ищу, - это таблицы запросов и результатов, содержащие список параметров, где параметр содержит имя и значение, а также, необязательно, единицы измерения.

Спасибо заранее!

Пост-ответное решение: Вот что я в итоге придумал, спасибо Aardappel.

namespace foobar;

enum RequestCode : uint16 { Noop, Get, Set, BulkGet, BulkSet }

union ValueType { UnsignedInteger, SignedInteger, RealNumber, Boolean, Text }

table UnsignedInteger {
  value:uint64 = 0;
}

table SignedInteger {
  value:int64 = 0;
}

table RealNumber {
  value:float64 = 0.0;
}

table Boolean {
  value:bool = false;
}

table Text {
  value:string (required);
}

table Parameter {
  name:string (required);
  valueType:ValueType;
  unit:string;
}

table Request {
  code:RequestCode = Noop;
  payload:[Parameter];
}

table Result {
  request:Request (required);
  success:bool = true;
  payload:[Parameter];
}

1 Ответ

0 голосов
/ 30 января 2019

В настоящее время вы не можете поместить скаляры непосредственно в объединение, поэтому вам нужно будет обернуть их в таблицу или структуру, где структура, вероятно, будет наиболее эффективной, например,

struct UInt64 { u:uint64 }
union ParameterValue { UInt64, Float64, Bool, string }

Этопотому что объединение должно быть одинаково одинакового размера, поэтому оно допускает только те типы, для которых вы можете иметь смещение.

Обычно, хотя FlatBuffers является системой со строгим типом, и создаваемая здесь схема отменяет, чтоэмулируя динамически типизированные данные, поскольку ваши данные - это, по сути, список пар (строка, любой тип).Возможно, вам лучше использовать систему, разработанную для этого конкретного случая использования, такую ​​как FlexBuffers (https://google.github.io/flatbuffers/flexbuffers.html, в настоящее время только C ++), которая явно имеет тип карты со всей строкой -> любые пары типов.

Конечно, еще лучше не хранить данные в общем виде, а вместо этого создавать новую схему для каждого типа запросов и ответов, которые вы имеете, и делать имена параметров в полях, а не в сериализованных данных.Это, безусловно, самый эффективный и безопасный тип.

...