in thrift/lib/hack/src/ThriftSerializationHelper.php [165:355]
private static function readStructHelper(
TProtocol $protocol,
$field_type,
&$object,
$tspec,
): int {
$xfer = 0;
switch ($field_type) {
case TType::BOOL:
$xfer += $protocol->readBool(&$object);
break;
case TType::BYTE:
$xfer += $protocol->readByte(&$object);
break;
case TType::I16:
$xfer += $protocol->readI16(&$object);
break;
case TType::I32:
// Enums:
// In Hack, enums are encoded as I32s.
// This looks into the tspec to distinguish the two of them.
// Optimization opportunity: Add a TType of enum and encode that to
// the tspec to avoid this if statement.
if (isset($tspec['enum'])) {
$val = null;
$xfer += $protocol->readI32(&$val);
$enum_class = $tspec['enum'];
$object = $enum_class::coerce($val);
} else {
$xfer += $protocol->readI32(&$object);
}
break;
case TType::I64:
$xfer += $protocol->readI64(&$object);
break;
case TType::DOUBLE:
$xfer += $protocol->readDouble(&$object);
break;
case TType::FLOAT:
$xfer += $protocol->readFloat(&$object);
break;
case TType::STRING:
$xfer += $protocol->readString(&$object);
break;
case TType::LST:
$size = 0;
$element_type = 0;
$xfer += $protocol->readListBegin(&$element_type, &$size);
// Use the correct collection.
$list = null;
if ($tspec['format'] === 'harray') {
$list = vec[];
} else if ($tspec['format'] === 'collection') {
$list = Vector {};
} else { // format === 'array'
$list = varray[];
}
for ($i = 0; $size === null || $i < $size; ++$i) {
if ($size === null && !$protocol->readListHasNext()) {
break;
}
$list_element = null;
$xfer += self::readStructHelper(
$protocol,
$tspec['etype'],
&$list_element,
$tspec['elem']
);
// If the element type is enum and the enum
// does not exist, it will return a null.
if ($list_element === null) {
continue;
}
/* HH_IGNORE_ERROR[4006] type can be Vector, vec, or array */
$list[] = $list_element;
}
$object = $list;
$xfer += $protocol->readListEnd();
break;
case TType::SET:
$size = 0;
$element_type = 0;
$xfer += $protocol->readSetBegin(&$element_type, &$size);
// Use the correct collection.
if ($tspec['format'] === 'harray') {
$set = keyset[];
} else if ($tspec['format'] === 'collection') {
$set = Set {};
} else { // format === 'array'
$set = array();
}
for ($i = 0; $size === null || $i < $size; ++$i) {
if ($size === null && !$protocol->readSetHasNext()) {
break;
}
$set_element = null;
$xfer += self::readStructHelper(
$protocol,
$tspec['etype'],
&$set_element,
$tspec['elem']
);
// If the element type is enum and the enum
// does not exist, it will return a null.
if ($set_element === null) {
continue;
}
// When using a set array(), we can't append in the normal way.
// Therefore, we need to distinguish between the two types
// before we add the element to the set.
if ($tspec['format'] === 'array') {
invariant(is_array($set), 'for hack');
$set[$set_element] = true;
} else {
/* HH_IGNORE_ERROR[4006] type will be Set or keyset */
$set[] = $set_element;
}
}
$object = $set;
$xfer += $protocol->readSetEnd();
break;
case TType::MAP:
$size = 0;
$key_type = 0;
$value_type = 0;
$xfer += $protocol->readMapBegin(
inout $key_type,
inout $value_type,
inout $size,
);
// Use the correct collection.
$map = null;
if ($tspec['format'] === 'harray') {
$map = dict[];
} else if ($tspec['format'] === 'collection') {
$map = Map {};
} else { // format === 'array'
$map = array();
}
for ($i = 0; $size === null || $i < $size; ++$i) {
if ($size === null && !$protocol->readMapHasNext()) {
break;
}
$key = null;
$val = null;
$xfer += self::readStructHelper(
$protocol,
$tspec['ktype'],
&$key,
$tspec['key']
);
$xfer += self::readStructHelper(
$protocol,
$tspec['vtype'],
&$val,
$tspec['val']
);
// If the element type is enum and the enum
// does not exist, it will return a null.
if ($key === null || $val === null) {
continue;
}
$map[$key] = $val;
}
$object = $map;
$xfer += $protocol->readMapEnd();
break;
case TType::STRUCT:
$object = new $tspec['class']();
$xfer += $object->read($protocol);
break;
default:
$xfer += $protocol->skip($field_type);
}
return $xfer;
}