blob: a3fa04813a2e552f67ecdff92e2ddc4df5a7b7a5 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <mojo/bindings/union.h>
#include <assert.h>
#include <mojo/bindings/internal/type_descriptor.h>
#include <string.h>
#define UNION_TAG_UNKNOWN ((uint32_t)0xFFFFFFFF)
size_t MojomUnion_ComputeSerializedSize(
const struct MojomTypeDescriptorUnion* in_type_desc,
const struct MojomUnionLayout* in_union_data) {
assert(in_type_desc);
assert(in_union_data);
for (size_t i = 0; i < in_type_desc->num_entries; i++) {
const struct MojomTypeDescriptorUnionEntry* entry =
&(in_type_desc->entries[i]);
if (in_union_data->tag != entry->tag)
continue;
// We should skip non-pointer types.
if (!MojomType_IsPointer(entry->elem_type))
break;
return MojomType_DispatchComputeSerializedSize(
entry->elem_type, entry->elem_descriptor, entry->nullable,
&(in_union_data->data.pointer.ptr));
}
return 0;
}
void MojomUnion_EncodePointersAndHandles(
const struct MojomTypeDescriptorUnion* in_type_desc,
struct MojomUnionLayout* inout_union,
uint32_t in_buf_size,
struct MojomHandleBuffer* inout_handles_buffer) {
assert(in_buf_size >= sizeof(struct MojomUnionLayout));
for (size_t i = 0; i < in_type_desc->num_entries; i++) {
const struct MojomTypeDescriptorUnionEntry* entry =
&(in_type_desc->entries[i]);
if (inout_union->tag != entry->tag)
continue;
if (entry->elem_type == MOJOM_TYPE_DESCRIPTOR_TYPE_POD)
break;
MojomType_DispatchEncodePointersAndHandles(
entry->elem_type,
entry->elem_descriptor,
entry->nullable,
&inout_union->data,
in_buf_size - ((char*)&inout_union->data - (char*)inout_union),
inout_handles_buffer);
break;
}
}
void MojomUnion_DecodePointersAndHandles(
const struct MojomTypeDescriptorUnion* in_type_desc,
struct MojomUnionLayout* inout_union,
uint32_t in_union_size,
MojoHandle* inout_handles,
uint32_t in_num_handles) {
assert(in_union_size >= sizeof(struct MojomUnionLayout));
assert(inout_handles != NULL || in_num_handles == 0);
for (size_t i = 0; i < in_type_desc->num_entries; i++) {
const struct MojomTypeDescriptorUnionEntry* entry =
&(in_type_desc->entries[i]);
if (inout_union->tag != entry->tag)
continue;
if (entry->elem_type == MOJOM_TYPE_DESCRIPTOR_TYPE_POD)
break;
MojomType_DispatchDecodePointersAndHandles(
entry->elem_type,
entry->elem_descriptor,
entry->nullable,
&inout_union->data,
in_union_size - ((char*)&inout_union->data - (char*)inout_union),
inout_handles,
in_num_handles);
break;
}
}
MojomValidationResult MojomUnion_Validate(
const struct MojomTypeDescriptorUnion* in_type_desc,
bool in_nullable,
const struct MojomUnionLayout* in_union,
uint32_t in_union_size,
uint32_t in_num_handles,
struct MojomValidationContext* inout_context) {
for (size_t i = 0; i < in_type_desc->num_entries; i++) {
const struct MojomTypeDescriptorUnionEntry* entry =
&(in_type_desc->entries[i]);
if (in_union->tag != entry->tag)
continue;
if (entry->elem_type == MOJOM_TYPE_DESCRIPTOR_TYPE_POD)
break;
if (!in_nullable && in_union->size != sizeof(struct MojomUnionLayout))
return MOJOM_VALIDATION_UNEXPECTED_NULL_UNION;
return MojomType_DispatchValidate(
entry->elem_type,
entry->elem_descriptor,
entry->nullable,
&(in_union->data),
in_union_size - ((char*)&(in_union->data) - (char*)in_union),
in_num_handles,
inout_context);
}
return MOJOM_VALIDATION_ERROR_NONE;
}
bool MojomUnion_DeepCopy(struct MojomBuffer* buffer,
const struct MojomTypeDescriptorUnion* in_type_desc,
const struct MojomUnionLayout* in_union_data,
struct MojomUnionLayout* out_union_data) {
memcpy(out_union_data, in_union_data, sizeof(struct MojomUnionLayout));
// Unions with size 0 are null.
if (in_union_data->size == 0)
return true;
for (size_t i = 0; i < in_type_desc->num_entries; i++) {
const struct MojomTypeDescriptorUnionEntry* entry =
&(in_type_desc->entries[i]);
if (in_union_data->tag != entry->tag)
continue;
// We should skip non-pointer types.
if (entry->elem_type == MOJOM_TYPE_DESCRIPTOR_TYPE_POD)
return true;
return MojomType_DispatchDeepCopy(
buffer, entry->elem_type, entry->elem_descriptor,
&(in_union_data->data), &(out_union_data->data));
}
// We reach here if we don't recognize the tag. If it's the UNKNOWN tag, it's
// not a failure. If it's an unrecognized tag (erroneous or because this union
// is from a future-version), we don't know how to copy it, so the copy is a
// failure.
return in_union_data->tag < in_type_desc->num_fields ||
in_union_data->tag == UNION_TAG_UNKNOWN;
}