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 #ifndef LIB_FIDL_CPP_MESSAGE_PART_H_
6 #define LIB_FIDL_CPP_MESSAGE_PART_H_
7 
8 #include <stdint.h>
9 #include <string.h>
10 
11 #include <zircon/types.h>
12 
13 namespace fidl {
14 
15 // Part of a FIDL message.
16 //
17 // A FIDL message has two parts: the bytes and the handles. This class is used
18 // to represent both kinds of parts.
19 //
20 // Each part of the message has a data buffer, which contains the actual data
21 // for that part of the message, a capacity for that buffer, and the actual
22 // amount of data stored in the buffer, which might be less that the capacity if
23 // the buffer is not completely full.
24 template<typename T>
25 class MessagePart {
26 public:
27     using value_type = T;
28     using const_iterator = const T*;
29 
30     // A message part with no storage.
MessagePart()31     MessagePart() : data_(nullptr), capacity_(0u), actual_(0u) {}
32 
33     // A message part that uses the given storage.
34     //
35     // The constructed |MessagePart| object does not take ownership of the given
36     // storage.
37     MessagePart(T* data, uint32_t capacity, uint32_t actual = 0u)
data_(data)38         : data_(data), capacity_(capacity), actual_(actual) {}
39 
40     MessagePart(const MessagePart& other) = delete;
41     MessagePart& operator=(const MessagePart& other) = delete;
42 
MessagePart(MessagePart && other)43     MessagePart(MessagePart&& other)
44         : data_(other.data_),
45           capacity_(other.capacity_),
46           actual_(other.actual_) {
47         other.data_ = nullptr;
48         other.capacity_ = 0u;
49         other.actual_ = 0u;
50     }
51 
52     MessagePart& operator=(MessagePart&& other) {
53         if (this == &other)
54             return *this;
55         data_ = other.data_;
56         capacity_ = other.capacity_;
57         actual_ = other.actual_;
58         other.data_ = nullptr;
59         other.capacity_ = 0u;
60         other.actual_ = 0u;
61         return *this;
62     }
63 
64     // The data stored in this part of the message.
data()65     T* data() const { return data_; }
66 
67     // The total amount of storage available for this part of the message.
68     //
69     // This part of the message might not actually use all of this storage. To
70     // determine how much storage is actually being used, see |actual()|.
capacity()71     uint32_t capacity() const { return capacity_; }
72 
73     // The amount of storage that is actually being used for this part of the
74     // message.
75     //
76     // There might be more storage available than is actually being used. To
77     // determine how much storage is available, see |capacity()|.
actual()78     uint32_t actual() const { return actual_; }
set_actual(uint32_t actual)79     void set_actual(uint32_t actual) { actual_ = actual; }
80 
begin()81     T* begin() { return data_; }
begin()82     const T* begin() const { return data_; }
cbegin()83     const T* cbegin() const { return data_; }
84 
end()85     T* end() { return data_ + actual_; }
end()86     const T* end() const { return data_ + actual_; }
cend()87     const T* cend() const { return data_ + actual_; }
88 
size()89     size_t size() const { return actual_; }
90 
91 private:
92     T* data_;
93     uint32_t capacity_;
94     uint32_t actual_;
95 };
96 
97 using BytePart = MessagePart<uint8_t>;
98 using HandlePart = MessagePart<zx_handle_t>;
99 
100 } // namespace fidl
101 
102 #endif // LIB_FIDL_CPP_MESSAGE_PART_H_
103