1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <lib/fidl/cpp/message_buffer.h>
6#include <zircon/assert.h>
7
8#include <stdlib.h>
9
10namespace fidl {
11namespace {
12
13uint64_t AddPadding(uint32_t offset) {
14    constexpr uint32_t kMask = alignof(zx_handle_t) - 1;
15    // Cast before addition to avoid overflow.
16    return static_cast<uint64_t>(offset) + static_cast<uint64_t>(offset & kMask);
17}
18
19size_t GetAllocSize(uint32_t bytes_capacity, uint32_t handles_capacity) {
20    return AddPadding(bytes_capacity) + sizeof(zx_handle_t) * handles_capacity;
21}
22
23} // namespace
24
25MessageBuffer::MessageBuffer(uint32_t bytes_capacity,
26                             uint32_t handles_capacity)
27    : buffer_(static_cast<uint8_t*>(malloc(GetAllocSize(bytes_capacity, handles_capacity)))),
28      bytes_capacity_(bytes_capacity),
29      handles_capacity_(handles_capacity) {
30    ZX_ASSERT_MSG(buffer_, "malloc returned NULL in MessageBuffer::MessageBuffer()");
31}
32
33MessageBuffer::~MessageBuffer() {
34    free(buffer_);
35}
36
37zx_handle_t* MessageBuffer::handles() const {
38    return reinterpret_cast<zx_handle_t*>(buffer_ + AddPadding(bytes_capacity_));
39}
40
41Message MessageBuffer::CreateEmptyMessage() {
42    return Message(BytePart(bytes(), bytes_capacity()),
43                   HandlePart(handles(), handles_capacity()));
44}
45
46Builder MessageBuffer::CreateBuilder() {
47    return Builder(bytes(), bytes_capacity());
48}
49
50} // namespace fidl
51