interest: Correcting encoding/decoding of Nonce field

Nonce field is now encoded as 4-byte uint8_t value, as defined by
NDN-TLV spec.  In addition to that, setNonce will not reset
wireEncoding, rather than just modify the existing wire encoding, if it
is already exists.

Change-Id: Ibec3737ccfba70fec5c0531487782a46fbc5600a
Refs: #1600
diff --git a/src/encoding/encoding-buffer.hpp b/src/encoding/encoding-buffer.hpp
index b3f8916..d3fa3ac 100644
--- a/src/encoding/encoding-buffer.hpp
+++ b/src/encoding/encoding-buffer.hpp
@@ -131,6 +131,9 @@
   prependVarNumber(uint64_t varNumber);
 
   inline size_t
+  prependBlock(const Block& block);
+
+  inline size_t
   appendByte(uint8_t value);
 
   inline size_t
@@ -191,6 +194,9 @@
   prependVarNumber(uint64_t varNumber);
 
   inline size_t
+  prependBlock(const Block& block);
+
+  inline size_t
   appendByte(uint8_t value);
 
   inline size_t
@@ -203,6 +209,66 @@
   appendVarNumber(uint64_t varNumber);
 };
 
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+/// helper methods
+
+template<bool P>
+inline size_t
+prependNonNegativeIntegerBlock(EncodingImpl<P>& encoder, uint32_t type, uint64_t number)
+{
+  size_t valueLength = encoder.prependNonNegativeInteger(number);
+  size_t totalLength = valueLength;
+  totalLength += encoder.prependVarNumber(valueLength);
+  totalLength += encoder.prependVarNumber(type);
+
+  return totalLength;
+}
+
+template<bool P>
+inline size_t
+prependByteArrayBlock(EncodingImpl<P>& encoder, uint32_t type,
+                      const uint8_t* array, size_t arraySize)
+{
+  size_t valueLength = encoder.prependByteArray(array, arraySize);
+  size_t totalLength = valueLength;
+  totalLength += encoder.prependVarNumber(valueLength);
+  totalLength += encoder.prependVarNumber(type);
+
+  return totalLength;
+}
+
+template<bool P>
+inline size_t
+prependBooleanBlock(EncodingImpl<P>& encoder, uint32_t type)
+{
+  size_t totalLength = encoder.prependVarNumber(0);
+  totalLength += encoder.prependVarNumber(type);
+
+  return totalLength;
+}
+
+
+template<bool P, class U>
+inline size_t
+prependNestedBlock(EncodingImpl<P>& encoder, uint32_t type, const U& nestedBlock)
+{
+  size_t valueLength = nestedBlock.wireEncode(encoder);
+  size_t totalLength = valueLength;
+  totalLength += encoder.prependVarNumber(valueLength);
+  totalLength += encoder.prependVarNumber(type);
+
+  return totalLength;
+}
+
+template<bool P>
+inline size_t
+prependBlock(EncodingImpl<P>& encoder, const Block& block)
+{
+  return encoder.prependByteArray(block.wire(), block.size());
+}
 
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
@@ -415,6 +481,28 @@
   }
 }
 
+inline size_t
+EncodingImpl<encoding::Buffer>::prependBlock(const Block& block)
+{
+  if (block.hasWire()) {
+    return prependByteArray(block.wire(), block.size());
+  }
+  else {
+    return prependByteArrayBlock(*this, block.type(), block.value(), block.value_size());
+  }
+}
+
+inline size_t
+EncodingImpl<encoding::Estimator>::prependBlock(const Block& block)
+{
+  if (block.hasWire()) {
+    return block.size();
+  }
+  else {
+    return prependByteArrayBlock(*this, block.type(), block.value(), block.value_size());
+  }
+}
+
 /////////////////////////////////////////////////////////
 // Append to the back of the buffer. Resize if needed. //
 /////////////////////////////////////////////////////////
@@ -512,64 +600,6 @@
   return prependVarNumber(varNumber);
 }
 
