1 /*
2 * Copyright (c) 2016, 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 generating and processing MLE TLVs.
32 */
33
34 #ifndef TLVS_HPP_
35 #define TLVS_HPP_
36
37 #include "openthread-core-config.h"
38
39 #include <openthread/thread.h>
40 #include <openthread/platform/toolchain.h>
41
42 #include "common/encoding.hpp"
43 #include "common/error.hpp"
44 #include "common/type_traits.hpp"
45
46 namespace ot {
47
48 using ot::Encoding::BigEndian::HostSwap16;
49
50 class Message;
51
52 /**
53 * This class implements TLV generation and parsing.
54 *
55 */
56 OT_TOOL_PACKED_BEGIN
57 class Tlv
58 {
59 public:
60 /**
61 * The maximum length of the Base TLV format.
62 *
63 */
64 static constexpr uint8_t kBaseTlvMaxLength = OT_NETWORK_BASE_TLV_MAX_LENGTH;
65
66 /**
67 * This method returns the Type value.
68 *
69 * @returns The Type value.
70 *
71 */
GetType(void) const72 uint8_t GetType(void) const { return mType; }
73
74 /**
75 * This method sets the Type value.
76 *
77 * @param[in] aType The Type value.
78 *
79 */
SetType(uint8_t aType)80 void SetType(uint8_t aType) { mType = aType; }
81
82 /**
83 * This method indicates whether the TLV is an Extended TLV.
84 *
85 * @retval TRUE If the TLV is an Extended TLV.
86 * @retval FALSE If the TLV is not an Extended TLV.
87 *
88 */
IsExtended(void) const89 bool IsExtended(void) const { return (mLength == kExtendedLength); }
90
91 /**
92 * This method returns the Length value.
93 *
94 * @note This method should be used when TLV is not an Extended TLV, otherwise the returned length from this method
95 * would not be correct. When TLV is an Extended TLV, the TLV should be down-casted to the `ExtendedTlv` type and
96 * the `ExtendedTlv::GetLength()` should be used instead.
97 *
98 * @returns The Length value.
99 *
100 */
GetLength(void) const101 uint8_t GetLength(void) const { return mLength; }
102
103 /**
104 * This method sets the Length value.
105 *
106 * @param[in] aLength The Length value.
107 *
108 */
SetLength(uint8_t aLength)109 void SetLength(uint8_t aLength) { mLength = aLength; }
110
111 /**
112 * This method returns the TLV's total size (number of bytes) including Type, Length, and Value fields.
113 *
114 * This method correctly returns the TLV size independent of whether the TLV is an Extended TLV or not.
115 *
116 * @returns The total size include Type, Length, and Value fields.
117 *
118 */
119 uint32_t GetSize(void) const;
120
121 /**
122 * This method returns a pointer to the Value.
123 *
124 * This method can be used independent of whether the TLV is an Extended TLV or not.
125 *
126 * @returns A pointer to the value.
127 *
128 */
129 uint8_t *GetValue(void);
130
131 /**
132 * This method returns a pointer to the Value.
133 *
134 * This method can be used independent of whether the TLV is an Extended TLV or not.
135 *
136 * @returns A pointer to the value.
137 *
138 */
139 const uint8_t *GetValue(void) const;
140
141 /**
142 * This method returns a pointer to the next TLV.
143 *
144 * This method correctly returns the next TLV independent of whether the current TLV is an Extended TLV or not.
145 *
146 * @returns A pointer to the next TLV.
147 *
148 */
GetNext(void)149 Tlv *GetNext(void) { return reinterpret_cast<Tlv *>(reinterpret_cast<uint8_t *>(this) + GetSize()); }
150
151 /**
152 * This method returns a pointer to the next TLV.
153 *
154 * This method correctly returns the next TLV independent of whether the current TLV is an Extended TLV or not.
155 *
156 * @returns A pointer to the next TLV.
157 *
158 */
GetNext(void) const159 const Tlv *GetNext(void) const
160 {
161 return reinterpret_cast<const Tlv *>(reinterpret_cast<const uint8_t *>(this) + GetSize());
162 }
163
164 /**
165 * This method appends a TLV to the end of the message.
166 *
167 * On success, this method grows the message by the size of the TLV.
168 *
169 * @param[in] aMessage A reference to the message to append to.
170 *
171 * @retval kErrorNone Successfully appended the TLV to the message.
172 * @retval kErrorNoBufs Insufficient available buffers to grow the message.
173 *
174 */
175 Error AppendTo(Message &aMessage) const;
176
177 /**
178 * This static method reads a TLV's value in a message at a given offset expecting a minimum length for the value.
179 *
180 * This method can be used independent of whether the read TLV (from the message) is an Extended TLV or not.
181 *
182 * @param[in] aMessage The message to read from.
183 * @param[in] aOffset The offset into the message pointing to the start of the TLV.
184 * @param[out] aValue A buffer to output the TLV's value, must contain (at least) @p aMinLength bytes.
185 * @param[in] aMinLength The minimum expected length of TLV and number of bytes to copy into @p aValue buffer.
186 *
187 * @retval kErrorNone Successfully read the TLV and copied @p aMinLength into @p aValue.
188 * @retval kErrorParse The TLV was not well-formed and could not be parsed.
189 *
190 */
191 static Error ReadTlvValue(const Message &aMessage, uint16_t aOffset, void *aValue, uint8_t aMinLength);
192
193 /**
194 * This static method reads a simple TLV with a single non-integral value in a message at a given offset.
195 *
196 * @tparam SimpleTlvType The simple TLV type to read (must be a sub-class of `SimpleTlvInfo`).
197 *
198 * @param[in] aMessage The message to read from.
199 * @param[in] aOffset The offset into the message pointing to the start of the TLV.
200 * @param[out] aValue A reference to the value object to output the read value.
201 *
202 * @retval kErrorNone Successfully read the TLV and updated the @p aValue.
203 * @retval kErrorParse The TLV was not well-formed and could not be parsed.
204 *
205 */
206 template <typename SimpleTlvType>
Read(const Message & aMessage,uint16_t aOffset,typename SimpleTlvType::ValueType & aValue)207 static Error Read(const Message &aMessage, uint16_t aOffset, typename SimpleTlvType::ValueType &aValue)
208 {
209 return ReadTlvValue(aMessage, aOffset, &aValue, sizeof(aValue));
210 }
211
212 /**
213 * This static method reads a simple TLV with a single integral value in a message at a given offset.
214 *
215 * @tparam UintTlvType The simple TLV type to read (must be a sub-class of `UintTlvInfo`).
216 *
217 * @param[in] aMessage The message to read from.
218 * @param[in] aOffset The offset into the message pointing to the start of the TLV.
219 * @param[out] aValue A reference to an unsigned int to output the read value.
220 *
221 * @retval kErrorNone Successfully read the TLV and updated the @p aValue.
222 * @retval kErrorParse The TLV was not well-formed and could not be parsed.
223 *
224 */
225 template <typename UintTlvType>
Read(const Message & aMessage,uint16_t aOffset,typename UintTlvType::UintValueType & aValue)226 static Error Read(const Message &aMessage, uint16_t aOffset, typename UintTlvType::UintValueType &aValue)
227 {
228 return ReadUintTlv(aMessage, aOffset, aValue);
229 }
230
231 /**
232 * This static method reads a simple TLV with a UTF-8 string value in a message at a given offset.
233 *
234 * @tparam StringTlvType The simple TLV type to read (must be a sub-class of `StringTlvInfo`).
235 *
236 * @param[in] aMessage The message to read from.
237 * @param[in] aOffset The offset into the message pointing to the start of the TLV.
238 * @param[out] aValue A reference to the string buffer to output the read value.
239 *
240 * @retval kErrorNone Successfully read the TLV and updated the @p aValue.
241 * @retval kErrorParse The TLV was not well-formed and could not be parsed.
242 *
243 */
244 template <typename StringTlvType>
Read(const Message & aMessage,uint16_t aOffset,typename StringTlvType::StringType & aValue)245 static Error Read(const Message &aMessage, uint16_t aOffset, typename StringTlvType::StringType &aValue)
246 {
247 return ReadStringTlv(aMessage, aOffset, StringTlvType::kMaxStringLength, aValue);
248 }
249
250 /**
251 * This static method searches for and reads a requested TLV out of a given message.
252 *
253 * This method can be used independent of whether the read TLV (from message) is an Extended TLV or not.
254 *
255 * @param[in] aMessage A reference to the message.
256 * @param[in] aType The Type value to search for.
257 * @param[in] aMaxSize Maximum number of bytes to read.
258 * @param[out] aTlv A reference to the TLV that will be copied to.
259 *
260 * @retval kErrorNone Successfully copied the TLV.
261 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
262 *
263 */
264 static Error FindTlv(const Message &aMessage, uint8_t aType, uint16_t aMaxSize, Tlv &aTlv);
265
266 /**
267 * This static method searches for and reads a requested TLV out of a given message.
268 *
269 * This method can be used independent of whether the read TLV (from message) is an Extended TLV or not.
270 *
271 * @tparam TlvType The TlvType to search for (must be a sub-class of `Tlv`).
272 *
273 * @param[in] aMessage A reference to the message.
274 * @param[out] aTlv A reference to the TLV that will be copied to.
275 *
276 * @retval kErrorNone Successfully copied the TLV.
277 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
278 *
279 */
FindTlv(const Message & aMessage,TlvType & aTlv)280 template <typename TlvType> static Error FindTlv(const Message &aMessage, TlvType &aTlv)
281 {
282 return FindTlv(aMessage, TlvType::kType, sizeof(TlvType), aTlv);
283 }
284
285 /**
286 * This static method obtains the offset of a TLV within @p aMessage.
287 *
288 * This method can be used independent of whether the read TLV (from message) is an Extended TLV or not.
289 *
290 * @param[in] aMessage A reference to the message.
291 * @param[in] aType The Type value to search for.
292 * @param[out] aOffset A reference to the offset of the TLV.
293 *
294 * @retval kErrorNone Successfully copied the TLV.
295 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
296 *
297 */
298 static Error FindTlvOffset(const Message &aMessage, uint8_t aType, uint16_t &aOffset);
299
300 /**
301 * This static method finds the offset and length of a given TLV type.
302 *
303 * This method can be used independent of whether the read TLV (from message) is an Extended TLV or not.
304 *
305 * @param[in] aMessage A reference to the message.
306 * @param[in] aType The Type value to search for.
307 * @param[out] aValueOffset The offset where the value starts.
308 * @param[out] aLength The length of the value.
309 *
310 * @retval kErrorNone Successfully found the TLV.
311 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
312 *
313 */
314 static Error FindTlvValueOffset(const Message &aMessage, uint8_t aType, uint16_t &aValueOffset, uint16_t &aLength);
315
316 /**
317 * This static method searches for a TLV with a given type in a message, ensures its length is same or larger than
318 * an expected minimum value, and then reads its value into a given buffer.
319 *
320 * If the TLV length is smaller than the minimum length @p aLength, the TLV is considered invalid. In this case,
321 * this method returns `kErrorParse` and the @p aValue buffer is not updated.
322 *
323 * If the TLV length is larger than @p aLength, the TLV is considered valid, but only the first @p aLength bytes
324 * of the value are read and copied into the @p aValue buffer.
325 *
326 * @tparam TlvType The TLV type to find.
327 *
328 * @param[in] aMessage A reference to the message.
329 * @param[out] aValue A buffer to output the value (must contain at least @p aLength bytes).
330 * @param[in] aLength The expected (minimum) length of the TLV value.
331 *
332 * @retval kErrorNone The TLV was found and read successfully. @p aValue is updated.
333 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
334 * @retval kErrorParse TLV was found but it was not well-formed and could not be parsed.
335 *
336 */
Find(const Message & aMessage,void * aValue,uint8_t aLength)337 template <typename TlvType> static Error Find(const Message &aMessage, void *aValue, uint8_t aLength)
338 {
339 return FindTlv(aMessage, TlvType::kType, aValue, aLength);
340 }
341
342 /**
343 * This static method searches for a simple TLV with a single non-integral value in a message, ensures its length is
344 * same or larger than the expected `ValueType` object size, and then reads its value into a value object reference.
345 *
346 * If the TLV length is smaller than the size of @p aValue, the TLV is considered invalid. In this case, this
347 * method returns `kErrorParse` and the @p aValue is not updated.
348 *
349 * If the TLV length is larger than the size of @p aValue, the TLV is considered valid, but the size of
350 * `ValueType` bytes are read and copied into the @p aValue.
351 *
352 * @tparam SimpleTlvType The simple TLV type to find (must be a sub-class of `SimpleTlvInfo`)
353 *
354 * @param[in] aMessage A reference to the message.
355 * @param[out] aValue A reference to the value object to output the read value.
356 *
357 * @retval kErrorNone The TLV was found and read successfully. @p aValue is updated.
358 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
359 * @retval kErrorParse TLV was found but it was not well-formed and could not be parsed.
360 *
361 */
362 template <typename SimpleTlvType>
Find(const Message & aMessage,typename SimpleTlvType::ValueType & aValue)363 static Error Find(const Message &aMessage, typename SimpleTlvType::ValueType &aValue)
364 {
365 return FindTlv(aMessage, SimpleTlvType::kType, &aValue, sizeof(aValue));
366 }
367
368 /**
369 * This static method searches for a simple TLV with a single integral value in a message, and then reads its value
370 * into a given `uint` reference variable.
371 *
372 * If the TLV length is smaller than size of integral value, the TLV is considered invalid. In this case, this
373 * method returns `kErrorParse` and the @p aValue is not updated.
374 *
375 * @tparam UintTlvType The simple TLV type to find (must be a sub-class of `UintTlvInfo`)
376 *
377 * @param[in] aMessage A reference to the message.
378 * @param[out] aValue A reference to an unsigned int value to output the TLV's value.
379 *
380 * @retval kErrorNone The TLV was found and read successfully. @p aValue is updated.
381 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
382 * @retval kErrorParse TLV was found but it was not well-formed and could not be parsed.
383 *
384 */
385 template <typename UintTlvType>
Find(const Message & aMessage,typename UintTlvType::UintValueType & aValue)386 static Error Find(const Message &aMessage, typename UintTlvType::UintValueType &aValue)
387 {
388 return FindUintTlv(aMessage, UintTlvType::kType, aValue);
389 }
390
391 /**
392 * This static method searches for a simple TLV with a UTF-8 string value in a message, and then reads its value
393 * into a given string buffer.
394 *
395 * If the TLV length is longer than maximum string length specified by `StringTlvType::kMaxStringLength` then
396 * only up to maximum length is read and returned. In this case `kErrorNone` is returned.
397 *
398 * The returned string in @p aValue is always null terminated.`StringTlvType::StringType` MUST have at least
399 * `kMaxStringLength + 1` chars.
400 *
401 * @tparam StringTlvType The simple TLV type to find (must be a sub-class of `StringTlvInfo`)
402 *
403 * @param[in] aMessage A reference to the message.
404 * @param[out] aValue A reference to a string buffer to output the TLV's value.
405 *
406 * @retval kErrorNone The TLV was found and read successfully. @p aValue is updated.
407 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
408 * @retval kErrorParse TLV was found but it was not well-formed and could not be parsed.
409 *
410 */
411 template <typename StringTlvType>
Find(const Message & aMessage,typename StringTlvType::StringType & aValue)412 static Error Find(const Message &aMessage, typename StringTlvType::StringType &aValue)
413 {
414 return FindStringTlv(aMessage, StringTlvType::kType, StringTlvType::kMaxStringLength, aValue);
415 }
416
417 /**
418 * This static method appends a TLV with a given type and value to a message.
419 *
420 * On success this method grows the message by the size of the TLV.
421 *
422 * @tparam TlvType The TLV type to append.
423 *
424 * @param[in] aMessage A reference to the message to append to.
425 * @param[in] aValue A buffer containing the TLV value.
426 * @param[in] aLength The value length (in bytes).
427 *
428 * @retval kErrorNone Successfully appended the TLV to the message.
429 * @retval kErrorNoBufs Insufficient available buffers to grow the message.
430 *
431 */
Append(Message & aMessage,const void * aValue,uint8_t aLength)432 template <typename TlvType> static Error Append(Message &aMessage, const void *aValue, uint8_t aLength)
433 {
434 return AppendTlv(aMessage, TlvType::kType, aValue, aLength);
435 }
436
437 /**
438 * This static method appends a simple TLV with a single (non-integral) value to a message.
439 *
440 * On success this method grows the message by the size of the TLV.
441 *
442 * @tparam SimpleTlvType The simple TLV type to append (must be a sub-class of `SimpleTlvInfo`)
443 *
444 * @param[in] aMessage A reference to the message to append to.
445 * @param[in] aValue A reference to the object containing TLV's value.
446 *
447 * @retval kErrorNone Successfully appended the TLV to the message.
448 * @retval kErrorNoBufs Insufficient available buffers to grow the message.
449 *
450 */
451 template <typename SimpleTlvType>
Append(Message & aMessage,const typename SimpleTlvType::ValueType & aValue)452 static Error Append(Message &aMessage, const typename SimpleTlvType::ValueType &aValue)
453 {
454 return AppendTlv(aMessage, SimpleTlvType::kType, &aValue, sizeof(aValue));
455 }
456
457 /**
458 * This static method appends a simple TLV with a single integral value to a message.
459 *
460 * On success this method grows the message by the size of the TLV.
461 *
462 * @tparam UintTlvType The simple TLV type to append (must be a sub-class of `UintTlvInfo`)
463 *
464 * @param[in] aMessage A reference to the message to append to.
465 * @param[in] aValue An unsigned int value to use as TLV's value.
466 *
467 * @retval kErrorNone Successfully appended the TLV to the message.
468 * @retval kErrorNoBufs Insufficient available buffers to grow the message.
469 *
470 */
Append(Message & aMessage,typename UintTlvType::UintValueType aValue)471 template <typename UintTlvType> static Error Append(Message &aMessage, typename UintTlvType::UintValueType aValue)
472 {
473 return AppendUintTlv(aMessage, UintTlvType::kType, aValue);
474 }
475
476 /**
477 * This static method appends a simple TLV with a single UTF-8 string value to a message.
478 *
479 * On success this method grows the message by the size of the TLV.
480 *
481 * If the passed in @p aValue string length is longer than the maximum allowed length for the TLV as specified by
482 * `StringTlvType::kMaxStringLength`, the first maximum length chars are appended.
483 *
484 * The @p aValue can be `nullptr` in which case it is treated as an empty string.
485 *
486 * @tparam StringTlvType The simple TLV type to append (must be a sub-class of `StringTlvInfo`)
487 *
488 * @param[in] aMessage A reference to the message to append to.
489 * @param[in] aValue A pointer to a C string to append as TLV's value.
490 *
491 * @retval kErrorNone Successfully appended the TLV to the message.
492 * @retval kErrorNoBufs Insufficient available buffers to grow the message.
493 *
494 */
Append(Message & aMessage,const char * aValue)495 template <typename StringTlvType> static Error Append(Message &aMessage, const char *aValue)
496 {
497 return AppendStringTlv(aMessage, StringTlvType::kType, StringTlvType::kMaxStringLength, aValue);
498 }
499
500 protected:
501 static const uint8_t kExtendedLength = 255; // Extended Length value.
502
503 private:
504 struct ParsedInfo
505 {
506 Error ParseFrom(const Message &aMessage, uint16_t aOffset);
507 Error FindIn(const Message &aMessage, uint8_t aType);
508
509 uint8_t mType;
510 uint16_t mLength;
511 uint16_t mOffset;
512 uint16_t mValueOffset;
513 uint16_t mSize;
514 };
515
516 static Error FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint8_t aLength);
517 static Error AppendTlv(Message &aMessage, uint8_t aType, const void *aValue, uint8_t aLength);
518 static Error ReadStringTlv(const Message &aMessage, uint16_t aOffset, uint8_t aMaxStringLength, char *aValue);
519 static Error FindStringTlv(const Message &aMessage, uint8_t aType, uint8_t aMaxStringLength, char *aValue);
520 static Error AppendStringTlv(Message &aMessage, uint8_t aType, uint8_t aMaxStringLength, const char *aValue);
521 template <typename UintType> static Error ReadUintTlv(const Message &aMessage, uint16_t aOffset, UintType &aValue);
522 template <typename UintType> static Error FindUintTlv(const Message &aMessage, uint8_t aType, UintType &aValue);
523 template <typename UintType> static Error AppendUintTlv(Message &aMessage, uint8_t aType, UintType aValue);
524
525 uint8_t mType;
526 uint8_t mLength;
527 } OT_TOOL_PACKED_END;
528
529 OT_TOOL_PACKED_BEGIN
530 class ExtendedTlv : public Tlv
531 {
532 public:
533 /**
534 * This method returns the Length value.
535 *
536 */
GetLength(void) const537 uint16_t GetLength(void) const { return HostSwap16(mLength); }
538
539 /**
540 * This method sets the Length value.
541 *
542 * @param[in] aLength The Length value.
543 *
544 */
SetLength(uint16_t aLength)545 void SetLength(uint16_t aLength)
546 {
547 Tlv::SetLength(kExtendedLength);
548 mLength = HostSwap16(aLength);
549 }
550
551 private:
552 uint16_t mLength;
553 } OT_TOOL_PACKED_END;
554
555 /**
556 * This template method casts a `Tlv` pointer to a given subclass `TlvType` pointer.
557 *
558 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `Tlv`.
559 *
560 * @param[in] aTlv A pointer to a `Tlv` to convert/cast to a `TlvType`.
561 *
562 * @returns A `TlvType` pointer to `aTlv`.
563 *
564 */
As(Tlv * aTlv)565 template <class TlvType> TlvType *As(Tlv *aTlv) { return static_cast<TlvType *>(aTlv); }
566
567 /**
568 * This template method casts a `Tlv` pointer to a given subclass `TlvType` pointer.
569 *
570 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `Tlv`.
571 *
572 * @param[in] aTlv A pointer to a `Tlv` to convert/cast to a `TlvType`.
573 *
574 * @returns A `TlvType` pointer to `aTlv`.
575 *
576 */
As(const Tlv * aTlv)577 template <class TlvType> const TlvType *As(const Tlv *aTlv) { return static_cast<const TlvType *>(aTlv); }
578
579 /**
580 * This template method casts a `Tlv` reference to a given subclass `TlvType` reference.
581 *
582 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `Tlv`.
583 *
584 * @param[in] aTlv A reference to a `Tlv` to convert/cast to a `TlvType`.
585 *
586 * @returns A `TlvType` reference to `aTlv`.
587 *
588 */
As(Tlv & aTlv)589 template <class TlvType> TlvType &As(Tlv &aTlv) { return static_cast<TlvType &>(aTlv); }
590
591 /**
592 * This template method casts a `Tlv` reference to a given subclass `TlvType` reference.
593 *
594 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `Tlv`.
595 *
596 * @param[in] aTlv A reference to a `Tlv` to convert/cast to a `TlvType`.
597 *
598 * @returns A `TlvType` reference to `aTlv`.
599 *
600 */
As(const Tlv & aTlv)601 template <class TlvType> const TlvType &As(const Tlv &aTlv) { return static_cast<const TlvType &>(aTlv); }
602
603 /**
604 * This class defines constants for a TLV.
605 *
606 * @tparam kTlvTypeValue The TLV Type value.
607 *
608 */
609 template <uint8_t kTlvTypeValue> class TlvInfo
610 {
611 public:
612 static constexpr uint8_t kType = kTlvTypeValue; ///< The TLV Type value.
613 };
614
615 /**
616 * This class defines constants and types for a simple TLV with an unsigned int value type.
617 *
618 * This class and its sub-classes are intended to be used as the template type in `Tlv::Append<UintTlvType>()`, and
619 * the related `Tlv::Find<UintTlvType>()` and `Tlv::Read<UintTlvType>()`.
620 *
621 * @tparam kTlvTypeValue The TLV Type value.
622 * @tparam UintType The TLV Value's type (must be an unsigned int, i.e. uint8_t, uint16_t, or uint32_t).
623 *
624 */
625 template <uint8_t kTlvTypeValue, typename UintType> class UintTlvInfo : public TlvInfo<kTlvTypeValue>
626 {
627 public:
628 static_assert(TypeTraits::IsSame<UintType, uint8_t>::kValue || TypeTraits::IsSame<UintType, uint16_t>::kValue ||
629 TypeTraits::IsSame<UintType, uint32_t>::kValue,
630 "UintTlv must be used used with unsigned int value type");
631
632 typedef UintType UintValueType; ///< The TLV Value unsigned int type.
633 };
634
635 /**
636 * This class defines constants and types for a simple TLV with a single value.
637 *
638 * This class and its sub-classes are intended to be used as the template type in `Tlv::Append<SimpleTlvType>()`,
639 * and the related `Tlv::Find<SimpleTlvType>()` and `Tlv::Read<SimpleTlvType>()`.
640 *
641 * @tparam kTlvTypeValue The TLV Type value.
642 * @tparam TlvValueType The TLV Value's type (must not be an integral type).
643 *
644 */
645 template <uint8_t kTlvTypeValue, typename TlvValueType> class SimpleTlvInfo : public TlvInfo<kTlvTypeValue>
646 {
647 public:
648 static_assert(!TypeTraits::IsPointer<TlvValueType>::kValue, "TlvValueType must not be a pointer");
649 static_assert(!TypeTraits::IsSame<TlvValueType, uint8_t>::kValue, "SimpleTlv must not use int value type");
650 static_assert(!TypeTraits::IsSame<TlvValueType, uint16_t>::kValue, "SimpleTlv must not use int value type");
651 static_assert(!TypeTraits::IsSame<TlvValueType, uint32_t>::kValue, "SimpleTlv must not use int value type");
652 static_assert(!TypeTraits::IsSame<TlvValueType, int8_t>::kValue, "SimpleTlv must not use int value type");
653 static_assert(!TypeTraits::IsSame<TlvValueType, int16_t>::kValue, "SimpleTlv must not use int value type");
654 static_assert(!TypeTraits::IsSame<TlvValueType, int32_t>::kValue, "SimpleTlv must not use int value type");
655
656 typedef TlvValueType ValueType; ///< The TLV Value type.
657 };
658
659 /**
660 * This class defines constants and types for a simple TLV with a UTF-8 string value.
661 *
662 * This class and its sub-classes are intended to be used as the template type in `Tlv::Append<StringTlvType>()`,
663 * and the related `Tlv::Find<StringTlvType>()` and `Tlv::Read<StringTlvType>()`.
664 *
665 * @tparam kTlvTypeValue The TLV Type value.
666 * @tparam kTlvMaxValueLength The maximum allowed string length (as TLV value).
667 *
668 */
669 template <uint8_t kTlvTypeValue, uint8_t kTlvMaxValueLength> class StringTlvInfo : public TlvInfo<kTlvTypeValue>
670 {
671 public:
672 static constexpr uint8_t kMaxStringLength = kTlvMaxValueLength; ///< Maximum string length.
673
674 typedef char StringType[kMaxStringLength + 1]; ///< String buffer for TLV value.
675 };
676
677 } // namespace ot
678
679 #endif // TLVS_HPP_
680