encoding: in Block::blockFromValue(), fail early if TLV length is zero

Also add a test for the boost::asio::const_buffer conversion operator

Change-Id: I312e8cba21ee1e6c29f3fb90485fa2932a2e5fb2
diff --git a/ndn-cxx/encoding/block.cpp b/ndn-cxx/encoding/block.cpp
index 8314c7d..2c40fdb 100644
--- a/ndn-cxx/encoding/block.cpp
+++ b/ndn-cxx/encoding/block.cpp
@@ -313,8 +313,9 @@
 Block
 Block::blockFromValue() const
 {
-  if (!hasValue())
-    NDN_THROW(Error("Block has no TLV-VALUE"));
+  if (value_size() == 0) {
+    NDN_THROW(Error("Cannot construct block from empty TLV-VALUE"));
+  }
 
   return Block(*this, m_valueBegin, m_valueEnd, true);
 }
@@ -327,12 +328,11 @@
   if (!m_elements.empty() || value_size() == 0)
     return;
 
-  Buffer::const_iterator begin = value_begin();
-  Buffer::const_iterator end = value_end();
+  auto begin = value_begin();
+  auto end = value_end();
 
   while (begin != end) {
-    Buffer::const_iterator pos = begin;
-
+    auto pos = begin;
     uint32_t type = tlv::readType(pos, end);
     uint64_t length = tlv::readVarNumber(pos, end);
     if (length > static_cast<uint64_t>(end - pos)) {
@@ -342,7 +342,7 @@
     }
     // pos now points to TLV-VALUE of sub element
 
-    Buffer::const_iterator subEnd = pos + length;
+    auto subEnd = pos + length;
     m_elements.emplace_back(m_buffer, type, begin, subEnd, pos, subEnd);
 
     begin = subEnd;
@@ -471,7 +471,7 @@
 
 Block::operator boost::asio::const_buffer() const
 {
-  return boost::asio::const_buffer(wire(), size());
+  return {wire(), size()};
 }
 
 bool
diff --git a/tests/unit/encoding/block.t.cpp b/tests/unit/encoding/block.t.cpp
index fda45ca..b6a841b 100644
--- a/tests/unit/encoding/block.t.cpp
+++ b/tests/unit/encoding/block.t.cpp
@@ -24,6 +24,7 @@
 
 #include "tests/boost-test.hpp"
 
+#include <boost/asio/buffer.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/test/data/test_case.hpp>
 
@@ -419,6 +420,28 @@
 
 BOOST_AUTO_TEST_SUITE_END() // Construction
 
+BOOST_AUTO_TEST_CASE(BlockFromValue)
+{
+  Block b1(301);
+  BOOST_CHECK_EXCEPTION(b1.blockFromValue(), Block::Error, [] (const auto& e) {
+    return e.what() == "Cannot construct block from empty TLV-VALUE"s;
+  });
+
+  Block b2(302, make_shared<Buffer>());
+  BOOST_CHECK_EXCEPTION(b2.blockFromValue(), Block::Error, [] (const auto& e) {
+    return e.what() == "Cannot construct block from empty TLV-VALUE"s;
+  });
+
+  b1.encode();
+  Block b3(303, b1);
+  b3.encode();
+  Block nested = b3.blockFromValue();
+  BOOST_CHECK_EQUAL(nested.type(), 301);
+  BOOST_CHECK_EQUAL(nested.size(), 4);
+  BOOST_CHECK_EQUAL(nested.value_size(), 0);
+  BOOST_CHECK(nested == b1);
+}
+
 BOOST_AUTO_TEST_SUITE(SubElements)
 
 BOOST_AUTO_TEST_CASE(Parse)
@@ -600,6 +623,14 @@
 
 BOOST_AUTO_TEST_SUITE_END() // SubElements
 
+BOOST_AUTO_TEST_CASE(ToAsioConstBuffer)
+{
+  Block block = "0101A0"_block;
+  boost::asio::const_buffer buffer(block);
+  BOOST_CHECK_EQUAL(boost::asio::buffer_cast<const uint8_t*>(buffer), block.wire());
+  BOOST_CHECK_EQUAL(boost::asio::buffer_size(buffer), block.size());
+}
+
 BOOST_AUTO_TEST_CASE(Equality)
 {
   const uint8_t one[] = {0x08, 0x00};