Dictionary in protocol buffers - serialization

Is there any way to serialize a dictionary using protocol buffers, or I'll have to use Thrift if I need that?

For future answer seekers, ProtoBuf now supports Maps natively:
message MapMessage
{
map<string, string> MyMap = 1;
}

Protobuf specification now supports dictionaries (maps) natively.
Original answer
People typically write down the dictionary as a list of key-value pairs, and then rebuild the dictionary on the other end.
message Pair {
string key = 1;
string value = 2;
}
message Dictionary {
repeated Pair pairs = 1;
}

You can check the ProtoText package.
Assume you want to serialize a dict person_dict to a pre-defined PersonBuf protobuf object defined in personbuf_pb2 module.
In this case, to use ProtoText,
import ProtoText
from personbuf_pb2 import PersonBuf
obj = PersonBuf()
obj.update(person_dict)

I firstly comment the #Flassari 's answer as it is really convenient.
However, in my case, I needed map<Type, repeated AnyModel> where :
enum Type {
Undefined = 0;
Square = 1;
Circle = 2;
}
message AnyModel {
string Name = 1;
}
Here I just want to return a dictionary that, for each type, contain a list of AnyModel
However, I didn't find a better workaround than the one proposed by #JesperE so I did the following: (as you can't use enum as key in map)
message MyRPCBodyCall {
map<string, AnyModels> Models = 1;
}
enum Type {
Undefined = 0;
Square = 1;
Circle = 2;
}
message AnyModel {
string Name = 1;
}
message AnyModelArray {
repeated AnyModel AnyModels = 1;
}
Here I convert from/to string my enum using my chosen code languages from both server/client side
So both approaches are actually valid answers IMO, depends on your requirements.

Related

Slice() nested for loop values i and j Kotlin