-/// helper methods
-
-template<bool P>
-inline size_t
-prependNonNegativeIntegerBlock(EncodingImpl<P>& encoder, uint32_t type, uint64_t number)
-{
-  size_t valueLength = encoder.prependNonNegativeInteger(number);
-  size_t totalLength = valueLength;
-  totalLength += encoder.prependVarNumber(valueLength);
-  totalLength += encoder.prependVarNumber(type);
-
-  return totalLength;
-}
-
-template<bool P>
-inline size_t
-prependByteArrayBlock(EncodingImpl<P>& encoder, uint32_t type,
-                      const uint8_t* array, size_t arraySize)
-{
-  size_t valueLength = encoder.prependByteArray(array, arraySize);
-  size_t totalLength = valueLength;
-  totalLength += encoder.prependVarNumber(valueLength);
-  totalLength += encoder.prependVarNumber(type);
-
-  return totalLength;
-}
-
-template<bool P>
-inline size_t
-prependBooleanBlock(EncodingImpl<P>& encoder, uint32_t type)
-{
-  size_t totalLength = encoder.prependVarNumber(0);
-  totalLength += encoder.prependVarNumber(type);
-
-  return totalLength;
-}
-
-
-template<bool P, class U>
-inline size_t
-prependNestedBlock(EncodingImpl<P>& encoder, uint32_t type, const U& nestedBlock)
-{
-  size_t valueLength = nestedBlock.wireEncode(encoder);
-  size_t totalLength = valueLength;
-  totalLength += encoder.prependVarNumber(valueLength);
-  totalLength += encoder.prependVarNumber(type);
-
-  return totalLength;
-}
-
-template<bool P>
-inline size_t
-prependBlock(EncodingImpl<P>& encoder, const Block& block)
-{
-  return encoder.prependByteArray(block.wire(), block.size());
-}
-
-
 } // ndn
 
 #endif // NDN_ENCODING_ENCODING_BUFFER_HPP
diff --git a/src/interest.cpp b/src/interest.cpp
index cd3271e..9e5b129 100644
--- a/src/interest.cpp
+++ b/src/interest.cpp
@@ -29,15 +29,34 @@
 
 namespace ndn {
 
-const uint32_t&
+uint32_t
 Interest::getNonce() const
 {
-  if (m_nonce == 0)
-    m_nonce = random::generateWord32();
+  if (!m_nonce.hasWire())
+    const_cast<Interest*>(this)->setNonce(random::generateWord32());
 
-  return m_nonce;
+  if (m_nonce.value_size() == sizeof(uint32_t))
+    return *reinterpret_cast<const uint32_t*>(m_nonce.value());
+  else {
+    // for compatibility reasons.  Should be removed eventually
+    return readNonNegativeInteger(m_nonce);
+  }
 }
 
+Interest&
+Interest::setNonce(uint32_t nonce)
+{
+  if (m_wire.hasWire() && m_nonce.value_size() == sizeof(uint32_t)) {
+    std::memcpy(const_cast<uint8_t*>(m_nonce.value()), &nonce, sizeof(nonce));
+  }
+  else {
+    m_nonce = dataBlock(Tlv::Nonce,
+                        reinterpret_cast<const uint8_t*>(&nonce),
+                        sizeof(nonce));
+    m_wire.reset();
+  }
+  return *this;
+}
 
 bool
 Interest::matchesName(const Name& name) const
@@ -122,7 +141,7 @@
     delim = '&';
   }
 
