1 /*
2  *  Copyright (c) 2022, 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 includes definitions for `FrameData`.
32  */
33 
34 #ifndef FRAME_DATA_HPP_
35 #define FRAME_DATA_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "common/data.hpp"
40 #include "common/type_traits.hpp"
41 
42 namespace ot {
43 
44 /**
45  * Represents a frame `Data` which is simply a wrapper over a pointer to a buffer with a given frame length.
46  *
47  * It provide helper method to parse the content. As data is parsed and read, the `FrameData` is updated to skip over
48  * the read content.
49  *
50  */
51 class FrameData : public Data<kWithUint16Length>
52 {
53 public:
54     /**
55      * Indicates whether or not there are enough bytes remaining in the `FrameData` to read a given number
56      * of bytes.
57      *
58      * @param[in] aLength   The read length to check.
59      *
60      * @retval TRUE   There are enough remaining bytes to read @p aLength bytes.
61      * @retval FALSE  There are not enough remaining bytes to read @p aLength bytes.
62      *
63      */
CanRead(uint16_t aLength) const64     bool CanRead(uint16_t aLength) const { return GetLength() >= aLength; }
65 
66     /**
67      * Reads an `uint8_t` value from the `FrameData`.
68      *
69      * If read successfully, the `FrameData` is updated to skip over the read content.
70      *
71      * @param[out] aUint8   A reference to an `uint8_t` to return the read value.
72      *
73      * @retval kErrorNone   Successfully read `uint8_t` value and skipped over it.
74      * @retval kErrorParse  Not enough bytes remaining to read.
75      *
76      */
77     Error ReadUint8(uint8_t &aUint8);
78 
79     /**
80      * Reads an `uint16_t` value assuming big endian encoding from the `FrameData`.
81      *
82      * If read successfully, the `FrameData` is updated to skip over the read content.
83      *
84      * @param[out] aUint16   A reference to an `uint16_t` to return the read value.
85      *
86      * @retval kErrorNone   Successfully read `uint16_t` value and skipped over it.
87      * @retval kErrorParse  Not enough bytes remaining to read.
88      *
89      */
90     Error ReadBigEndianUint16(uint16_t &aUint16);
91 
92     /**
93      * Reads an `uint32_t` value assuming big endian encoding from the `FrameData`.
94      *
95      * If read successfully, the `FrameData` is updated to skip over the read content.
96      *
97      * @param[out] aUint32   A reference to an `uint32_t` to return the read value.
98      *
99      * @retval kErrorNone   Successfully read `uint32_t` value and skipped over it.
100      * @retval kErrorParse  Not enough bytes remaining to read.
101      *
102      */
103     Error ReadBigEndianUint32(uint32_t &aUint32);
104 
105     /**
106      * Reads an `uint16_t` value assuming little endian encoding from the `FrameData`.
107      *
108      * If read successfully, the `FrameData` is updated to skip over the read content.
109      *
110      * @param[out] aUint16   A reference to an `uint16_t` to return the read value.
111      *
112      * @retval kErrorNone   Successfully read `uint16_t` value and skipped over it.
113      * @retval kErrorParse  Not enough bytes remaining to read.
114      *
115      */
116     Error ReadLittleEndianUint16(uint16_t &aUint16);
117 
118     /**
119      * Reads an `uint32_t` value assuming little endian encoding from the `FrameData`.
120      *
121      * If read successfully, the `FrameData` is updated to skip over the read content.
122      *
123      * @param[out] aUint32   A reference to an `uint32_t` to return the read value.
124      *
125      * @retval kErrorNone   Successfully read `uint32_t` value and skipped over it.
126      * @retval kErrorParse  Not enough bytes remaining to read.
127      *
128      */
129     Error ReadLittleEndianUint32(uint32_t &aUint32);
130 
131     /**
132      * Reads a given number of bytes from the `FrameData`.
133      *
134      * If read successfully, the `FrameData` is updated to skip over the read content.
135      *
136      * @param[out] aBuffer   The buffer to copy the read bytes into.
137      * @param[in]  aLength   Number of bytes to read.
138      *
139      * @retval kErrorNone   Successfully read @p aLength bytes into @p aBuffer and skipped over them.
140      * @retval kErrorParse  Not enough bytes remaining to read @p aLength.
141      *
142      */
143     Error ReadBytes(void *aBuffer, uint16_t aLength);
144 
145     /**
146      * Reads an object from the `FrameData`.
147      *
148      * @tparam     ObjectType   The object type to read from the message.
149      *
150      * @param[out] aObject      A reference to the object to read into.
151      *
152      * @retval kErrorNone     Successfully read @p aObject and skipped over the read content.
153      * @retval kErrorParse    Not enough bytes remaining to read the entire object.
154      *
155      */
Read(ObjectType & aObject)156     template <typename ObjectType> Error Read(ObjectType &aObject)
157     {
158         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
159 
160         return ReadBytes(&aObject, sizeof(ObjectType));
161     }
162 
163     /**
164      * Skips over a given number of bytes from `FrameData`.
165      *
166      * The caller MUST make sure that the @p aLength is smaller than current data length. Otherwise the behavior of
167      * this method is undefined.
168      *
169      * @param[in] aLength   The length (number of bytes) to skip over.
170      *
171      */
172     void SkipOver(uint16_t aLength);
173 };
174 
175 } // namespace ot
176 
177 #endif // FRAME_DATA_HPP_
178