2012-02-06 11 views
21

Sto cercando di determinare la relazione tra i valori di default e has_foo() dichiarati in varie interfacce di programmazione. In particolare, sto cercando di determinare in quali circostanze (se ce ne sono) è possibile "distinguere" tra un campo impostato esplicitamente sul valore predefinito e un valore non impostato.in che modo i metodi has_field() si riferiscono ai valori predefiniti in protobuf?

  1. Se ho impostato in modo esplicito un campo (ad esempio "Bar.foo") al suo valore di default (ad esempio, zero), allora è il bar :: has_foo() rendimento garantito vero per quella struttura di dati? (Questo sembra essere vero per il codice generato in C++, da un'ispezione rapida, ma ciò non significa che sia garantito.) Se questo è vero, è possibile distinguere tra un valore predefinito impostato in modo esplicito e un set prima della serializzazione.

  2. Se imposto esplicitamente un campo al suo valore predefinito (ad es. Zero), quindi serializzo quell'oggetto e lo invii sul filo, il valore verrà inviato o meno? Se non lo è, allora chiaramente qualsiasi codice che riceve questo oggetto non può distinguere tra un valore predefinito impostato in modo esplicito e un valore non impostato. Ad esempio, non sarà possibile distinguere questi due casi dopo la serializzazione - Bar :: has_foo() restituirà false in entrambi i casi.

Se non è possibile capire la differenza, ciò che è la tecnica consigliata per la codifica di un campo protobuf se voglio codificare un valore opzionale "Null"? Un paio di opzioni mi vengono in mente, ma non sembrano grandi: (a) aggiungi un campo booleano in più che registra se il campo è impostato o no, oppure (b) usa un campo "ripetuto" anche se semanticamente voglio un campo opzionale - in questo modo posso dire la differenza tra nessun valore (lista lunghezza-zero) o un valore impostato (lista lunghezza-uno).

risposta

26

Quanto segue si applica sintassi 'proto2', non 'proto3':

La nozione di un campo essendo impostare o non è una caratteristica nucleo di Protobuf. Se si imposta un campo su un valore (qualsiasi valore), il metodo corrisponde al valore restituito true, altrimenti si verifica un errore nell'API.

Se non si imposta un campo e quindi si serializza il messaggio, non viene inviato alcun valore per quel campo. Il lato ricevente analizzerà il messaggio, scoprirà quali valori sono inclusi e imposta i corrispondenti valori "ha_xxx".

Esattamente come questo è implementato nel formato wire è documentato qui: http://code.google.com/apis/protocolbuffers/docs/encoding.html. La versione breve è che il messaggio è codificato come una sequenza di coppie chiave-valore, e solo i campi che sono esplicitamente impostati sono inclusi nel messaggio codificato.

I valori predefiniti entrano in gioco solo quando si tenta di leggere un campo non impostato.

+0

Grazie. Ma per essere chiari: (1) Se I * esplicitamente * imposta un campo su un valore (anche il suo valore predefinito), allora ha_xxx è vero; e (2) se serializzo un oggetto protobuf, allora un campo verrà inviato sul filo se has_xxx è vero, anche se il valore del campo è il valore predefinito? –

+0

Sì, è corretto. – JesperE

+1

Non penso sia corretto. Non dice da nessuna parte nella documentazione delle specifiche che hai collegato: (1) Un membro dovrebbe essere codificato comunque se il suo valore corrisponde al valore predefinito. (2) L'implementazione di protobuf deve consentire di distinguere tra un valore predefinito codificato e un valore predefinito impostato durante la decodifica.Sono byte extra per inviare un tag + ID vuoto sul filo quando la definizione sull'altro capo ha già un valore predefinito adatto. Inoltre, la documentazione riporta anche "Se uno qualsiasi dei tuoi elementi è opzionale, il messaggio codificato può avere o meno una coppia chiave-valore con quel numero di tag". – shanna

Problemi correlati