1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker * Copyright (c) 2017, The OpenThread Authors.
3*cfb92d14SAndroid Build Coastguard Worker * All rights reserved.
4*cfb92d14SAndroid Build Coastguard Worker *
5*cfb92d14SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
6*cfb92d14SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met:
7*cfb92d14SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
8*cfb92d14SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
9*cfb92d14SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
10*cfb92d14SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
11*cfb92d14SAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
12*cfb92d14SAndroid Build Coastguard Worker * 3. Neither the name of the copyright holder nor the
13*cfb92d14SAndroid Build Coastguard Worker * names of its contributors may be used to endorse or promote products
14*cfb92d14SAndroid Build Coastguard Worker * derived from this software without specific prior written permission.
15*cfb92d14SAndroid Build Coastguard Worker *
16*cfb92d14SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17*cfb92d14SAndroid Build Coastguard Worker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*cfb92d14SAndroid Build Coastguard Worker * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*cfb92d14SAndroid Build Coastguard Worker * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20*cfb92d14SAndroid Build Coastguard Worker * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21*cfb92d14SAndroid Build Coastguard Worker * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22*cfb92d14SAndroid Build Coastguard Worker * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23*cfb92d14SAndroid Build Coastguard Worker * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*cfb92d14SAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25*cfb92d14SAndroid Build Coastguard Worker * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*cfb92d14SAndroid Build Coastguard Worker */
27*cfb92d14SAndroid Build Coastguard Worker
28*cfb92d14SAndroid Build Coastguard Worker /**
29*cfb92d14SAndroid Build Coastguard Worker * @file
30*cfb92d14SAndroid Build Coastguard Worker * This file implements a spinel decoder.
31*cfb92d14SAndroid Build Coastguard Worker */
32*cfb92d14SAndroid Build Coastguard Worker
33*cfb92d14SAndroid Build Coastguard Worker #include "spinel_decoder.hpp"
34*cfb92d14SAndroid Build Coastguard Worker
35*cfb92d14SAndroid Build Coastguard Worker #include "common/string.hpp"
36*cfb92d14SAndroid Build Coastguard Worker #include "lib/utils/utils.hpp"
37*cfb92d14SAndroid Build Coastguard Worker
38*cfb92d14SAndroid Build Coastguard Worker namespace ot {
39*cfb92d14SAndroid Build Coastguard Worker namespace Spinel {
40*cfb92d14SAndroid Build Coastguard Worker
Decoder(void)41*cfb92d14SAndroid Build Coastguard Worker Decoder::Decoder(void)
42*cfb92d14SAndroid Build Coastguard Worker : mFrame(nullptr)
43*cfb92d14SAndroid Build Coastguard Worker , mLength(0)
44*cfb92d14SAndroid Build Coastguard Worker , mIndex(0)
45*cfb92d14SAndroid Build Coastguard Worker , mEnd(0)
46*cfb92d14SAndroid Build Coastguard Worker , mNumOpenStructs(0)
47*cfb92d14SAndroid Build Coastguard Worker , mSavedNumOpenStructs(0)
48*cfb92d14SAndroid Build Coastguard Worker , mSavedIndex(0)
49*cfb92d14SAndroid Build Coastguard Worker , mSavedEnd(0)
50*cfb92d14SAndroid Build Coastguard Worker {
51*cfb92d14SAndroid Build Coastguard Worker }
52*cfb92d14SAndroid Build Coastguard Worker
Init(const uint8_t * aFrame,uint16_t aLength)53*cfb92d14SAndroid Build Coastguard Worker void Decoder::Init(const uint8_t *aFrame, uint16_t aLength)
54*cfb92d14SAndroid Build Coastguard Worker {
55*cfb92d14SAndroid Build Coastguard Worker mFrame = aFrame;
56*cfb92d14SAndroid Build Coastguard Worker mLength = (mFrame != nullptr) ? aLength : 0;
57*cfb92d14SAndroid Build Coastguard Worker
58*cfb92d14SAndroid Build Coastguard Worker Reset();
59*cfb92d14SAndroid Build Coastguard Worker ClearSavedPosition();
60*cfb92d14SAndroid Build Coastguard Worker }
61*cfb92d14SAndroid Build Coastguard Worker
Reset(void)62*cfb92d14SAndroid Build Coastguard Worker void Decoder::Reset(void)
63*cfb92d14SAndroid Build Coastguard Worker {
64*cfb92d14SAndroid Build Coastguard Worker mIndex = 0;
65*cfb92d14SAndroid Build Coastguard Worker mEnd = mLength;
66*cfb92d14SAndroid Build Coastguard Worker mNumOpenStructs = 0;
67*cfb92d14SAndroid Build Coastguard Worker ClearSavedPosition();
68*cfb92d14SAndroid Build Coastguard Worker }
69*cfb92d14SAndroid Build Coastguard Worker
ReadBool(bool & aBool)70*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadBool(bool &aBool)
71*cfb92d14SAndroid Build Coastguard Worker {
72*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
73*cfb92d14SAndroid Build Coastguard Worker uint8_t byte;
74*cfb92d14SAndroid Build Coastguard Worker
75*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = ReadUint8(byte));
76*cfb92d14SAndroid Build Coastguard Worker
77*cfb92d14SAndroid Build Coastguard Worker // Boolean value are encoded in 8-bits as either 0x00 or 0x01. All other values are illegal.
78*cfb92d14SAndroid Build Coastguard Worker if (byte == 0x00)
79*cfb92d14SAndroid Build Coastguard Worker {
80*cfb92d14SAndroid Build Coastguard Worker aBool = false;
81*cfb92d14SAndroid Build Coastguard Worker }
82*cfb92d14SAndroid Build Coastguard Worker else if (byte == 0x01)
83*cfb92d14SAndroid Build Coastguard Worker {
84*cfb92d14SAndroid Build Coastguard Worker aBool = true;
85*cfb92d14SAndroid Build Coastguard Worker }
86*cfb92d14SAndroid Build Coastguard Worker else
87*cfb92d14SAndroid Build Coastguard Worker {
88*cfb92d14SAndroid Build Coastguard Worker error = OT_ERROR_PARSE;
89*cfb92d14SAndroid Build Coastguard Worker }
90*cfb92d14SAndroid Build Coastguard Worker
91*cfb92d14SAndroid Build Coastguard Worker exit:
92*cfb92d14SAndroid Build Coastguard Worker return error;
93*cfb92d14SAndroid Build Coastguard Worker }
94*cfb92d14SAndroid Build Coastguard Worker
ReadUint8(uint8_t & aUint8)95*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadUint8(uint8_t &aUint8)
96*cfb92d14SAndroid Build Coastguard Worker {
97*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
98*cfb92d14SAndroid Build Coastguard Worker
99*cfb92d14SAndroid Build Coastguard Worker EXPECT(mIndex + sizeof(uint8_t) <= mEnd, error = OT_ERROR_PARSE);
100*cfb92d14SAndroid Build Coastguard Worker aUint8 = mFrame[mIndex];
101*cfb92d14SAndroid Build Coastguard Worker mIndex += sizeof(uint8_t);
102*cfb92d14SAndroid Build Coastguard Worker
103*cfb92d14SAndroid Build Coastguard Worker exit:
104*cfb92d14SAndroid Build Coastguard Worker return error;
105*cfb92d14SAndroid Build Coastguard Worker }
106*cfb92d14SAndroid Build Coastguard Worker
ReadInt8(int8_t & aInt8)107*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadInt8(int8_t &aInt8)
108*cfb92d14SAndroid Build Coastguard Worker {
109*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
110*cfb92d14SAndroid Build Coastguard Worker uint8_t byte;
111*cfb92d14SAndroid Build Coastguard Worker
112*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = ReadUint8(byte));
113*cfb92d14SAndroid Build Coastguard Worker aInt8 = static_cast<int8_t>(byte);
114*cfb92d14SAndroid Build Coastguard Worker
115*cfb92d14SAndroid Build Coastguard Worker exit:
116*cfb92d14SAndroid Build Coastguard Worker return error;
117*cfb92d14SAndroid Build Coastguard Worker }
118*cfb92d14SAndroid Build Coastguard Worker
ReadUint16(uint16_t & aUint16)119*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadUint16(uint16_t &aUint16)
120*cfb92d14SAndroid Build Coastguard Worker {
121*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
122*cfb92d14SAndroid Build Coastguard Worker
123*cfb92d14SAndroid Build Coastguard Worker EXPECT(mIndex + sizeof(uint16_t) <= mEnd, error = OT_ERROR_PARSE);
124*cfb92d14SAndroid Build Coastguard Worker
125*cfb92d14SAndroid Build Coastguard Worker aUint16 = static_cast<uint16_t>(mFrame[mIndex] | (mFrame[mIndex + 1] << 8));
126*cfb92d14SAndroid Build Coastguard Worker
127*cfb92d14SAndroid Build Coastguard Worker mIndex += sizeof(uint16_t);
128*cfb92d14SAndroid Build Coastguard Worker
129*cfb92d14SAndroid Build Coastguard Worker exit:
130*cfb92d14SAndroid Build Coastguard Worker return error;
131*cfb92d14SAndroid Build Coastguard Worker }
132*cfb92d14SAndroid Build Coastguard Worker
ReadInt16(int16_t & aInt16)133*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadInt16(int16_t &aInt16)
134*cfb92d14SAndroid Build Coastguard Worker {
135*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
136*cfb92d14SAndroid Build Coastguard Worker uint16_t u16;
137*cfb92d14SAndroid Build Coastguard Worker
138*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = ReadUint16(u16));
139*cfb92d14SAndroid Build Coastguard Worker aInt16 = static_cast<int16_t>(u16);
140*cfb92d14SAndroid Build Coastguard Worker
141*cfb92d14SAndroid Build Coastguard Worker exit:
142*cfb92d14SAndroid Build Coastguard Worker return error;
143*cfb92d14SAndroid Build Coastguard Worker }
144*cfb92d14SAndroid Build Coastguard Worker
ReadUint32(uint32_t & aUint32)145*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadUint32(uint32_t &aUint32)
146*cfb92d14SAndroid Build Coastguard Worker {
147*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
148*cfb92d14SAndroid Build Coastguard Worker
149*cfb92d14SAndroid Build Coastguard Worker EXPECT(mIndex + sizeof(uint32_t) <= mEnd, error = OT_ERROR_PARSE);
150*cfb92d14SAndroid Build Coastguard Worker
151*cfb92d14SAndroid Build Coastguard Worker aUint32 = ((static_cast<uint32_t>(mFrame[mIndex + 0]) << 0) | (static_cast<uint32_t>(mFrame[mIndex + 1]) << 8) |
152*cfb92d14SAndroid Build Coastguard Worker (static_cast<uint32_t>(mFrame[mIndex + 2]) << 16) | (static_cast<uint32_t>(mFrame[mIndex + 3]) << 24));
153*cfb92d14SAndroid Build Coastguard Worker
154*cfb92d14SAndroid Build Coastguard Worker mIndex += sizeof(uint32_t);
155*cfb92d14SAndroid Build Coastguard Worker
156*cfb92d14SAndroid Build Coastguard Worker exit:
157*cfb92d14SAndroid Build Coastguard Worker return error;
158*cfb92d14SAndroid Build Coastguard Worker }
159*cfb92d14SAndroid Build Coastguard Worker
ReadInt32(int32_t & aInt32)160*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadInt32(int32_t &aInt32)
161*cfb92d14SAndroid Build Coastguard Worker {
162*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
163*cfb92d14SAndroid Build Coastguard Worker uint32_t u32;
164*cfb92d14SAndroid Build Coastguard Worker
165*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = ReadUint32(u32));
166*cfb92d14SAndroid Build Coastguard Worker aInt32 = static_cast<int32_t>(u32);
167*cfb92d14SAndroid Build Coastguard Worker
168*cfb92d14SAndroid Build Coastguard Worker exit:
169*cfb92d14SAndroid Build Coastguard Worker return error;
170*cfb92d14SAndroid Build Coastguard Worker }
171*cfb92d14SAndroid Build Coastguard Worker
ReadUint64(uint64_t & aUint64)172*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadUint64(uint64_t &aUint64)
173*cfb92d14SAndroid Build Coastguard Worker {
174*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
175*cfb92d14SAndroid Build Coastguard Worker
176*cfb92d14SAndroid Build Coastguard Worker EXPECT(mIndex + sizeof(uint64_t) <= mEnd, error = OT_ERROR_PARSE);
177*cfb92d14SAndroid Build Coastguard Worker
178*cfb92d14SAndroid Build Coastguard Worker aUint64 = ((static_cast<uint64_t>(mFrame[mIndex + 0]) << 0) | (static_cast<uint64_t>(mFrame[mIndex + 1]) << 8) |
179*cfb92d14SAndroid Build Coastguard Worker (static_cast<uint64_t>(mFrame[mIndex + 2]) << 16) | (static_cast<uint64_t>(mFrame[mIndex + 3]) << 24) |
180*cfb92d14SAndroid Build Coastguard Worker (static_cast<uint64_t>(mFrame[mIndex + 4]) << 32) | (static_cast<uint64_t>(mFrame[mIndex + 5]) << 40) |
181*cfb92d14SAndroid Build Coastguard Worker (static_cast<uint64_t>(mFrame[mIndex + 6]) << 48) | (static_cast<uint64_t>(mFrame[mIndex + 7]) << 56));
182*cfb92d14SAndroid Build Coastguard Worker
183*cfb92d14SAndroid Build Coastguard Worker mIndex += sizeof(uint64_t);
184*cfb92d14SAndroid Build Coastguard Worker
185*cfb92d14SAndroid Build Coastguard Worker exit:
186*cfb92d14SAndroid Build Coastguard Worker return error;
187*cfb92d14SAndroid Build Coastguard Worker }
188*cfb92d14SAndroid Build Coastguard Worker
ReadInt64(int64_t & aInt64)189*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadInt64(int64_t &aInt64)
190*cfb92d14SAndroid Build Coastguard Worker {
191*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
192*cfb92d14SAndroid Build Coastguard Worker uint64_t u64;
193*cfb92d14SAndroid Build Coastguard Worker
194*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = ReadUint64(u64));
195*cfb92d14SAndroid Build Coastguard Worker aInt64 = static_cast<int64_t>(u64);
196*cfb92d14SAndroid Build Coastguard Worker
197*cfb92d14SAndroid Build Coastguard Worker exit:
198*cfb92d14SAndroid Build Coastguard Worker return error;
199*cfb92d14SAndroid Build Coastguard Worker }
200*cfb92d14SAndroid Build Coastguard Worker
ReadUintPacked(unsigned int & aUint)201*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadUintPacked(unsigned int &aUint)
202*cfb92d14SAndroid Build Coastguard Worker {
203*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
204*cfb92d14SAndroid Build Coastguard Worker spinel_ssize_t parsedLen;
205*cfb92d14SAndroid Build Coastguard Worker unsigned int uint;
206*cfb92d14SAndroid Build Coastguard Worker
207*cfb92d14SAndroid Build Coastguard Worker parsedLen = spinel_packed_uint_decode(&mFrame[mIndex], mEnd - mIndex, &uint);
208*cfb92d14SAndroid Build Coastguard Worker EXPECT(parsedLen > 0, error = OT_ERROR_PARSE);
209*cfb92d14SAndroid Build Coastguard Worker
210*cfb92d14SAndroid Build Coastguard Worker mIndex += parsedLen;
211*cfb92d14SAndroid Build Coastguard Worker aUint = uint;
212*cfb92d14SAndroid Build Coastguard Worker
213*cfb92d14SAndroid Build Coastguard Worker exit:
214*cfb92d14SAndroid Build Coastguard Worker return error;
215*cfb92d14SAndroid Build Coastguard Worker }
216*cfb92d14SAndroid Build Coastguard Worker
217*cfb92d14SAndroid Build Coastguard Worker // Reads an item of given size and updates the pointer `aPtr`.
ReadItem(const uint8_t ** aPtr,uint16_t aSize)218*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadItem(const uint8_t **aPtr, uint16_t aSize)
219*cfb92d14SAndroid Build Coastguard Worker {
220*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
221*cfb92d14SAndroid Build Coastguard Worker
222*cfb92d14SAndroid Build Coastguard Worker EXPECT(mIndex + aSize <= mEnd, error = OT_ERROR_PARSE);
223*cfb92d14SAndroid Build Coastguard Worker
224*cfb92d14SAndroid Build Coastguard Worker *aPtr = &mFrame[mIndex];
225*cfb92d14SAndroid Build Coastguard Worker
226*cfb92d14SAndroid Build Coastguard Worker mIndex += aSize;
227*cfb92d14SAndroid Build Coastguard Worker
228*cfb92d14SAndroid Build Coastguard Worker exit:
229*cfb92d14SAndroid Build Coastguard Worker return error;
230*cfb92d14SAndroid Build Coastguard Worker }
231*cfb92d14SAndroid Build Coastguard Worker
ReadIp6Address(spinel_ipv6addr_t & aIp6Addr)232*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadIp6Address(spinel_ipv6addr_t &aIp6Addr)
233*cfb92d14SAndroid Build Coastguard Worker {
234*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
235*cfb92d14SAndroid Build Coastguard Worker const spinel_ipv6addr_t *ipv6AddrPtr = nullptr;
236*cfb92d14SAndroid Build Coastguard Worker
237*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = ReadIp6Address(ipv6AddrPtr));
238*cfb92d14SAndroid Build Coastguard Worker EXPECT(ipv6AddrPtr != nullptr, error = OT_ERROR_PARSE);
239*cfb92d14SAndroid Build Coastguard Worker aIp6Addr = *ipv6AddrPtr;
240*cfb92d14SAndroid Build Coastguard Worker
241*cfb92d14SAndroid Build Coastguard Worker exit:
242*cfb92d14SAndroid Build Coastguard Worker return error;
243*cfb92d14SAndroid Build Coastguard Worker }
244*cfb92d14SAndroid Build Coastguard Worker
ReadIp6Address(otIp6Address & aIp6Addr)245*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadIp6Address(otIp6Address &aIp6Addr)
246*cfb92d14SAndroid Build Coastguard Worker {
247*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
248*cfb92d14SAndroid Build Coastguard Worker const otIp6Address *ipv6AddrPtr = nullptr;
249*cfb92d14SAndroid Build Coastguard Worker
250*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = ReadIp6Address(ipv6AddrPtr));
251*cfb92d14SAndroid Build Coastguard Worker EXPECT(ipv6AddrPtr != nullptr, error = OT_ERROR_PARSE);
252*cfb92d14SAndroid Build Coastguard Worker aIp6Addr = *ipv6AddrPtr;
253*cfb92d14SAndroid Build Coastguard Worker
254*cfb92d14SAndroid Build Coastguard Worker exit:
255*cfb92d14SAndroid Build Coastguard Worker return error;
256*cfb92d14SAndroid Build Coastguard Worker }
257*cfb92d14SAndroid Build Coastguard Worker
ReadEui64(spinel_eui64_t & aEui64)258*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadEui64(spinel_eui64_t &aEui64)
259*cfb92d14SAndroid Build Coastguard Worker {
260*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
261*cfb92d14SAndroid Build Coastguard Worker const spinel_eui64_t *eui64Ptr = nullptr;
262*cfb92d14SAndroid Build Coastguard Worker
263*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = ReadEui64(eui64Ptr));
264*cfb92d14SAndroid Build Coastguard Worker EXPECT(eui64Ptr != nullptr, error = OT_ERROR_PARSE);
265*cfb92d14SAndroid Build Coastguard Worker aEui64 = *eui64Ptr;
266*cfb92d14SAndroid Build Coastguard Worker
267*cfb92d14SAndroid Build Coastguard Worker exit:
268*cfb92d14SAndroid Build Coastguard Worker return error;
269*cfb92d14SAndroid Build Coastguard Worker }
270*cfb92d14SAndroid Build Coastguard Worker
ReadEui64(otExtAddress & aEui64)271*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadEui64(otExtAddress &aEui64)
272*cfb92d14SAndroid Build Coastguard Worker {
273*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
274*cfb92d14SAndroid Build Coastguard Worker const otExtAddress *eui64Ptr = nullptr;
275*cfb92d14SAndroid Build Coastguard Worker
276*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = ReadEui64(eui64Ptr));
277*cfb92d14SAndroid Build Coastguard Worker EXPECT(eui64Ptr != nullptr, error = OT_ERROR_PARSE);
278*cfb92d14SAndroid Build Coastguard Worker aEui64 = *eui64Ptr;
279*cfb92d14SAndroid Build Coastguard Worker
280*cfb92d14SAndroid Build Coastguard Worker exit:
281*cfb92d14SAndroid Build Coastguard Worker return error;
282*cfb92d14SAndroid Build Coastguard Worker }
283*cfb92d14SAndroid Build Coastguard Worker
ReadEui48(spinel_eui48_t & aEui48)284*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadEui48(spinel_eui48_t &aEui48)
285*cfb92d14SAndroid Build Coastguard Worker {
286*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
287*cfb92d14SAndroid Build Coastguard Worker const spinel_eui48_t *eui48Ptr = nullptr;
288*cfb92d14SAndroid Build Coastguard Worker
289*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = ReadEui48(eui48Ptr));
290*cfb92d14SAndroid Build Coastguard Worker EXPECT(eui48Ptr != nullptr, error = OT_ERROR_PARSE);
291*cfb92d14SAndroid Build Coastguard Worker aEui48 = *eui48Ptr;
292*cfb92d14SAndroid Build Coastguard Worker
293*cfb92d14SAndroid Build Coastguard Worker exit:
294*cfb92d14SAndroid Build Coastguard Worker return error;
295*cfb92d14SAndroid Build Coastguard Worker }
296*cfb92d14SAndroid Build Coastguard Worker
ReadUtf8(const char * & aUtf8)297*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadUtf8(const char *&aUtf8)
298*cfb92d14SAndroid Build Coastguard Worker {
299*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
300*cfb92d14SAndroid Build Coastguard Worker size_t len;
301*cfb92d14SAndroid Build Coastguard Worker
302*cfb92d14SAndroid Build Coastguard Worker // Ensure there is at least one byte (for null character).
303*cfb92d14SAndroid Build Coastguard Worker EXPECT(mIndex + sizeof(uint8_t) <= mEnd, error = OT_ERROR_PARSE);
304*cfb92d14SAndroid Build Coastguard Worker
305*cfb92d14SAndroid Build Coastguard Worker len = StringLength(reinterpret_cast<const char *>(&mFrame[mIndex]), mEnd - mIndex);
306*cfb92d14SAndroid Build Coastguard Worker EXPECT(len < static_cast<uint16_t>(mEnd - mIndex), error = OT_ERROR_PARSE);
307*cfb92d14SAndroid Build Coastguard Worker
308*cfb92d14SAndroid Build Coastguard Worker aUtf8 = reinterpret_cast<const char *>(&mFrame[mIndex]);
309*cfb92d14SAndroid Build Coastguard Worker
310*cfb92d14SAndroid Build Coastguard Worker // `sizeof(uint8_t)` is added for the terminating null character.
311*cfb92d14SAndroid Build Coastguard Worker mIndex += static_cast<uint16_t>(len + sizeof(uint8_t));
312*cfb92d14SAndroid Build Coastguard Worker
313*cfb92d14SAndroid Build Coastguard Worker exit:
314*cfb92d14SAndroid Build Coastguard Worker return error;
315*cfb92d14SAndroid Build Coastguard Worker }
316*cfb92d14SAndroid Build Coastguard Worker
ReadData(const uint8_t * & aData,uint16_t & aDataLen)317*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadData(const uint8_t *&aData, uint16_t &aDataLen)
318*cfb92d14SAndroid Build Coastguard Worker {
319*cfb92d14SAndroid Build Coastguard Worker aDataLen = mEnd - mIndex;
320*cfb92d14SAndroid Build Coastguard Worker
321*cfb92d14SAndroid Build Coastguard Worker return ReadItem(&aData, aDataLen);
322*cfb92d14SAndroid Build Coastguard Worker }
323*cfb92d14SAndroid Build Coastguard Worker
ReadDataWithLen(const uint8_t * & aData,uint16_t & aDataLen)324*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ReadDataWithLen(const uint8_t *&aData, uint16_t &aDataLen)
325*cfb92d14SAndroid Build Coastguard Worker {
326*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
327*cfb92d14SAndroid Build Coastguard Worker uint16_t len;
328*cfb92d14SAndroid Build Coastguard Worker
329*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = ReadUint16(len));
330*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = ReadItem(&aData, len));
331*cfb92d14SAndroid Build Coastguard Worker aDataLen = len;
332*cfb92d14SAndroid Build Coastguard Worker
333*cfb92d14SAndroid Build Coastguard Worker exit:
334*cfb92d14SAndroid Build Coastguard Worker return error;
335*cfb92d14SAndroid Build Coastguard Worker }
336*cfb92d14SAndroid Build Coastguard Worker
OpenStruct(void)337*cfb92d14SAndroid Build Coastguard Worker otError Decoder::OpenStruct(void)
338*cfb92d14SAndroid Build Coastguard Worker {
339*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
340*cfb92d14SAndroid Build Coastguard Worker uint16_t structLen;
341*cfb92d14SAndroid Build Coastguard Worker
342*cfb92d14SAndroid Build Coastguard Worker EXPECT(mNumOpenStructs < kMaxNestedStructs, error = OT_ERROR_INVALID_STATE);
343*cfb92d14SAndroid Build Coastguard Worker
344*cfb92d14SAndroid Build Coastguard Worker EXPECT_NO_ERROR(error = ReadUint16(structLen));
345*cfb92d14SAndroid Build Coastguard Worker EXPECT(structLen <= mEnd - mIndex, error = OT_ERROR_PARSE);
346*cfb92d14SAndroid Build Coastguard Worker
347*cfb92d14SAndroid Build Coastguard Worker mPrevEnd[mNumOpenStructs] = mEnd;
348*cfb92d14SAndroid Build Coastguard Worker mEnd = (mIndex + structLen);
349*cfb92d14SAndroid Build Coastguard Worker mNumOpenStructs++;
350*cfb92d14SAndroid Build Coastguard Worker
351*cfb92d14SAndroid Build Coastguard Worker exit:
352*cfb92d14SAndroid Build Coastguard Worker return error;
353*cfb92d14SAndroid Build Coastguard Worker }
354*cfb92d14SAndroid Build Coastguard Worker
CloseStruct(void)355*cfb92d14SAndroid Build Coastguard Worker otError Decoder::CloseStruct(void)
356*cfb92d14SAndroid Build Coastguard Worker {
357*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
358*cfb92d14SAndroid Build Coastguard Worker
359*cfb92d14SAndroid Build Coastguard Worker EXPECT(mNumOpenStructs > 0, error = OT_ERROR_INVALID_STATE);
360*cfb92d14SAndroid Build Coastguard Worker
361*cfb92d14SAndroid Build Coastguard Worker // If there is a saved position and it is contained
362*cfb92d14SAndroid Build Coastguard Worker // within the current struct being closed, the saved
363*cfb92d14SAndroid Build Coastguard Worker // position is cleared to ensure user cannot go back
364*cfb92d14SAndroid Build Coastguard Worker // to middle of an already closed struct.
365*cfb92d14SAndroid Build Coastguard Worker
366*cfb92d14SAndroid Build Coastguard Worker if (IsSavedPositionValid() && (mNumOpenStructs == mSavedNumOpenStructs))
367*cfb92d14SAndroid Build Coastguard Worker {
368*cfb92d14SAndroid Build Coastguard Worker ClearSavedPosition();
369*cfb92d14SAndroid Build Coastguard Worker }
370*cfb92d14SAndroid Build Coastguard Worker
371*cfb92d14SAndroid Build Coastguard Worker mNumOpenStructs--;
372*cfb92d14SAndroid Build Coastguard Worker mIndex = mEnd;
373*cfb92d14SAndroid Build Coastguard Worker mEnd = mPrevEnd[mNumOpenStructs];
374*cfb92d14SAndroid Build Coastguard Worker
375*cfb92d14SAndroid Build Coastguard Worker exit:
376*cfb92d14SAndroid Build Coastguard Worker return error;
377*cfb92d14SAndroid Build Coastguard Worker }
378*cfb92d14SAndroid Build Coastguard Worker
SavePosition(void)379*cfb92d14SAndroid Build Coastguard Worker void Decoder::SavePosition(void)
380*cfb92d14SAndroid Build Coastguard Worker {
381*cfb92d14SAndroid Build Coastguard Worker mSavedIndex = mIndex;
382*cfb92d14SAndroid Build Coastguard Worker mSavedEnd = mEnd;
383*cfb92d14SAndroid Build Coastguard Worker mSavedNumOpenStructs = mNumOpenStructs;
384*cfb92d14SAndroid Build Coastguard Worker }
385*cfb92d14SAndroid Build Coastguard Worker
ResetToSaved(void)386*cfb92d14SAndroid Build Coastguard Worker otError Decoder::ResetToSaved(void)
387*cfb92d14SAndroid Build Coastguard Worker {
388*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
389*cfb92d14SAndroid Build Coastguard Worker
390*cfb92d14SAndroid Build Coastguard Worker EXPECT(IsSavedPositionValid(), error = OT_ERROR_INVALID_STATE);
391*cfb92d14SAndroid Build Coastguard Worker
392*cfb92d14SAndroid Build Coastguard Worker mIndex = mSavedIndex;
393*cfb92d14SAndroid Build Coastguard Worker mEnd = mSavedEnd;
394*cfb92d14SAndroid Build Coastguard Worker mNumOpenStructs = mSavedNumOpenStructs;
395*cfb92d14SAndroid Build Coastguard Worker
396*cfb92d14SAndroid Build Coastguard Worker exit:
397*cfb92d14SAndroid Build Coastguard Worker return error;
398*cfb92d14SAndroid Build Coastguard Worker }
399*cfb92d14SAndroid Build Coastguard Worker
400*cfb92d14SAndroid Build Coastguard Worker } // namespace Spinel
401*cfb92d14SAndroid Build Coastguard Worker } // namespace ot
402