blob: 26336ff461a27bdcba0f1a091c2bf195f7b243e0 [file] [log] [blame]
Eric Newberry261dbc22015-07-22 23:18:18 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Teng Liang02960742017-10-24 00:36:45 -07002/*
Teng Liang5b323d12018-01-31 18:50:45 -07003 * Copyright (c) 2013-2018 Regents of the University of California.
Eric Newberry261dbc22015-07-22 23:18:18 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
Alexander Afanasyeve3874232017-03-26 16:58:59 -050022#ifndef NDN_CXX_LP_FIELD_DECL_HPP
23#define NDN_CXX_LP_FIELD_DECL_HPP
Eric Newberry261dbc22015-07-22 23:18:18 -070024
Teng Liang02960742017-10-24 00:36:45 -070025#include "empty-value.hpp"
Alexander Afanasyeve3874232017-03-26 16:58:59 -050026#include "field.hpp"
Junxiao Shi974b81a2018-04-21 01:37:03 +000027#include "sequence.hpp"
Alexander Afanasyeve3874232017-03-26 16:58:59 -050028#include "tlv.hpp"
Eric Newberry261dbc22015-07-22 23:18:18 -070029
Alexander Afanasyeve3874232017-03-26 16:58:59 -050030#include "../encoding/block-helpers.hpp"
31#include "../util/concepts.hpp"
Eric Newberry261dbc22015-07-22 23:18:18 -070032#include <boost/concept/requires.hpp>
33
34namespace ndn {
35namespace lp {
Eric Newberry261dbc22015-07-22 23:18:18 -070036
Junxiao Shi974b81a2018-04-21 01:37:03 +000037/** \brief Indicate a uint64_t field shall be decoded and encoded as a non-negative integer.
38 */
39struct NonNegativeIntegerTag;
40
Eric Newberry261dbc22015-07-22 23:18:18 -070041template<typename TlvType, typename T>
42struct DecodeHelper
43{
44 static
45 BOOST_CONCEPT_REQUIRES(((WireDecodable<T>)), (T))
46 decode(const Block& wire)
47 {
Eric Newberry261dbc22015-07-22 23:18:18 -070048 T type;
49 type.wireDecode(wire);
50 return type;
51 }
52};
53
54template<typename TlvType>
Teng Liang02960742017-10-24 00:36:45 -070055struct DecodeHelper<TlvType, EmptyValue>
56{
57 static EmptyValue
58 decode(const Block& wire)
59 {
60 if (wire.value_size() != 0) {
61 BOOST_THROW_EXCEPTION(ndn::tlv::Error("NDNLP field of TLV-TYPE " + to_string(wire.type()) +
Junxiao Shi974b81a2018-04-21 01:37:03 +000062 " must be empty"));
Teng Liang02960742017-10-24 00:36:45 -070063 }
64
65 return EmptyValue{};
66 }
67};
68
69template<typename TlvType>
Junxiao Shi974b81a2018-04-21 01:37:03 +000070struct DecodeHelper<TlvType, NonNegativeIntegerTag>
71{
72 static uint64_t
73 decode(const Block& wire)
74 {
75 return readNonNegativeInteger(wire);
76 }
77};
78
79template<typename TlvType>
Eric Newberry261dbc22015-07-22 23:18:18 -070080struct DecodeHelper<TlvType, uint64_t>
81{
82 static uint64_t
83 decode(const Block& wire)
84 {
Junxiao Shi974b81a2018-04-21 01:37:03 +000085 // NDNLPv2 spec defines sequence number fields to be encoded as a fixed-width unsigned integer,
86 // but previous versions of ndn-cxx encode it as a NonNegativeInteger, so we decode it as such
87 // for backwards compatibility. In a future version, the decoder will be changed to accept
88 // 8-byte big endian only, to allow faster decoding.
Eric Newberry261dbc22015-07-22 23:18:18 -070089 return readNonNegativeInteger(wire);
90 }
91};
92
93template<typename TlvType>
94struct DecodeHelper<TlvType, std::pair<Buffer::const_iterator, Buffer::const_iterator>>
95{
96 static std::pair<Buffer::const_iterator, Buffer::const_iterator>
97 decode(const Block& wire)
98 {
Eric Newberry261dbc22015-07-22 23:18:18 -070099 if (wire.value_size() == 0) {
Teng Liang02960742017-10-24 00:36:45 -0700100 BOOST_THROW_EXCEPTION(ndn::tlv::Error("NDNLP field of TLV-TYPE " + to_string(wire.type()) +
Junxiao Shi974b81a2018-04-21 01:37:03 +0000101 " cannot be empty"));
Eric Newberry261dbc22015-07-22 23:18:18 -0700102 }
103
104 return std::make_pair(wire.value_begin(), wire.value_end());
105 }
106};
107
108template<typename encoding::Tag TAG, typename TlvType, typename T>
109struct EncodeHelper
110{
111 static
Teng Liang5b323d12018-01-31 18:50:45 -0700112 BOOST_CONCEPT_REQUIRES(((WireEncodableWithEncodingBuffer<T>)), (size_t))
Eric Newberry261dbc22015-07-22 23:18:18 -0700113 encode(EncodingImpl<TAG>& encoder, const T& value)
114 {
115 return value.wireEncode(encoder);
116 }
117};
118
119template<typename encoding::Tag TAG, typename TlvType>
Teng Liang02960742017-10-24 00:36:45 -0700120struct EncodeHelper<TAG, TlvType, EmptyValue>
121{
122 static size_t
123 encode(EncodingImpl<TAG>& encoder, const EmptyValue value)
124 {
125 size_t length = 0;
126 length += encoder.prependVarNumber(0);
127 length += encoder.prependVarNumber(TlvType::value);
128 return length;
129 }
130};
131
132template<typename encoding::Tag TAG, typename TlvType>
Junxiao Shi974b81a2018-04-21 01:37:03 +0000133struct EncodeHelper<TAG, TlvType, NonNegativeIntegerTag>
134{
135 static size_t
136 encode(EncodingImpl<TAG>& encoder, uint64_t value)
137 {
138 return prependNonNegativeIntegerBlock(encoder, TlvType::value, value);
139 }
140};
141
142template<typename encoding::Tag TAG, typename TlvType>
Eric Newberry261dbc22015-07-22 23:18:18 -0700143struct EncodeHelper<TAG, TlvType, uint64_t>
144{
145 static size_t
Junxiao Shi974b81a2018-04-21 01:37:03 +0000146 encode(EncodingImpl<TAG>& encoder, uint64_t value)
Eric Newberry261dbc22015-07-22 23:18:18 -0700147 {
Junxiao Shi974b81a2018-04-21 01:37:03 +0000148 uint64_t be = htobe64(value);
149 const uint8_t* buf = reinterpret_cast<const uint8_t*>(&be);
150 return encoder.prependByteArrayBlock(TlvType::value, buf, sizeof(be));
Eric Newberry261dbc22015-07-22 23:18:18 -0700151 }
152};
153
154template<typename encoding::Tag TAG, typename TlvType>
155struct EncodeHelper<TAG, TlvType, std::pair<Buffer::const_iterator, Buffer::const_iterator>>
156{
157 static size_t
158 encode(EncodingImpl<TAG>& encoder, const std::pair<Buffer::const_iterator, Buffer::const_iterator>& value)
159 {
160 size_t length = 0;
161 length += encoder.prependRange(value.first, value.second);
162 length += encoder.prependVarNumber(length);
163 length += encoder.prependVarNumber(TlvType::value);
164 return length;
165 }
166};
167
Junxiao Shi974b81a2018-04-21 01:37:03 +0000168/** \brief Declare a field.
169 * \tparam LOCATION a tag that indicates where the field is in an LpPacket.
170 * \tparam VALUE type of field value.
171 * \tparam TYPE TLV-TYPE number of the field.
172 * \tparam REPEATABLE whether the field is repeatable.
173 * \tparam DECODER_TAG selects a specialization of DecodeHelper.
174 * \tparam ENCODER_TAG selects a specialization of EncodeHelper.
175 */
176template<typename LOCATION, typename VALUE, uint64_t TYPE, bool REPEATABLE = false,
177 typename DECODER_TAG = VALUE, typename ENCODER_TAG = VALUE>
Eric Newberry261dbc22015-07-22 23:18:18 -0700178class FieldDecl
179{
180public:
181 typedef LOCATION FieldLocation;
182 typedef VALUE ValueType;
183 typedef std::integral_constant<uint64_t, TYPE> TlvType;
184 typedef std::integral_constant<bool, REPEATABLE> IsRepeatable;
185
Junxiao Shi974b81a2018-04-21 01:37:03 +0000186 /** \brief Decode a field.
187 * \param wire an element with top-level TLV-TYPE \c TlvType::value.
188 * \return value of the field.
189 * \throw ndn::tlv::Error decode failure.
Eric Newberry83872fd2015-08-06 17:01:24 -0700190 */
Eric Newberry261dbc22015-07-22 23:18:18 -0700191 static ValueType
192 decode(const Block& wire)
193 {
Eric Newberry83872fd2015-08-06 17:01:24 -0700194 if (wire.type() != TlvType::value) {
Junxiao Shi974b81a2018-04-21 01:37:03 +0000195 BOOST_THROW_EXCEPTION(ndn::tlv::Error("Unexpected TLV-TYPE " + to_string(wire.type())));
Eric Newberry83872fd2015-08-06 17:01:24 -0700196 }
197
Junxiao Shi974b81a2018-04-21 01:37:03 +0000198 return DecodeHelper<TlvType, DECODER_TAG>::decode(wire);
Eric Newberry261dbc22015-07-22 23:18:18 -0700199 }
200
Junxiao Shi974b81a2018-04-21 01:37:03 +0000201 /** \brief Encode a field and prepend to \p encoder.
202 * \param encoder a buffer encoder or estimator.
203 * \param value value of the field.
Eric Newberry83872fd2015-08-06 17:01:24 -0700204 */
Junxiao Shi974b81a2018-04-21 01:37:03 +0000205 template<typename encoding::Tag TAG>
Eric Newberry261dbc22015-07-22 23:18:18 -0700206 static size_t
Junxiao Shi974b81a2018-04-21 01:37:03 +0000207 encode(EncodingImpl<TAG>& encoder, const ValueType& value)
Eric Newberry261dbc22015-07-22 23:18:18 -0700208 {
Junxiao Shi974b81a2018-04-21 01:37:03 +0000209 return EncodeHelper<TAG, TlvType, ENCODER_TAG>::encode(encoder, value);
Eric Newberry261dbc22015-07-22 23:18:18 -0700210 }
211};
212
Eric Newberry261dbc22015-07-22 23:18:18 -0700213} // namespace lp
Junxiao Shi09bcab52016-07-18 02:43:34 +0000214} // namespace ndn
Eric Newberry261dbc22015-07-22 23:18:18 -0700215
Alexander Afanasyeve3874232017-03-26 16:58:59 -0500216#endif // NDN_CXX_LP_FIELD_DECL_HPP