-  if (interest.getNonce() > 0) {
+  if (interest.hasNonce()) {
     os << delim << "ndn.Nonce=" << interest.getNonce();
     delim = '&';
   }
diff --git a/src/interest.hpp b/src/interest.hpp
index d949950..138ea7c 100644
--- a/src/interest.hpp
+++ b/src/interest.hpp
@@ -54,8 +54,7 @@
    * Otherwise, Interest::shared_from_this() will throw an exception.
    */
   Interest()
-    : m_nonce(0)
-    , m_scope(-1)
+    : m_scope(-1)
     , m_interestLifetime(time::milliseconds::min())
   {
   }
@@ -74,7 +73,6 @@
    */
   Interest(const Name& name)
     : m_name(name)
-    , m_nonce(0)
     , m_scope(-1)
     , m_interestLifetime(time::milliseconds::min())
   {
@@ -95,7 +93,6 @@
    */
   Interest(const Name& name, const time::milliseconds& interestLifetime)
     : m_name(name)
-    , m_nonce(0)
     , m_scope(-1)
     , m_interestLifetime(interestLifetime)
   {
@@ -118,10 +115,12 @@
            uint32_t nonce = 0)
     : m_name(name)
     , m_selectors(selectors)
-    , m_nonce(nonce)
     , m_scope(scope)
     , m_interestLifetime(interestLifetime)
   {
+    if (nonce > 0) {
+      setNonce(nonce);
+    }
   }
 
   /**
@@ -153,10 +152,12 @@
                     .setExclude(exclude)
                     .setChildSelector(childSelector)
                     .setMustBeFresh(mustBeFresh))
-    , m_nonce(nonce)
     , m_scope(scope)
     , m_interestLifetime(interestLifetime)
   {
+    if (nonce > 0) {
+      setNonce(nonce);
+    }
   }
 
   /**
@@ -312,17 +313,27 @@
    *
    * Const reference needed for C decoding
    */
-  const uint32_t&
+  uint32_t
   getNonce() const;
 
-  Interest&
-  setNonce(uint32_t nonce)
+  /**
+   * @brief Check if Nonce set
+   */
+  bool
+  hasNonce() const
   {
-    m_nonce = nonce;
-    m_wire.reset();
-    return *this;
+    return m_nonce.hasWire();
   }
 
+  /**
+   * @brief Set Interest's nonce
+   *
+   * Note that if wire format already exists, this call simply replaces nonce in the
+   * existing wire format, without resetting and recreating it.
+   */
+  Interest&
+  setNonce(uint32_t nonce);
+
   //
 
   nfd::LocalControlHeader&
@@ -489,7 +500,7 @@
 private:
   Name m_name;
   Selectors m_selectors;
-  mutable uint32_t m_nonce;
+  mutable Block m_nonce;
   int m_scope;
   time::milliseconds m_interestLifetime;
 
@@ -547,7 +558,8 @@
     }
 
   // Nonce
-  totalLength += prependNonNegativeIntegerBlock(block, Tlv::Nonce, getNonce());
+  getNonce(); // to ensure that Nonce is properly set
+  totalLength += block.prependBlock(m_nonce);
 
   // Selectors
   if (!getSelectors().empty())
@@ -558,8 +570,8 @@
   // Name
   totalLength += getName().wireEncode(block);
 
-  totalLength += block.prependVarNumber (totalLength);
-  totalLength += block.prependVarNumber (Tlv::Interest);
+  totalLength += block.prependVarNumber(totalLength);
+  totalLength += block.prependVarNumber(Tlv::Interest);
   return totalLength;
 }
 
@@ -575,7 +587,9 @@
   EncodingBuffer buffer(estimatedSize, 0);
   wireEncode(buffer);
 
-  m_wire = buffer.block();
+  // to ensure that Nonce block points to the right memory location
+  const_cast<Interest*>(this)->wireDecode(buffer.block());
+
   return m_wire;
 }
 
@@ -608,13 +622,7 @@
     m_selectors = Selectors();
 
   // Nonce
-  val = m_wire.find(Tlv::Nonce);
-  if (val != m_wire.elements_end())
-    {
-      m_nonce = readNonNegativeInteger(*val);
-    }
-  else
-    m_nonce = 0;
+  m_nonce = m_wire.get(Tlv::Nonce);
 
   // Scope
   val = m_wire.find(Tlv::Scope);