Protocol Buffer
Protocol Buffer est un moyen simple, rapide et efficace de réaliser des échanges de messages entre applications ou microservices. Chaque fichier .proto, composant le message, débute par la déclaration de syntaxe que le compilateur doit respecter. Aujourd'hui c'est la version 3. Ensuite chaque message est une structure composée de plusieurs lignes de 3 champs :
syntax = "proto3";
message MyMessage {
int32 id = 1;
string first_name = 2;
bool validated = 3;
}
Il existe un certain nombre de déclarations pour les types scalaires : int32, int64, uint32, uint64,
double, float, sint32, sint64, fixed32, fixed64, sfixed32, sfixed64. Ils désignent des valeurs flottantes,
en simple ou double précision, des entiers en 32 ou 64 bits, des entiers signés ou non signés.
Généralement, pour des raisons de simplicité, nous serons amenés à utiliser essentiellement les types
int32, float (32 bits) ou double (64 bits).
bool pour un booléen qui sera true ou false.
string pour une chaine de caractère qui sera toujours encodée en UTF-8 ou ASCII-7 bits. Il n'y
a pas d'autres représentations de chaines.
bytes pour représenter une séquence d'octets.
Par défaut une variable dispose d'une valeur zéro qui sera :
Les énumérations sont déclarées par le mot clé enum. Un enum doit commencer par le tag 0. Une énumération va créer un type à l'intérieur d'un message. Il ne restera qu'à définir une variable de ce type dans le message.
syntax = "proto3";
message Personne {
int32 age = 1;
enum EyeColor {
UNKNOWN_COLOR = 0; // valeur par défaut
GREEN_EYE = 1;
BLUE_EYE = 2;
}
// Utilisation du type énuméré comme type dans le message
EyeColor couleur_des_yeux = 2;
}
Ce qui est important dans la définition du message en ProtoBuf est le Tag (sous-entendu le Tag Number). C'est un nombre qui peut aller de 1 (pas zéro) jusqu'à 2^29 - 1. L'intervalle 19000 à 19999 ne doit pas être utilisé car réservé à Google...
Les Tags numérotés de 1 à 15 utilient un octet et sont à réserver aux champs les plus fréquemment peuplés par votre application. Les tags numérotés de 16 à 2047 occupent quant à eux 2 octets.
Il suffit de marquer la définition du tag par le mot-clé repeated. Cela va enregistrer le fait que les éléments qui suivent peuvent être répétés et du même type.
syntax = "proto3";
message Personne {
string name = 1;
int32 age = 2;
bool is_adult = 3;
repeated phone_number = 4;
}
Un fichier peut contenir autant de messages que l'on souhaite, soit de messages déclarés les uns à la suite des autres, soit inclus les uns dans les autres. Le fait de déclarer un message induit la génération d'un type qui est exploitable automatiquement.
syntax = "proto3";
message PremierMessage {
int age = 1;
string name = 2;
// Le type Date provient du message déclaré à la suite de ce PremierMessage
Date Anniversaire = 3;
// Déclaration d'un message à l'intérieur d'un autre message
message Address {
string address1 = 1;
string address2 = 2;
string zipcode = 3;
string country = 4;
}
// Utilisation du type Address provenant du message déclaré encapsulé dans PremierMessage
repeated Address addresses = 4; // Le numéro du tag est celui qui vient en séquence dans le message PremierMessage
}
message Date {
int year = 1;
int month = 2;
int day = 3;
}
Il suffit de marquer la définition du tag par le mot-clé repeated. Cela va enregistrer
le fait que les éléments qui suivent peuvent être répétés et du même type.
syntax = "proto3";
message Personne {
string name = 1;
int32 age = 2;
bool is_adult = 3;
repeated phone_number = 4;
}
Si des messages ont dékà été écrits dans d'autres fichiers, il suffit de les importer par la commande
import "chemin-complet-du-fichier-à-importer";
en prenant garde à craiment appeler l'import
avec le chemin pleinement qualifé qui mène à votre fichier .proto que vous souhaitez importer.
Si vous souhaitez structurer votre code, vous pouvez utiliser la notion de packages pour les fichiers
que vous importez. Cela permettra d'éviter par exemple que plusieurs imports portent le même nom et
génère des conflits.
Il suffit de noter package nom-du-package;
dans le message pouvant être importé et de l'utiliser
avec son nom de package depuis le message qui en a besoin nom-du-package.type-de-message variable
.
syntax = "proto3";
import "mon-message.proto";
message TestMessage {
int32 age = 1;
mon-message.Date anniversaire;
}
Et dans le fichier importé mon-message.proto nous déclarons la notion de package :
syntax = "proto3";
package mon-message;
message Date {
int32 jour = 1;
int32 mois = 2;
int32 annee = 3;
}
Site des développeurs ProtoBuf chez Google : https://developers.google.com/protocol-buffers