com.bendb.thrifty.schema.Requiredness Maven / Gradle / Ivy
Show all versions of thrifty-schema Show documentation
/*
* Copyright (C) 2015-2016 Benjamin Bader
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bendb.thrifty.schema;
/**
* A description of whether and when a field may be absent from a struct,
* union, or exception.
*
* The semantics of required, optional, and the default are underspecified
* at present. Intuitively, `required` should mean that the struct containing
* the field cannot be valid unless the field is present, where `optional`
* would indicate that the field's presence does not affect the struct's
* validity. The actual impacts of these modifiers are both more subtle and
* implementation-defined, varying both by runtime library and code-generator
* implementations.
*
*
For a more thorough treatment of the subject, see
* this blog post which,
* though being five years old at the time of writing, is still relevant. Read
* on for my own interpretation of things.
*
*
What does the official implementation do?
*
* There are two times when requiredness modifiers affect behavior - during
* serialization and during struct validation. During serialization, they
* affect whether a field will be written to the underlying protocol. During
* validation, they determine whether an unset field will cause validation to
* fail. As this is not documented anywhere, a close reading of the Apache
* implementation's Java code generator yields the following tables, describing
* the actual impact of the modifiers:
*
*
Will an unset field be serialized?
*
* The question refers to whether writing a struct to a protocol will result in
* a beginField, field, endField sequence being emitted.
*
*
*
*
*
* Value types
* Objects
*
*
*
*
* Default
* always*
* if set
*
*
* Optional
* if set
* if set
*
*
* Required
* always*
* always
*
*
*
*
* As can be seen, serialization behavior only changes for value types.
*
*
Validation: Will a field potentially cause validation failures?
*
* Validation happens at the beginning of serialization and the end of
* deserialization. In both cases, the following table describes the impact
* of a missing field:
*
*
*
*
*
* Value Type
* Object
*
*
*
*
* Default
* no
* no
*
*
* Optional
* no
* no
*
*
* Required
* only on deserialization
* yes
*
*
*
*
* What does Thrifty do?
*
* For a few reasons, Thrifty has a simpler decision matrix. As noted, we
* do not provide server implementations, and so are unconcerned with the
* distinction between standard and RPC-result serialization. Second, we
* do not track {@code isSet} for fields - if a field is {@code null}, it is
* unset. As such, we differ from Apache in a few minor ways.
*
*
Missing required value-types always fail validation
*
* In Apache, a struct can pass validation if it has required-but-unset
* value-type fields. In Thrifty, this is not possible - structs cannot be
* built without all required members.
*
*
Missing, default, value-types are not serialized
*
* This is probably the most significant difference. Apache will serialize
* unset value-type fields as whatever default value may be there. It is
* technically possible for non-zero values that are not "set" to be sent!
* In contrast, Thrifty treats default-requiredness "value types" as optional.
* The rationale for diverging from the official implementation is twofold.
* One, sending data that is not set is deeply suspect.
*/
public enum Requiredness {
/**
* No requirement. The semantics of this are undefined, but in practice
* can mean required for serialization, optional for deserialization.
*
*
This is not consistent between server implementations.
*
*
For Thrifty's purposes, this is treated as optional.
*/
DEFAULT,
/**
* Required. In practice this means that a field must be present both on
* serialization and on deserialization.
*/
REQUIRED,
/**
* Optional fields may be unset at all times.
*/
OPTIONAL
}