• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 in a message at a given offset expecting a minimum length for the value.
179      *
180      * @param[in]   aMessage    The message to read from.
181      * @param[in]   aOffset     The offset into the message pointing to the start of the TLV.
182      * @param[out]  aValue      A buffer to output the TLV's value, must contain (at least) @p aMinLength bytes.
183      * @param[in]   aMinLength  The minimum expected length of TLV and number of bytes to copy into @p aValue buffer.
184      *
185      * @retval kErrorNone        Successfully read the TLV and copied @p aMinLength into @p aValue.
186      * @retval kErrorParse       The TLV was not well-formed and could not be parsed.
187      *
188      */
189     static Error ReadTlv(const Message &aMessage, uint16_t aOffset, void *aValue, uint8_t aMinLength);
190 
191     /**
192      * This static method reads a simple TLV with a single non-integral value in a message at a given offset.
193      *
194      * @tparam      SimpleTlvType   The simple TLV type to read (must be a sub-class of `SimpleTlvInfo`).
195      *
196      * @param[in]   aMessage        The message to read from.
197      * @param[in]   aOffset         The offset into the message pointing to the start of the TLV.
198      * @param[out]  aValue          A reference to the value object to output the read value.
199      *
200      * @retval kErrorNone        Successfully read the TLV and updated the @p aValue.
201      * @retval kErrorParse       The TLV was not well-formed and could not be parsed.
202      *
203      */
204     template <typename SimpleTlvType>
Read(const Message & aMessage,uint16_t aOffset,typename SimpleTlvType::ValueType & aValue)205     static Error Read(const Message &aMessage, uint16_t aOffset, typename SimpleTlvType::ValueType &aValue)
206     {
207         return ReadTlv(aMessage, aOffset, &aValue, sizeof(aValue));
208     }
209 
210     /**
211      * This static method reads a simple TLV with a single integral value in a message at a given offset.
212      *
213      * @tparam      UintTlvType     The simple TLV type to read (must be a sub-class of `UintTlvInfo`).
214      *
215      * @param[in]   aMessage        The message to read from.
216      * @param[in]   aOffset         The offset into the message pointing to the start of the TLV.
217      * @param[out]  aValue          A reference to an unsigned int to output the read value.
218      *
219      * @retval kErrorNone        Successfully read the TLV and updated the @p aValue.
220      * @retval kErrorParse       The TLV was not well-formed and could not be parsed.
221      *
222      */
223     template <typename UintTlvType>
Read(const Message & aMessage,uint16_t aOffset,typename UintTlvType::UintValueType & aValue)224     static Error Read(const Message &aMessage, uint16_t aOffset, typename UintTlvType::UintValueType &aValue)
225     {
226         return ReadUintTlv(aMessage, aOffset, aValue);
227     }
228 
229     /**
230      * This static method searches for and reads a requested TLV out of a given message.
231      *
232      * This method can be used independent of whether the read TLV (from message) is an Extended TLV or not.
233      *
234      * @param[in]   aMessage    A reference to the message.
235      * @param[in]   aType       The Type value to search for.
236      * @param[in]   aMaxSize    Maximum number of bytes to read.
237      * @param[out]  aTlv        A reference to the TLV that will be copied to.
238      *
239      * @retval kErrorNone       Successfully copied the TLV.
240      * @retval kErrorNotFound   Could not find the TLV with Type @p aType.
241      *
242      */
243     static Error FindTlv(const Message &aMessage, uint8_t aType, uint16_t aMaxSize, Tlv &aTlv);
244 
245     /**
246      * This static method searches for and reads a requested TLV out of a given message.
247      *
248      * This method can be used independent of whether the read TLV (from message) is an Extended TLV or not.
249      *
250      * @tparam      TlvType     The TlvType to search for (must be a sub-class of `Tlv`).
251      *
252      * @param[in]   aMessage    A reference to the message.
253      * @param[out]  aTlv        A reference to the TLV that will be copied to.
254      *
255      * @retval kErrorNone       Successfully copied the TLV.
256      * @retval kErrorNotFound   Could not find the TLV with Type @p aType.
257      *
258      */
FindTlv(const Message & aMessage,TlvType & aTlv)259     template <typename TlvType> static Error FindTlv(const Message &aMessage, TlvType &aTlv)
260     {
261         return FindTlv(aMessage, TlvType::kType, sizeof(TlvType), aTlv);
262     }
263 
264     /**
265      * This static method obtains the offset of a TLV within @p aMessage.
266      *
267      * This method can be used independent of whether the read TLV (from message) is an Extended TLV or not.
268      *
269      * @param[in]   aMessage    A reference to the message.
270      * @param[in]   aType       The Type value to search for.
271      * @param[out]  aOffset     A reference to the offset of the TLV.
272      *
273      * @retval kErrorNone       Successfully copied the TLV.
274      * @retval kErrorNotFound   Could not find the TLV with Type @p aType.
275      *
276      */
277     static Error FindTlvOffset(const Message &aMessage, uint8_t aType, uint16_t &aOffset);
278 
279     /**
280      * This static method finds the offset and length of a given TLV type.
281      *
282      * This method can be used independent of whether the read TLV (from message) is an Extended TLV or not.
283      *
284      * @param[in]   aMessage      A reference to the message.
285      * @param[in]   aType         The Type value to search for.
286      * @param[out]  aValueOffset  The offset where the value starts.
287      * @param[out]  aLength       The length of the value.
288      *
289      * @retval kErrorNone       Successfully found the TLV.
290      * @retval kErrorNotFound   Could not find the TLV with Type @p aType.
291      *
292      */
293     static Error FindTlvValueOffset(const Message &aMessage, uint8_t aType, uint16_t &aValueOffset, uint16_t &aLength);
294 
295     /**
296      * This static method searches for a TLV with a given type in a message, ensures its length is same or larger than
297      * an expected minimum value, and then reads its value into a given buffer.
298      *
299      * If the TLV length is smaller than the minimum length @p aLength, the TLV is considered invalid. In this case,
300      * this method returns `kErrorParse` and the @p aValue buffer is not updated.
301      *
302      * If the TLV length is larger than @p aLength, the TLV is considered valid, but only the first @p aLength bytes
303      * of the value are read and copied into the @p aValue buffer.
304      *
305      * @tparam       TlvType     The TLV type to find.
306      *
307      * @param[in]    aMessage    A reference to the message.
308      * @param[out]   aValue      A buffer to output the value (must contain at least @p aLength bytes).
309      * @param[in]    aLength     The expected (minimum) length of the TLV value.
310      *
311      * @retval kErrorNone       The TLV was found and read successfully. @p aValue is updated.
312      * @retval kErrorNotFound   Could not find the TLV with Type @p aType.
313      * @retval kErrorParse      TLV was found but it was not well-formed and could not be parsed.
314      *
315      */
Find(const Message & aMessage,void * aValue,uint8_t aLength)316     template <typename TlvType> static Error Find(const Message &aMessage, void *aValue, uint8_t aLength)
317     {
318         return FindTlv(aMessage, TlvType::kType, aValue, aLength);
319     }
320 
321     /**
322      * This static method searches for a simple TLV with a single non-integral value in a message, ensures its length is
323      * same or larger than the expected `ValueType` object size, and then reads its value into a value object reference.
324      *
325      * If the TLV length is smaller than the size of @p aValue, the TLV is considered invalid. In this case, this
326      * method returns `kErrorParse` and the @p aValue is not updated.
327      *
328      * If the TLV length is larger than the size of @p aValue, the TLV is considered valid, but the size of
329      * `ValueType` bytes are read and copied into the @p aValue.
330      *
331      * @tparam       SimpleTlvType   The simple TLV type to find (must be a sub-class of `SimpleTlvInfo`)
332      *
333      * @param[in]    aMessage        A reference to the message.
334      * @param[out]   aValue          A reference to the value object to output the read value.
335      *
336      * @retval kErrorNone         The TLV was found and read successfully. @p aValue is updated.
337      * @retval kErrorNotFound     Could not find the TLV with Type @p aType.
338      * @retval kErrorParse        TLV was found but it was not well-formed and could not be parsed.
339      *
340      */
341     template <typename SimpleTlvType>
Find(const Message & aMessage,typename SimpleTlvType::ValueType & aValue)342     static Error Find(const Message &aMessage, typename SimpleTlvType::ValueType &aValue)
343     {
344         return FindTlv(aMessage, SimpleTlvType::kType, &aValue, sizeof(aValue));
345     }
346 
347     /**
348      * This static method searches for a simple TLV with a single integral value in a message, and then reads its value
349      * into a given `uint` reference variable.
350      *
351      * If the TLV length is smaller than size of integral value, the TLV is considered invalid. In this case, this
352      * method returns `kErrorParse` and the @p aValue is not updated.
353      *
354      * @tparam       UintTlvType     The simple TLV type to find (must be a sub-class of `UintTlvInfo`)
355      *
356      * @param[in]    aMessage        A reference to the message.
357      * @param[out]   aValue          A reference to an unsigned int value to output the TLV's value.
358      *
359      * @retval kErrorNone         The TLV was found and read successfully. @p aValue is updated.
360      * @retval kErrorNotFound     Could not find the TLV with Type @p aType.
361      * @retval kErrorParse        TLV was found but it was not well-formed and could not be parsed.
362      *
363      */
364     template <typename UintTlvType>
Find(const Message & aMessage,typename UintTlvType::UintValueType & aValue)365     static Error Find(const Message &aMessage, typename UintTlvType::UintValueType &aValue)
366     {
367         return FindUintTlv(aMessage, UintTlvType::kType, aValue);
368     }
369 
370     /**
371      * This static method appends a TLV with a given type and value to a message.
372      *
373      * On success this method grows the message by the size of the TLV.
374      *
375      * @tparam     TlvType       The TLV type to append.
376      *
377      * @param[in]  aMessage      A reference to the message to append to.
378      * @param[in]  aValue        A buffer containing the TLV value.
379      * @param[in]  aLength       The value length (in bytes).
380      *
381      * @retval kErrorNone     Successfully appended the TLV to the message.
382      * @retval kErrorNoBufs   Insufficient available buffers to grow the message.
383      *
384      */
Append(Message & aMessage,const void * aValue,uint8_t aLength)385     template <typename TlvType> static Error Append(Message &aMessage, const void *aValue, uint8_t aLength)
386     {
387         return AppendTlv(aMessage, TlvType::kType, aValue, aLength);
388     }
389 
390     /**
391      * This static method appends a simple TLV with a single (non-integral) value to a message.
392      *
393      * On success this method grows the message by the size of the TLV.
394      *
395      * @tparam     SimpleTlvType The simple TLV type to append (must be a sub-class of `SimpleTlvInfo`)
396      *
397      * @param[in]  aMessage      A reference to the message to append to.
398      * @param[in]  aValue        A reference to the object containing TLV's value.
399      *
400      * @retval kErrorNone     Successfully appended the TLV to the message.
401      * @retval kErrorNoBufs   Insufficient available buffers to grow the message.
402      *
403      */
404     template <typename SimpleTlvType>
Append(Message & aMessage,const typename SimpleTlvType::ValueType & aValue)405     static Error Append(Message &aMessage, const typename SimpleTlvType::ValueType &aValue)
406     {
407         return AppendTlv(aMessage, SimpleTlvType::kType, &aValue, sizeof(aValue));
408     }
409 
410     /**
411      * This static method appends a simple TLV with a single integral value to a message.
412      *
413      * On success this method grows the message by the size of the TLV.
414      *
415      * @tparam     UintTlvType   The simple TLV type to append (must be a sub-class of `UintTlvInfo`)
416      *
417      * @param[in]  aMessage      A reference to the message to append to.
418      * @param[in]  aValue        An unsigned int value to use as TLV's value.
419      *
420      * @retval kErrorNone     Successfully appended the TLV to the message.
421      * @retval kErrorNoBufs   Insufficient available buffers to grow the message.
422      *
423      */
Append(Message & aMessage,typename UintTlvType::UintValueType aValue)424     template <typename UintTlvType> static Error Append(Message &aMessage, typename UintTlvType::UintValueType aValue)
425     {
426         return AppendUintTlv(aMessage, UintTlvType::kType, aValue);
427     }
428 
429 protected:
430     static const uint8_t kExtendedLength = 255; // Extended Length value.
431 
432 private:
433     static Error Find(const Message &aMessage, uint8_t aType, uint16_t *aOffset, uint16_t *aSize, bool *aIsExtendedTlv);
434     static Error FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint8_t aLength);
435     static Error AppendTlv(Message &aMessage, uint8_t aType, const void *aValue, uint8_t aLength);
436     template <typename UintType> static Error ReadUintTlv(const Message &aMessage, uint16_t aOffset, UintType &aValue);
437     template <typename UintType> static Error FindUintTlv(const Message &aMessage, uint8_t aType, UintType &aValue);
438     template <typename UintType> static Error AppendUintTlv(Message &aMessage, uint8_t aType, UintType aValue);
439 
440     uint8_t mType;
441     uint8_t mLength;
442 } OT_TOOL_PACKED_END;
443 
444 OT_TOOL_PACKED_BEGIN
445 class ExtendedTlv : public Tlv
446 {
447 public:
448     /**
449      * This method returns the Length value.
450      *
451      */
GetLength(void) const452     uint16_t GetLength(void) const { return HostSwap16(mLength); }
453 
454     /**
455      * This method sets the Length value.
456      *
457      * @param[in]  aLength  The Length value.
458      *
459      */
SetLength(uint16_t aLength)460     void SetLength(uint16_t aLength)
461     {
462         Tlv::SetLength(kExtendedLength);
463         mLength = HostSwap16(aLength);
464     }
465 
466 private:
467     uint16_t mLength;
468 } OT_TOOL_PACKED_END;
469 
470 /**
471  * This template method casts a `Tlv` pointer to a given subclass `TlvType` pointer.
472  *
473  * @tparam TlvType  The TLV type to cast into. MUST be a subclass of `Tlv`.
474  *
475  * @param[in] aTlv   A pointer to a `Tlv` to convert/cast to a `TlvType`.
476  *
477  * @returns A `TlvType` pointer to `aTlv`.
478  *
479  */
As(Tlv * aTlv)480 template <class TlvType> TlvType *As(Tlv *aTlv)
481 {
482     return static_cast<TlvType *>(aTlv);
483 }
484 
485 /**
486  * This template method casts a `Tlv` pointer to a given subclass `TlvType` pointer.
487  *
488  * @tparam TlvType  The TLV type to cast into. MUST be a subclass of `Tlv`.
489  *
490  * @param[in] aTlv   A pointer to a `Tlv` to convert/cast to a `TlvType`.
491  *
492  * @returns A `TlvType` pointer to `aTlv`.
493  *
494  */
As(const Tlv * aTlv)495 template <class TlvType> const TlvType *As(const Tlv *aTlv)
496 {
497     return static_cast<const TlvType *>(aTlv);
498 }
499 
500 /**
501  * This template method casts a `Tlv` reference to a given subclass `TlvType` reference.
502  *
503  * @tparam TlvType  The TLV type to cast into. MUST be a subclass of `Tlv`.
504  *
505  * @param[in] aTlv   A reference to a `Tlv` to convert/cast to a `TlvType`.
506  *
507  * @returns A `TlvType` reference to `aTlv`.
508  *
509  */
As(Tlv & aTlv)510 template <class TlvType> TlvType &As(Tlv &aTlv)
511 {
512     return static_cast<TlvType &>(aTlv);
513 }
514 
515 /**
516  * This template method casts a `Tlv` reference to a given subclass `TlvType` reference.
517  *
518  * @tparam TlvType  The TLV type to cast into. MUST be a subclass of `Tlv`.
519  *
520  * @param[in] aTlv   A reference to a `Tlv` to convert/cast to a `TlvType`.
521  *
522  * @returns A `TlvType` reference to `aTlv`.
523  *
524  */
As(const Tlv & aTlv)525 template <class TlvType> const TlvType &As(const Tlv &aTlv)
526 {
527     return static_cast<const TlvType &>(aTlv);
528 }
529 
530 /**
531  * This class defines constants for a TLV.
532  *
533  * @tparam kTlvTypeValue   The TLV Type value.
534  *
535  */
536 template <uint8_t kTlvTypeValue> class TlvInfo
537 {
538 public:
539     static constexpr uint8_t kType = kTlvTypeValue; ///< The TLV Type value.
540 };
541 
542 /**
543  * This class defines constants and types for a simple TLV with an unsigned int value type.
544  *
545  * This class and its sub-classes are intended to be used as the template type in `Tlv::Append<UintTlvType>()`, and
546  * the related `Tlv::Find<UintTlvType>()` and `Tlv::Read<UintTlvType>()`.
547  *
548  * @tparam kTlvTypeValue   The TLV Type value.
549  * @tparam UintType        The TLV Value's type (must be an unsigned int, i.e. uint8_t, uint16_t, or uint32_t).
550  *
551  */
552 template <uint8_t kTlvTypeValue, typename UintType> class UintTlvInfo : public TlvInfo<kTlvTypeValue>
553 {
554 public:
555     static_assert(TypeTraits::IsSame<UintType, uint8_t>::kValue || TypeTraits::IsSame<UintType, uint16_t>::kValue ||
556                       TypeTraits::IsSame<UintType, uint32_t>::kValue,
557                   "UintTlv must be used used with unsigned int value type");
558 
559     typedef UintType UintValueType; ///< The TLV Value unsigned int type.
560 };
561 
562 /**
563  * This class defines constants and types for a simple TLV with a single value.
564  *
565  * This class and its sub-classes are intended to be used as the template type in `Tlv::Append<SimpleTlvType>()`,
566  * and the related `Tlv::Find<SimpleTlvType>()` and `Tlv::Read<SimpleTlvType>()`.
567  *
568  * @tparam kTlvTypeValue   The TLV Type value.
569  * @tparam TlvValueType    The TLV Value's type (must not be an integral type).
570  *
571  */
572 template <uint8_t kTlvTypeValue, typename TlvValueType> class SimpleTlvInfo : public TlvInfo<kTlvTypeValue>
573 {
574 public:
575     static_assert(!TypeTraits::IsPointer<TlvValueType>::kValue, "TlvValueType must not be a pointer");
576     static_assert(!TypeTraits::IsSame<TlvValueType, uint8_t>::kValue, "SimpleTlv must not use int value type");
577     static_assert(!TypeTraits::IsSame<TlvValueType, uint16_t>::kValue, "SimpleTlv must not use int value type");
578     static_assert(!TypeTraits::IsSame<TlvValueType, uint32_t>::kValue, "SimpleTlv must not use int value type");
579     static_assert(!TypeTraits::IsSame<TlvValueType, int8_t>::kValue, "SimpleTlv must not use int value type");
580     static_assert(!TypeTraits::IsSame<TlvValueType, int16_t>::kValue, "SimpleTlv must not use int value type");
581     static_assert(!TypeTraits::IsSame<TlvValueType, int32_t>::kValue, "SimpleTlv must not use int value type");
582 
583     typedef TlvValueType ValueType; ///< The TLV Value type.
584 };
585 
586 } // namespace ot
587 
588 #endif // TLVS_HPP_
589