1 /* 2 * Copyright (c) 2021, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file defines OpenThread `Appender` class. 32 */ 33 34 #ifndef APPENDER_HPP_ 35 #define APPENDER_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include "common/const_cast.hpp" 40 #include "common/data.hpp" 41 #include "common/frame_builder.hpp" 42 #include "common/message.hpp" 43 #include "common/type_traits.hpp" 44 45 namespace ot { 46 47 /** 48 * The `Appender` class acts as a wrapper over either a `Message` or a data buffer and provides different flavors of 49 * `Append()` method. 50 * 51 * Helps in construction of message content where the destination can be either a `Message` or a buffer. 52 */ 53 class Appender 54 { 55 public: 56 /** 57 * Represent the `Appender` Type (whether appending to a `Message` or data buffer). 58 */ 59 enum Type : uint8_t 60 { 61 kMessage, ///< `Appender` appends to a `Message` 62 kBuffer, ///< `Appender` appends to a buffer. 63 }; 64 65 /** 66 * Initializes the `Appender` to append to a `Message`. 67 * 68 * New content is appended to the end of @p aMessage, growing its length. 69 * 70 * @param[in] aMessage The message to append to. 71 */ 72 explicit Appender(Message &aMessage); 73 74 /** 75 * Initializes the `Appender` to append in a given a buffer 76 * 77 * New content is append in the buffer starting from @p aBuffer up to is size @p aSize. `Appender` does not allow 78 * content to be appended beyond the size of the buffer. 79 * 80 * @param[in] aBuffer A pointer to start of buffer. 81 * @param[in] aSize The maximum size of @p aBuffer (number of available bytes in buffer). 82 */ 83 Appender(uint8_t *aBuffer, uint16_t aSize); 84 85 /** 86 * Indicates the `Appender` type (whether appending to a `Message` or data buffer). 87 * 88 * @returns The type of `Appender`. 89 */ GetType(void) const90 Type GetType(void) const { return mType; } 91 92 /** 93 * Appends bytes to the `Appender` object 94 * 95 * @param[in] aBuffer A pointer to a data buffer (MUST NOT be `nullptr`) to append. 96 * @param[in] aLength The number of bytes to append. 97 * 98 * @retval kErrorNone Successfully appended the bytes. 99 * @retval kErrorNoBufs Insufficient available buffers. 100 */ 101 Error AppendBytes(const void *aBuffer, uint16_t aLength); 102 103 /** 104 * Appends an object to the end of the `Appender` object. 105 * 106 * @tparam ObjectType The object type to append to the message. 107 * 108 * @param[in] aObject A reference to the object to append to the message. 109 * 110 * @retval kErrorNone Successfully appended the object. 111 * @retval kErrorNoBufs Insufficient available buffers to append @p aObject. 112 */ Append(const ObjectType & aObject)113 template <typename ObjectType> Error Append(const ObjectType &aObject) 114 { 115 static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); 116 117 return AppendBytes(&aObject, sizeof(ObjectType)); 118 } 119 120 /** 121 * Returns the number of bytes appended so far using `Appender` methods. 122 * 123 * Can be used independent of the `Type` of `Appender`. 124 * 125 * @returns The number of byes appended so far. 126 */ 127 uint16_t GetAppendedLength(void) const; 128 129 /** 130 * Returns the `Message` associated with `Appender`. 131 * 132 * MUST be used when `GetType() == kMessage`. Otherwise its behavior is undefined. 133 * 134 * @returns The `Message` instance associated with `Appender`. 135 */ GetMessage(void) const136 Message &GetMessage(void) const { return *mShared.mMessage.mMessage; } 137 138 /** 139 * Returns a pointer to the start of the data buffer associated with `Appender`. 140 * 141 * MUST be used when `GetType() == kBuffer`. Otherwise its behavior is undefined. 142 * 143 * @returns A pointer to the start of the data buffer associated with `Appender`. 144 */ GetBufferStart(void) const145 uint8_t *GetBufferStart(void) const { return AsNonConst(mShared.mFrameBuilder.GetBytes()); } 146 147 /** 148 * Gets the data buffer associated with `Appender` as a `Data`. 149 * 150 * MUST be used when `GetType() == kBuffer`. Otherwise its behavior is undefined. 151 * 152 * @pram[out] aData A reference to a `Data` to output the data buffer. 153 */ 154 void GetAsData(Data<kWithUint16Length> &aData) const; 155 156 private: 157 Type mType; 158 union 159 { 160 struct 161 { 162 Message *mMessage; 163 uint16_t mStartOffset; 164 } mMessage; 165 166 FrameBuilder mFrameBuilder; 167 } mShared; 168 }; 169 170 } // namespace ot 171 172 #endif // APPENDER_HPP_ 173