Используя protbuf3, как я могу выразить тип "Строка карты (возможно, CustomType)"?
Я пытаюсь поделиться большим словарем / картой между клиентом и службой. Мне нужно иметь возможность устанавливать значения в двух направлениях и удалять значения из словаря / карты, не пропуская всю карту каждый раз.
Я знаю, что могу создать карту, используя:
map<string, CustomType> cells = 3;
( Документы для карт protobuf3)
Я вижу предложение использовать один из них здесь: https://github.com/google/protobuf/issues/1606
Однако синтаксис, предложенный в этом отчете об ошибке, не имеет смысла для меня:
message Test1 {
oneof a_oneof {
int32 a = 1;
}
}
Как бы я проверил это? Как бы я храню None?
Я хотел бы попытаться создать что-то вроде:
message None{}
message MaybeCustomType{
oneof maybe{
CustomType just = 1;
None none = 2;
}
}
Но я совсем не уверен, что это элегантное и правильное решение.
Я также решил изменить свою схему полностью и делать.
map<string, CustomType> cells = 1;
repeated string deleted_cells = 2;
Однако мне не нравится это решение, потому что оно создает неопределенный случай. Что произойдет, если ячейка с именем "foo" появится и на карте ячеек, и на карте удаленных ячеек? Кроме того, он абстрагирует данные от вычислений. Я хотел бы иметь возможность передать ячейку в функцию, которая изменяет и потенциально решает удалить ячейку, и поэтому мне кажется естественным, что информация об удалении ячейки хранится рядом с самой ячейкой.
1 ответ
Ваш языковой тег упоминает haskell, но я не уверен, какую реализацию библиотеки вы используете для обеспечения поддержки proto3, поэтому я постараюсь дать общий ответ.
обзор
Тема, на которую вы указали, предлагает использовать oneof
с одним полем, так как можно представить null
(действительно отсутствие поля). К счастью, вам не нужно создавать None
введите для этой цели, поскольку он встроен в сгенерированные исходные файлы для конкретного языка. Взгляните на руководство по языку для одного из...
Вы можете проверить, какое значение в oneof установлено (если есть), используя специальный метод case() или метод WhichOneof(), в зависимости от выбранного вами языка.
Часть "если есть" - это магия, которую вы ищете. Сгенерированный код C++ для однозначного определения предоставит специальный oneof_name_case()
метод, который скажет вам, если одно из полей было установлено...
OneofNameCase oneof_name_case() const: возвращает перечисление, указывающее, какое поле установлено. Возвращает ONEOF_NAME_NOT_SET, если ни один из них не установлен.
Аналогичный метод генерируется для кода Java: getOneofNameCase()
возвращается ONEOFNAME_NOT_SET
если ни одно из полей не установлено.
пример
Начиная с тестового сообщения...
message Test1 {
oneof single_field_oneof {
int32 some_int = 1;
}
}
Если бы вы использовали C++, вы могли бы использовать код, подобный следующему, для обработки поля oneof...
int main(int argc, char* argv[]) {
Test1 test;
// <Populate message somehow>
if (test.single_field_case() == Test1::kSomeInt) {
std::cout << "Field is set, value is " << test.some_int() << std::endl;
} else {
assert(test.single_field_case() == Test1::SINGLE_FIELD_NOT_SET);
std::cout << "Field is not set" << std::endl;
}
}
Во всяком случае, как я уже говорил, я не знаком с конкретными привязками языка Proto3 для Haskell, но oneof
Функция должна иметь аналогичные функции в библиотеке, которую вы используете.