fixup decode logic for fragmented IOBufs
[folly.git] / folly / experimental / bser / Load.cpp
index 161f72a31626caf7ed6144db889398a9fa851bb9..ad390ee8a866f7405798ba076c0d50d430c62bae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2016-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "Bser.h"
-#include <folly/io/Cursor.h>
+
+#include <folly/experimental/bser/Bser.h>
+
 #include <folly/String.h>
+#include <folly/io/Cursor.h>
 
 using namespace folly;
 using folly::io::Cursor;
@@ -26,10 +28,11 @@ static dynamic parseBser(Cursor& curs);
 
 template <typename... ARGS>
 [[noreturn]] static void throwDecodeError(Cursor& curs, ARGS&&... args) {
-  throw BserDecodeError(folly::to<std::string>(std::forward<ARGS>(args)...,
-                                               " with ",
-                                               curs.length(),
-                                               " bytes remaining in cursor"));
+  throw BserDecodeError(folly::to<std::string>(
+      std::forward<ARGS>(args)...,
+      " with ",
+      curs.length(),
+      " bytes remaining in cursor"));
 }
 
 static int64_t decodeInt(Cursor& curs) {
@@ -56,25 +59,29 @@ static std::string decodeString(Cursor& curs) {
   if (len < 0) {
     throw std::range_error("string length must not be negative");
   }
-  str.reserve(len);
+  str.reserve(size_t(len));
 
-  size_t available = curs.length();
+  // peekBytes will advance over any "empty" IOBuf elements until
+  // it reaches the next one with data, so do that to obtain the
+  // true remaining length.
+  size_t available = curs.peekBytes().size();
   while (available < (size_t)len) {
     if (available == 0) {
       // Saw this case when we decodeHeader was returning the incorrect length
       // and we were splitting off too few bytes from the IOBufQueue
-      throwDecodeError(curs,
-                       "no data available while decoding a string, header was "
-                       "not decoded properly");
+      throwDecodeError(
+          curs,
+          "no data available while decoding a string, header was "
+          "not decoded properly");
     }
     str.append(reinterpret_cast<const char*>(curs.data()), available);
     curs.skipAtMost(available);
     len -= available;
-    available = curs.length();
+    available = curs.peekBytes().size();
   }
 
-  str.append(reinterpret_cast<const char*>(curs.data()), len);
-  curs.skipAtMost(len);
+  str.append(reinterpret_cast<const char*>(curs.data()), size_t(len));
+  curs.skipAtMost(size_t(len));
   return str;
 }
 
@@ -217,8 +224,8 @@ folly::dynamic parseBser(ByteRange str) {
 folly::dynamic parseBser(StringPiece str) {
   return parseBser(ByteRange((uint8_t*)str.data(), str.size()));
 }
-}
-}
+} // namespace bser
+} // namespace folly
 
 /* vim:ts=2:sw=2:et:
  */