2012-02-06 12 views
21

Estoy tratando de determinar la relación entre valores predeterminados y has_foo() métodos que se declaran en varias interfaces programáticas. En particular, estoy tratando de determinar bajo qué circunstancias (si hay alguna) puede "diferenciar" entre un campo explícitamente establecido en el valor predeterminado, y un valor no establecido.¿cómo se relacionan los métodos has_field() con los valores predeterminados en protobuf?

  1. Si fijo explícitamente un campo (por ejemplo, "Bar.foo") a su valor por defecto (por ejemplo, cero), entonces es Bar :: has_foo() retorno garantizado cierto para esa estructura de datos? (Esto parece ser cierto para el código generado por C++, a partir de una inspección rápida, pero eso no significa que esté garantizado). Si esto es cierto, entonces es posible distinguir entre un valor predeterminado establecido explícitamente y un valor antes de la serialización.

  2. Si configuré explícitamente un campo a su valor predeterminado (por ejemplo, cero), y luego serializo ese objeto y lo envío a través del cable, ¿se enviará o no el valor? Si no es así, es evidente que cualquier código que recibe este objeto no puede distinguir entre un valor predeterminado establecido explícitamente y un valor no establecido. Es decir, no será posible distinguir estos dos casos después de la serialización - Bar :: has_foo() devolverá falso en ambos casos.

Si no es posible distinguir la diferencia, ¿cuál es la técnica recomendada para codificar un campo protobuf si quiero codificar un valor opcional "anulable"? Me vienen a la mente un par de opciones, pero ninguna de las dos parece excelente: (a) agregue un campo booleano adicional que registre si el campo está o no configurado, o (b) use un campo "repetido" aunque quiero semánticamente un campo opcional - de esta manera puedo decir la diferencia entre ningún valor (lista de longitud cero) o un valor establecido (lista de longitud uno).

Respuesta

26

Lo siguiente se aplica para la sintaxis 'proto2', no 'proto3':

La noción de un campo que se está establecido o no es una característica núcleo de Protobuf. Si establece un campo en un valor (cualquier valor), el método correspondiente has_xxxdebe devolver verdadero; de lo contrario, tiene un error en la API.

Si no establece un campo y luego serializa el mensaje, no se envía ningún valor para ese campo. El lado receptor analizará el mensaje, descubrirá qué valores se incluyen y establecerá los valores "has_xxx" correspondientes.

Aquí se documenta cómo se implementa esto exactamente en el formato de cable: http://code.google.com/apis/protocolbuffers/docs/encoding.html. La versión corta es que el mensaje está codificado como una secuencia de pares clave-valor, y solo los campos que están explícitamente establecidos se incluyen en el mensaje codificado.

Los valores predeterminados solo entran en juego cuando intenta leer un campo no configurado.

+0

Gracias. Pero para ser claros: (1) Si * explícitamente * establece un campo para un valor (incluso su valor predeterminado), entonces has_xxx es verdadero; y (2) si serializo un objeto protobuf, se enviará un campo por el cable si has_xxx es verdadero, incluso si el valor del campo es el valor predeterminado? –

+0

Sí, eso es correcto. – JesperE

+1

No creo que sea correcto. No dice en ningún lugar de la documentación de especificaciones que vinculó que: (1) Un miembro debe codificarse de todos modos si su valor coincide con el valor predeterminado. (2) La implementación de protobuf debe permitirle distinguir entre un valor predeterminado codificado y un valor predeterminado establecido durante la decodificación.Son bytes adicionales para enviar una etiqueta + identificación vacía a través del cable cuando la definición en el otro extremo ya tiene un valor predeterminado adecuado. Además, la documentación incluso establece "Si alguno de tus elementos es opcional, el mensaje codificado puede tener o no un par clave-valor con ese número de etiqueta". – shanna

Cuestiones relacionadas