Используя 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 Функция должна иметь аналогичные функции в библиотеке, которую вы используете.

Другие вопросы по тегам