I am trying to share a large dictionary/map between a client and a service. I need to be able to bidirectionally set values, and delete values from the dictionary/map without passing the entire map back and forth each time.
I know I can create a map using:
map<string, CustomType> cells = 3;
I see a sugestion to use oneof here: https://github.com/google/protobuf/issues/1606
However, the syntax suggested in that bug report doesn't make sense to me:
message Test1 {
oneof a_oneof {
int32 a = 1;
}
}
How would I test for that? How would I store None?
I would try to create something like:
message None{}
message MaybeCustomType{
oneof maybe{
CustomType just = 1;
None none = 2;
}
}
But I'm not at all convinced that this is the elegant and correct solution.
I also considered changing my schema entirely and doing.
map<string, CustomType> cells = 1;
repeated string deleted_cells = 2;
However I don't like that solution because it creates an undefined case. What happens if a cell named "foo" appears in both the "cells" map and the "deleted_cells" map? Furthermore, it abstracts the data away from the computation. I'd like to be able to pass a cell to a function which modifies and potentially decides to delete the cell, and so it seems natural to me that information about cell deletion be stored near the cell itself.
Your language tag mentions haskell but I'm not sure which library implementation you're using to provide proto3 support, so I'll try to provide a generic answer.
Overview
The thread you pointed to suggests using
oneof
with a single field since it's possible to represent anull
(really the absence of the field). Fortunately you don't need to create aNone
type for this purpose since it is built into the language-specific generated source files. Take a look at the Language Guide for oneof...The "if any" part is the magic you're looking for. The generated C++ code for a oneof definition will provide a special
oneof_name_case()
method that will tell you if one of the fields have been set...A similar method is generated for Java code:
getOneofNameCase()
returnsONEOFNAME_NOT_SET
if none of the oneof fields are set.Example
Starting from a test message...
If you were using C++ you could use code similar to the following to handle the oneof field...
Anyway, as I mentioned I'm not familiar with the specific proto3 language bindings for Haskell, but the
oneof
feature should have similar functionality in the library that you're using.