I'm wanting to slice a range which I can do in Javascfript but am struggling in kotlin.
my current code is:
internal class blah {
fun longestPalindrome(s: String): String {
var longestP = ""
for (i in 0..s.length) {
for (j in 1..s.length) {
var subS = s.slice(i, j)
if (subS === subS.split("").reversed().joinToString("") && subS.length > longestP.length) {
longestP = subS
}
}
}
return longestP
}
and the error I get is:
Type mismatch.
Required:
IntRange
Found:
Int
Is there a way around this keeping most of the code I have?
As the error message says, slice wants an IntRange, not two Ints. So, pass it a range:
var subS = s.slice(i..j)
By the way, there are some bugs in your code:
You need to iterate up to the length minus 1 since the range starts at 0. But the easier way is to grab the indices range directly: for (i in s.indices)
I assume j should be i or bigger, not 1 or bigger, or you'll be checking some inverted Strings redundantly. It should look like for (j in i until s.length).
You need to use == instead of ===. The second operator is for referential equality, which will always be false for two computed Strings, even if they are identical.
I know this is probably just practice, but even with the above fixes, this code will fail if the String contains any multi-code-unit code points or any grapheme clusters. The proper way to do this would be by turning the String into a list of grapheme clusters and then performing the algorithm, but this is fairly complicated and should probably rely on some String processing code library.
class Solution {
fun longestPalindrome(s: String): String {
var longestPal = ""
for (i in 0 until s.length) {
for (j in i + 1..s.length) {
val substring = s.substring(i, j)
if (substring == substring.reversed() && substring.length > longestPal.length) {
longestPal = substring
}
}
}
return longestPal
}
}
This code is now functioning but unfortunately is not optimized enough to get through all test cases.

Three different ways to instantiate Arrays in AssemblyScript

I'm writing a smart contract and want to use Arrays to manipulate data, but looking at the AssemblyScript docs, I'm not sure the best way to proceed.
It seems fine to me to just use:
let testData:string[] = []
but when I consulted the assemblyscript docs, there are three recommended ways to create an Array:
// The Array constructor implicitly sets `.length = 10`, leading to an array of
// ten times `null` not matching the value type `string`. So, this will error:
var arr = new Array<string>(10);
// arr.length == 10 -> ERROR
// To account for this, the .create method has been introduced that initializes
// the backing capacity normally but leaves `.length = 0`. So, this will work:
var arr = Array.create<string>(10);
// arr.length == 0 -> OK
// When pushing to the latter array or subsequently inserting elements into it,
// .length will automatically grow just like one would expect, with the backing
// buffer already properly sized (no resize will occur). So, this is fine:
for (let i = 0; i < 10; ++i) arr[i] = "notnull";
// arr.length == 10 -> OK
When would I want to use one type of instantiation over another? Why wouldn't I just always use the version I presented in the beginning?
Nothing wrong with the array literal approach. It is basically equivalent to
let testData = new Array<string>();
However, sometimes you know what the length of the array should be and in such cases, preallocating the memory using Array.create is more efficient.
UPDATE
With this PR Array.create deprecated and should not be used anymore.
OLD ANSWER
let testData:string[] = []
semantically the same as
let testData = new Array<string>()
AssemblyScript doesn't support preallocated sparse arrays (arrays with holes) for reference elements which not explicitly declared as nullable like:
let data = new Array<string>(10);
data[9] = 1; // will be compile error
Instead you could use:
let data = new Array<string | null>(10);
assert(data.length == 10); // ok
assert(data[0] === null); // ok
or Array.create but in this case your length will be zero. Array.create is actually just reserve capacity for backing buffer.
let data = Array.create<string>(10);
assert(data.length == 0); // true
For plain (non-reference) types you could use usual way without care about nullabe or creating array via Array.create:
let data = new Array<i32>(10);
assert(data.length == 10); // ok
assert(data[0] == 0); // ok

Flatbuffers: How to allow multiple types for a single field

I'm writing a communication protocol schema for a list of parameters which can be of multiple values: uint64, float64, string or bool.
How can I set a table field to a union of multiple primitive scalar & non-scalar primitive type?
I've already tried using a union of those types, but I end up with the following error when building:
$ schemas/foobar.fbs:28: 0: error: type referenced but not defined
(check namespace): uint64, originally at: schemas/request.fbs:5
Here's the schema in its current state:
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];
}
The end result I'm looking for is the Request and Result tables to contain a list of parameters, where a parameter contains a name and value, and optionally the units.
Thx in advance!
Post-answer solution:
Here's what I came up with in the end, thx to 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];
}
You currently can't put scalars directly in a union, so you'd have to wrap these in a table or a struct, where struct would likely be the most efficient, e.g.
struct UInt64 { u:uint64 }
union ParameterValue { UInt64, Float64, Bool, string }
This is because a union must be uniformly the same size, so it only allows types to which you can have an offset.
Generally though, FlatBuffers is a strongly typed system, and the schema you are creating here is undoing that by emulating dynamically typed data, since your data is essentially a list of (string, any type) pairs. You may be better off with a system designed for this particular use case, such as FlexBuffers (https://google.github.io/flatbuffers/flexbuffers.html, currently only C++) which explicitly has a map type that is all string -> any type pairs.
Of course, even better is to not store data so generically, but instead make a new schema for each type of request and response you have, and make parameter names into fields, rather than serialized data. This is by far the most efficient, and type safe.

Sage: Iterate over increasing sequences

I have a problem that I am unwilling to believe hasn't been solved before in Sage.
Given a pair of integers (d,n) as input, I'd like to receive a list (or set, or whatever) of all nondecreasing sequences of length d all of whose entries are no greater than n.
Similarly, I'd like another function which returns all strictly increasing sequences of length d whose entries are no greater than n.
For example, for d = 2 n=3, I'd receive the output:
[[1,2], [1,3], [2,3]]
or
[[1,1], [1,2], [1,3], [2,2], [2,3], [3,3]]
depending on whether I'm using increasing or nondecreasing.
Does anyone know of such a function?
Edit Of course, if there is such a method for nonincreasing or decreasing sequences, I can modify that to fit my purposes. Just something to iterate over sequences
I needed this algorithm too and I finally managed to write one today. I will share the code here, but I only started to learn coding last week, so it is not pretty.
Idea Input=(r,d). Step 1) Create a class "ListAndPosition" that has a list L of arrays Integer[r+1]'s, and an integer q between 0 and r. Step 2) Create a method that receives a ListAndPosition (L,q) and screens sequentially the arrays in L checking if the integer at position q is less than the one at position q+1, if so, it adds a new array at the bottom of the list with that entry ++. When done, the Method calls itself again with the new list and q-1 as input.
The code for Step 1)
import java.util.ArrayList;
public class ListAndPosition {
public static Integer r=5;
public final ArrayList<Integer[]> L;
public int q;
public ListAndPosition(ArrayList<Integer[]> L, int q) {
this.L = L;
this.q = q;
}
public ArrayList<Integer[]> getList(){
return L;
}
public int getPosition() {
return q;
}
public void decreasePosition() {
q--;
}
public void showList() {
for(int i=0;i<L.size();i++){
for(int j=0; j<r+1 ; j++){
System.out.print(""+L.get(i)[j]);
}
System.out.println("");
}
}
}
The code for Step 2)
import java.util.ArrayList;
public class NonDecreasingSeqs {
public static Integer r=5;
public static Integer d=3;
public static void main(String[] args) {
//Creating the first array
Integer[] firstArray;
firstArray = new Integer[r+1];
for(int i=0;i<r;i++){
firstArray[i] = 0;
}
firstArray[r] = d;
//Creating the starting listAndDim
ArrayList<Integer[]> L = new ArrayList<Integer[]>();
L.add(firstArray);
ListAndPosition Lq = new ListAndPosition(L,r-1);
System.out.println(""+nonDecSeqs(Lq).size());
}
public static ArrayList<Integer[]> nonDecSeqs(ListAndPosition Lq){
int iterations = r-1-Lq.getPosition();
System.out.println("How many arrays in the list after "+iterations+" iterations? "+Lq.getList().size());
System.out.print("Should we stop the iteration?");
if(0<Lq.getPosition()){
System.out.println(" No, position = "+Lq.getPosition());
for(int i=0;i<Lq.getList().size();i++){
//Showing particular array
System.out.println("Array of L #"+i+":");
for(int j=0;j<r+1;j++){
System.out.print(""+Lq.getList().get(i)[j]);
}
System.out.print("\nCan it be modified at position "+Lq.getPosition()+"?");
if(Lq.getList().get(i)[Lq.getPosition()]<Lq.getList().get(i)[Lq.getPosition()+1]){
System.out.println(" Yes, "+Lq.getList().get(i)[Lq.getPosition()]+"<"+Lq.getList().get(i)[Lq.getPosition()+1]);
{
Integer[] tempArray = new Integer[r+1];
for(int j=0;j<r+1;j++){
if(j==Lq.getPosition()){
tempArray[j] = new Integer(Lq.getList().get(i)[j])+1;
}
else{
tempArray[j] = new Integer(Lq.getList().get(i)[j]);
}
}
Lq.getList().add(tempArray);
}
System.out.println("New list");Lq.showList();
}
else{
System.out.println(" No, "+Lq.getList().get(i)[Lq.getPosition()]+"="+Lq.getList().get(i)[Lq.getPosition()+1]);
}
}
System.out.print("Old position = "+Lq.getPosition());
Lq.decreasePosition();
System.out.println(", new position = "+Lq.getPosition());
nonDecSeqs(Lq);
}
else{
System.out.println(" Yes, position = "+Lq.getPosition());
}
return Lq.getList();
}
}
Remark: I needed my sequences to start at 0 and end at d.
This is probably not a very good answer to your question. But you could, in principle, use Partitions and the max_slope=-1 argument. Messing around with filtering lists of IntegerVectors sounds equally inefficient and depressing for other reasons.
If this has a canonical name, it might be in the list of sage-combinat functionality, and there is even a base class you could perhaps use for integer lists, which is basically what you are asking about. Maybe you could actually get what you want using IntegerListsLex? Hope this proves helpful.
This question can be solved by using the class "UnorderedTuples" described here:
http://doc.sagemath.org/html/en/reference/combinat/sage/combinat/tuple.html
To return all all nondecreasing sequences with entries between 0 and n-1 of length d, you may type:
UnorderedTuples(range(n),d)
This returns the nondecreasing sequence as a list. I needed an immutable object (because the sequences would become keys of a dictionary). So I used the "tuple" method to turn the lists into tuples:
immutables = []
for s in UnorderedTuples(range(n),d):
immutables.append(tuple(s))
return immutables
And I also wrote a method which picks out only the increasing sequences:
def isIncreasing(list):
for i in range(len(list) - 1):
if list[i] >= list[i+1]:
return false
return true
The method that returns only strictly increasing sequences would look like
immutables = []
for s in UnorderedTuples(range(n),d):
if isIncreasing(s):
immutables.append(tuple(s))
return immutables

Building a linked list in yacc with left recursive Grammar

I want to build a linked list of data in yacc.
My Grammar reads like this:
list: item
| list ',' item
;
I have put the appropriate structures in place in the declarations section. But I am not able to figure out a way to get a linked list out of this data. I have to store the recursively obtained data and then redirect it for other purposes.
Basically I am looking for a solution like this one:
https://stackoverflow.com/a/1429820/5134525
But this solution is for right recursion and doesn't work with left.
It depends heavily on how you implement your linked list, but once you have that, it is straight-forward. Something like:
struct list_node {
struct list_node *next;
value_t value;
};
struct list {
struct list_node *head, **tail;
};
struct list *new_list() {
struct list *rv = malloc(sizeof(struct list));
rv->head = 0;
rv->tail = &rv->head;
return rv; }
void push_back(struct list *list, value_t value) {
struct list_node *node = malloc(sizeof(struct list_node));
node->next = 0;
node->value = value;
*list->tail = node;
list->tail = &node->next; }
allows you to write your yacc code as:
list: item { push_back($$ = new_list(), $1); }
| list ',' item { push_back($$ = $1, $3); }
;
of course, you should probably add checks for running out of memory, and exit gracefully in that case.
If you use a left recursive rule, then you need to push the new item at the end of the list rather than the beginning.
If your linked list implementation doesn't support push_back, then push the successive items at the front and reverse the list when its finished.
Very simple.
list
: item
{
$$ = new MyList<SomeType>();
$$.add($1);
}
| list ',' item
{
$1.add($3);
$$ = $1;
}
;
assuming you are using C++, which you didn't state, and assuming you have some MyList<T> class with an add(T) method.