diff --git a/lib/nghttp2_buf.h b/lib/nghttp2_buf.h
index 8977f2ea82ced255504fdf7613446866a86ba7c7..7c43606e10fbaf806a88d825a0f32322e657d6fa 100644
--- a/lib/nghttp2_buf.h
+++ b/lib/nghttp2_buf.h
@@ -73,7 +73,7 @@ typedef struct {
 
 /*
  * Initializes the |buf|. No memory is allocated in this function. Use
- * nghttp2_buf_reserve() or nghttp2_buf_reserve2() to allocate memory.
+ * nghttp2_buf_reserve() to allocate memory.
  */
 void nghttp2_buf_init(nghttp2_buf *buf);
 
diff --git a/lib/nghttp2_hd.c b/lib/nghttp2_hd.c
index 65a09a5b5de395f5fa60a79b232102900da8bbd0..c6c5b5f8e54b43381bab288667df773345a61aef 100644
--- a/lib/nghttp2_hd.c
+++ b/lib/nghttp2_hd.c
@@ -1099,30 +1099,24 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
   inflater->min_hd_table_bufsize_max = UINT32_MAX;
 
   inflater->ent_keep = NULL;
-  inflater->nv_keep = NULL;
+  inflater->nv_name_keep = NULL;
+  inflater->nv_value_keep = NULL;
 
   inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
   inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
 
-  rv = nghttp2_bufs_init3(&inflater->nvbufs, NGHTTP2_HD_MAX_NV / 8, 8, 1, 0,
-                          mem);
-
-  if (rv != 0) {
-    goto nvbufs_fail;
-  }
+  nghttp2_buf_init(&inflater->namebuf);
+  nghttp2_buf_init(&inflater->valuebuf);
 
   inflater->huffman_encoded = 0;
   inflater->index = 0;
   inflater->left = 0;
   inflater->shift = 0;
-  inflater->newnamelen = 0;
   inflater->index_required = 0;
   inflater->no_index = 0;
 
   return 0;
 
-nvbufs_fail:
-  hd_context_free(&inflater->ctx);
 fail:
   return rv;
 }
@@ -1139,8 +1133,11 @@ static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
     inflater->ent_keep = NULL;
   }
 
-  nghttp2_mem_free(mem, inflater->nv_keep);
-  inflater->nv_keep = NULL;
+  nghttp2_mem_free(mem, inflater->nv_value_keep);
+  inflater->nv_value_keep = NULL;
+
+  nghttp2_mem_free(mem, inflater->nv_name_keep);
+  inflater->nv_name_keep = NULL;
 }
 
 void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
@@ -1148,8 +1145,13 @@ void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
 }
 
 void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
+  nghttp2_mem *mem;
+
+  mem = inflater->ctx.mem;
+
   hd_inflate_keep_free(inflater);
-  nghttp2_bufs_free(&inflater->nvbufs);
+  nghttp2_buf_free(&inflater->valuebuf, mem);
+  nghttp2_buf_free(&inflater->namebuf, mem);
   hd_context_free(&inflater->ctx);
 }
 
@@ -2036,11 +2038,9 @@ static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
  *   Out of memory
  * NGHTTP2_ERR_HEADER_COMP
  *   Huffman decoding failed
- * NGHTTP2_ERR_BUFFER_ERROR
- *     Out of buffer space.
  */
 static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
-                                    nghttp2_bufs *bufs, uint8_t *in,
+                                    nghttp2_buf *buf, uint8_t *in,
                                     uint8_t *last) {
   ssize_t readlen;
   int final = 0;
@@ -2048,7 +2048,7 @@ static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
     last = in + inflater->left;
     final = 1;
   }
-  readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, bufs, in,
+  readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
                                    (size_t)(last - in), final);
 
   if (readlen < 0) {
@@ -2070,17 +2070,13 @@ static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
  *   Out of memory
  * NGHTTP2_ERR_HEADER_COMP
  *   Header decompression failed
- * NGHTTP2_ERR_BUFFER_ERROR
- *     Out of buffer space.
  */
-static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater,
-                               nghttp2_bufs *bufs, uint8_t *in, uint8_t *last) {
-  int rv;
+static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf,
+                               uint8_t *in, uint8_t *last) {
   size_t len = nghttp2_min((size_t)(last - in), inflater->left);
-  rv = nghttp2_bufs_add(bufs, in, len);
-  if (rv != 0) {
-    return rv;
-  }
+
+  buf->last = nghttp2_cpymem(buf->last, in, len);
+
   inflater->left -= len;
   return (ssize_t)len;
 }
@@ -2105,112 +2101,6 @@ static int hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
   return 0;
 }
 
-static int hd_inflate_remove_bufs(nghttp2_hd_inflater *inflater, nghttp2_nv *nv,
-                                  int value_only) {
-  ssize_t rv;
-  size_t buflen;
-  uint8_t *buf;
-  nghttp2_buf *pbuf;
-
-  if (inflater->index_required ||
-      inflater->nvbufs.head != inflater->nvbufs.cur) {
-
-    rv = nghttp2_bufs_remove(&inflater->nvbufs, &buf);
-
-    if (rv < 0) {
-      return NGHTTP2_ERR_NOMEM;
-    }
-
-    nghttp2_bufs_reset(&inflater->nvbufs);
-
-    buflen = (size_t)rv;
-
-    if (value_only) {
-      /* we don't use this value, so no need to NULL-terminate */
-      nv->name = NULL;
-      nv->namelen = 0;
-
-      nv->value = buf;
-      nv->valuelen = buflen - 1;
-    } else {
-      nv->name = buf;
-      nv->namelen = inflater->newnamelen;
-
-      nv->value = buf + nv->namelen + 1;
-      nv->valuelen = buflen - nv->namelen - 2;
-    }
-
-    return 0;
-  }
-
-  /* If we are not going to store header in header table and
-     name/value are in first chunk, we just refer them from nv,
-     instead of mallocing another memory. */
-
-  pbuf = &inflater->nvbufs.head->buf;
-
-  if (value_only) {
-    /* we don't use this value, so no need to NULL-terminate */
-    nv->name = NULL;
-    nv->namelen = 0;
-
-    nv->value = pbuf->pos;
-    nv->valuelen = nghttp2_buf_len(pbuf) - 1;
-  } else {
-    nv->name = pbuf->pos;
-    nv->namelen = inflater->newnamelen;
-
-    nv->value = pbuf->pos + nv->namelen + 1;
-    nv->valuelen = nghttp2_buf_len(pbuf) - nv->namelen - 2;
-  }
-
-  /* Resetting does not change the content of first buffer */
-  nghttp2_bufs_reset(&inflater->nvbufs);
-
-  return 0;
-}
-
-static int hd_inflate_remove_bufs_with_name(nghttp2_hd_inflater *inflater,
-                                            nghttp2_nv *nv,
-                                            nghttp2_hd_entry *ent_name) {
-#ifndef NDEBUG
-  size_t rv;
-#endif
-  size_t buflen;
-  uint8_t *buf;
-  nghttp2_mem *mem;
-
-  mem = inflater->ctx.mem;
-
-  /* Allocate buffer including name in ent_name, plus terminating
-     NULL. */
-  buflen = ent_name->nv.namelen + 1 + nghttp2_bufs_len(&inflater->nvbufs);
-
-  buf = nghttp2_mem_malloc(mem, buflen);
-  if (buf == NULL) {
-    return NGHTTP2_ERR_NOMEM;
-  }
-
-  /* Copy including terminal NULL */
-  memcpy(buf, ent_name->nv.name, ent_name->nv.namelen + 1);
-#ifndef NDEBUG
-  rv =
-#endif
-      nghttp2_bufs_remove_copy(&inflater->nvbufs,
-                               buf + ent_name->nv.namelen + 1);
-  assert(ent_name->nv.namelen + 1 + rv == buflen);
-
-  nghttp2_bufs_reset(&inflater->nvbufs);
-
-  nv->name = buf;
-  nv->namelen = ent_name->nv.namelen;
-
-  nv->value = buf + nv->namelen + 1;
-  nv->valuelen = buflen - nv->namelen - 2;
-
-  return 0;
-}
-
 /*
  * Finalize literal header representation - new name- reception. If
  * header is emitted, |*nv_out| is filled with that value and 0 is
@@ -2224,16 +2114,18 @@ static int hd_inflate_remove_bufs_with_name(nghttp2_hd_inflater *inflater,
  */
 static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
                                      nghttp2_nv *nv_out, int *token_out) {
-  int rv;
   nghttp2_nv nv;
   nghttp2_mem *mem;
 
   mem = inflater->ctx.mem;
 
-  rv = hd_inflate_remove_bufs(inflater, &nv, 0 /* name and value */);
-  if (rv != 0) {
-    return NGHTTP2_ERR_NOMEM;
-  }
+  nv.name = inflater->namebuf.pos;
+  nv.namelen = nghttp2_buf_len(&inflater->namebuf);
+  nv.value = inflater->valuebuf.pos;
+  nv.valuelen = nghttp2_buf_len(&inflater->valuebuf);
+
+  nghttp2_buf_init(&inflater->valuebuf);
+  nghttp2_buf_init(&inflater->namebuf);
 
   if (inflater->no_index) {
     nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
@@ -2245,10 +2137,8 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
     nghttp2_hd_entry *new_ent;
     uint8_t ent_flags;
 
-    /* nv->value points to the middle of the buffer pointed by
-       nv->name.  So we just need to keep track of nv->name for memory
-       management. */
-    ent_flags = NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_NAME_GIFT;
+    ent_flags = NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_NAME_GIFT |
+                NGHTTP2_HD_FLAG_VALUE_ALLOC | NGHTTP2_HD_FLAG_VALUE_GIFT;
 
     new_ent = add_hd_table_incremental(&inflater->ctx, &nv,
                                        lookup_token(nv.name, nv.namelen),
@@ -2261,6 +2151,7 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
       return 0;
     }
 
+    nghttp2_mem_free(mem, nv.value);
     nghttp2_mem_free(mem, nv.name);
 
     return NGHTTP2_ERR_NOMEM;
@@ -2268,9 +2159,8 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
 
   emit_literal_header(nv_out, token_out, &nv);
 
-  if (nv.name != inflater->nvbufs.head->buf.pos) {
-    inflater->nv_keep = nv.name;
-  }
+  inflater->nv_name_keep = nv.name;
+  inflater->nv_value_keep = nv.value;
 
   return 0;
 }
@@ -2288,7 +2178,6 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
  */
 static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
                                      nghttp2_nv *nv_out, int *token_out) {
-  int rv;
   nghttp2_nv nv;
   nghttp2_hd_entry *ent_name;
   nghttp2_mem *mem;
@@ -2307,25 +2196,21 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
     nghttp2_hd_entry *new_ent;
     uint8_t ent_flags;
 
-    if (inflater->index < NGHTTP2_STATIC_TABLE_LENGTH) {
-      /* We don't copy name in static table */
-      rv = hd_inflate_remove_bufs(inflater, &nv, 1 /* value only */);
-      if (rv != 0) {
-        return NGHTTP2_ERR_NOMEM;
-      }
-      nv.name = ent_name->nv.name;
-      nv.namelen = ent_name->nv.namelen;
+    ent_flags = NGHTTP2_HD_FLAG_VALUE_ALLOC | NGHTTP2_HD_FLAG_VALUE_GIFT;
 
-      ent_flags = NGHTTP2_HD_FLAG_VALUE_ALLOC | NGHTTP2_HD_FLAG_VALUE_GIFT;
-    } else {
-      rv = hd_inflate_remove_bufs_with_name(inflater, &nv, ent_name);
-      if (rv != 0) {
-        return NGHTTP2_ERR_NOMEM;
-      }
-      /* nv->name and nv->value are in the same buffer. */
-      ent_flags = NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_NAME_GIFT;
+    if (inflater->index >= NGHTTP2_STATIC_TABLE_LENGTH) {
+      /* We don't copy name in static table */
+      ent_flags |= NGHTTP2_HD_FLAG_NAME_ALLOC;
     }
 
+    nv.name = ent_name->nv.name;
+    nv.namelen = ent_name->nv.namelen;
+
+    nv.value = inflater->valuebuf.pos;
+    nv.valuelen = nghttp2_buf_len(&inflater->valuebuf);
+
+    nghttp2_buf_init(&inflater->valuebuf);
+
     new_ent = add_hd_table_incremental(&inflater->ctx, &nv, ent_name->token,
                                        ent_flags, NULL, 0);
 
@@ -2339,28 +2224,21 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
       return 0;
     }
 
-    if (inflater->index < NGHTTP2_STATIC_TABLE_LENGTH) {
-      nghttp2_mem_free(mem, nv.value);
-    } else {
-      nghttp2_mem_free(mem, nv.name);
-    }
-
-    return NGHTTP2_ERR_NOMEM;
-  }
+    nghttp2_mem_free(mem, nv.value);
 
-  rv = hd_inflate_remove_bufs(inflater, &nv, 1 /* value only */);
-  if (rv != 0) {
     return NGHTTP2_ERR_NOMEM;
   }
 
   nv.name = ent_name->nv.name;
   nv.namelen = ent_name->nv.namelen;
+  nv.value = inflater->valuebuf.pos;
+  nv.valuelen = nghttp2_buf_len(&inflater->valuebuf);
+
+  nghttp2_buf_init(&inflater->valuebuf);
 
   emit_literal_header(nv_out, token_out, &nv);
 
-  if (nv.value != inflater->nvbufs.head->buf.pos) {
-    inflater->nv_keep = nv.value;
-  }
+  inflater->nv_value_keep = nv.value;
 
   return 0;
 }
@@ -2383,6 +2261,9 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
   uint8_t *last = in + inlen;
   int rfin = 0;
   int busy = 0;
+  nghttp2_mem *mem;
+
+  mem = inflater->ctx.mem;
 
   if (inflater->ctx.bad) {
     return NGHTTP2_ERR_HEADER_COMP;
@@ -2541,12 +2422,20 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
         nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
 
         inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
+        rv = nghttp2_buf_reserve(&inflater->namebuf, inflater->left * 2 + 1,
+                                 mem);
       } else {
         inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
+        rv = nghttp2_buf_reserve(&inflater->namebuf, inflater->left + 1, mem);
       }
+
+      if (rv != 0) {
+        goto fail;
+      }
+
       break;
     case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
-      rv = hd_inflate_read_huff(inflater, &inflater->nvbufs, in, last);
+      rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
       if (rv < 0) {
         goto fail;
       }
@@ -2562,18 +2451,13 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
         goto almost_ok;
       }
 
-      inflater->newnamelen = nghttp2_bufs_len(&inflater->nvbufs);
-
-      rv = nghttp2_bufs_addb(&inflater->nvbufs, '\0');
-      if (rv != 0) {
-        goto fail;
-      }
+      *inflater->namebuf.last = '\0';
 
       inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
 
       break;
     case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
-      rv = hd_inflate_read(inflater, &inflater->nvbufs, in, last);
+      rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
       if (rv < 0) {
         goto fail;
       }
@@ -2588,12 +2472,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
         goto almost_ok;
       }
 
-      inflater->newnamelen = nghttp2_bufs_len(&inflater->nvbufs);
-
-      rv = nghttp2_bufs_addb(&inflater->nvbufs, '\0');
-      if (rv != 0) {
-        goto fail;
-      }
+      *inflater->namebuf.last = '\0';
 
       inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
 
@@ -2625,15 +2504,24 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
         nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
 
         inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
+
+        rv = nghttp2_buf_reserve(&inflater->valuebuf, inflater->left * 2 + 1,
+                                 mem);
       } else {
         inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
+
+        rv = nghttp2_buf_reserve(&inflater->valuebuf, inflater->left + 1, mem);
+      }
+
+      if (rv != 0) {
+        goto fail;
       }
 
       busy = 1;
 
       break;
     case NGHTTP2_HD_STATE_READ_VALUEHUFF:
-      rv = hd_inflate_read_huff(inflater, &inflater->nvbufs, in, last);
+      rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
       if (rv < 0) {
         goto fail;
       }
@@ -2649,10 +2537,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
         goto almost_ok;
       }
 
-      rv = nghttp2_bufs_addb(&inflater->nvbufs, '\0');
-      if (rv != 0) {
-        goto fail;
-      }
+      *inflater->valuebuf.last = '\0';
 
       if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
         rv = hd_inflate_commit_newname(inflater, nv_out, token_out);
@@ -2669,7 +2554,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
 
       return (ssize_t)(in - first);
     case NGHTTP2_HD_STATE_READ_VALUE:
-      rv = hd_inflate_read(inflater, &inflater->nvbufs, in, last);
+      rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
       if (rv < 0) {
         DEBUGF(fprintf(stderr, "inflatehd: value read failure %zd: %s\n", rv,
                        nghttp2_strerror((int)rv)));
@@ -2686,10 +2571,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
         goto almost_ok;
       }
 
-      rv = nghttp2_bufs_addb(&inflater->nvbufs, '\0');
-      if (rv != 0) {
-        goto fail;
-      }
+      *inflater->valuebuf.last = '\0';
 
       if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
         rv = hd_inflate_commit_newname(inflater, nv_out, token_out);
diff --git a/lib/nghttp2_hd.h b/lib/nghttp2_hd.h
index adf227be3920189b31316edde1af30e4a574ec12..fff4c5a5d71df2ff16503360086c3cdf390e6bc0 100644
--- a/lib/nghttp2_hd.h
+++ b/lib/nghttp2_hd.h
@@ -276,7 +276,7 @@ struct nghttp2_hd_deflater {
 struct nghttp2_hd_inflater {
   nghttp2_hd_context ctx;
   /* header buffer */
-  nghttp2_bufs nvbufs;
+  nghttp2_buf namebuf, valuebuf;
   /* Stores current state of huffman decoding */
   nghttp2_hd_huff_decode_context huff_decode_ctx;
   /* Pointer to the nghttp2_hd_entry which is used current header
@@ -285,14 +285,11 @@ struct nghttp2_hd_inflater {
   nghttp2_hd_entry *ent_keep;
   /* Pointer to the name/value pair buffer which is used in the
      current header emission. */
-  uint8_t *nv_keep;
+  uint8_t *nv_name_keep, *nv_value_keep;
   /* The number of bytes to read */
   size_t left;
   /* The index in indexed repr or indexed name */
   size_t index;
-  /* The length of new name encoded in literal.  For huffman encoded
-     string, this is the length after it is decoded. */
-  size_t newnamelen;
   /* The maximum header table size the inflater supports. This is the
      same value transmitted in SETTINGS_HEADER_TABLE_SIZE */
   size_t settings_hd_table_bufsize_max;
@@ -470,11 +467,10 @@ int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
 void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
 
 /*
- * Decodes the given data |src| with length |srclen|. The |ctx| must
+ * Decodes the given data |src| with length |srclen|.  The |ctx| must
  * be initialized by nghttp2_hd_huff_decode_context_init(). The result
- * will be added to |dest|. This function may expand |dest| as
- * needed. The caller is responsible to release the memory of |dest|
- * by calling nghttp2_bufs_free().
+ * will be written to |buf|.  This function assumes that |buf| has the
+ * enough room to store the decoded byte string.
  *
  * The caller must set the |final| to nonzero if the given input is
  * the final block.
@@ -486,13 +482,11 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
  *
  * NGHTTP2_ERR_NOMEM
  *     Out of memory.
- * NGHTTP2_ERR_BUFFER_ERROR
- *     Maximum buffer capacity size exceeded.
  * NGHTTP2_ERR_HEADER_COMP
  *     Decoding process has failed.
  */
 ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
-                               nghttp2_bufs *bufs, const uint8_t *src,
+                               nghttp2_buf *buf, const uint8_t *src,
                                size_t srclen, int final);
 
 #endif /* NGHTTP2_HD_H */
diff --git a/lib/nghttp2_hd_huffman.c b/lib/nghttp2_hd_huffman.c
index 48638b75276c911b215047af2289696f398de910..3fb0d8863d8f2f93a8d2e4747318c6b174aace69 100644
--- a/lib/nghttp2_hd_huffman.c
+++ b/lib/nghttp2_hd_huffman.c
@@ -166,31 +166,10 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
   ctx->accept = 1;
 }
 
-/* Use macro to make the code simpler..., but error case is tricky.
-   We spent most of the CPU in decoding, so we are doing this
-   thing. */
-#define hd_huff_decode_sym_emit(bufs, sym, avail)                              \
-  do {                                                                         \
-    if ((avail)) {                                                             \
-      nghttp2_bufs_fast_addb((bufs), (sym));                                   \
-      --(avail);                                                               \
-    } else {                                                                   \
-      rv = nghttp2_bufs_addb((bufs), (sym));                                   \
-      if (rv != 0) {                                                           \
-        return rv;                                                             \
-      }                                                                        \
-      (avail) = nghttp2_bufs_cur_avail((bufs));                                \
-    }                                                                          \
-  } while (0)
-
 ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
-                               nghttp2_bufs *bufs, const uint8_t *src,
+                               nghttp2_buf *buf, const uint8_t *src,
                                size_t srclen, int final) {
   size_t i;
-  int rv;
-  size_t avail;
-
-  avail = nghttp2_bufs_cur_avail(bufs);
 
   /* We use the decoding algorithm described in
      http://graphics.ics.uci.edu/pub/Prefix.pdf */
@@ -202,8 +181,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
       return NGHTTP2_ERR_HEADER_COMP;
     }
     if (t->flags & NGHTTP2_HUFF_SYM) {
-      /* this is macro, and may return from this function on error */
-      hd_huff_decode_sym_emit(bufs, t->sym, avail);
+      *buf->last++ = t->sym;
     }
 
     t = &huff_decode_table[t->state][src[i] & 0xf];
@@ -211,8 +189,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
       return NGHTTP2_ERR_HEADER_COMP;
     }
     if (t->flags & NGHTTP2_HUFF_SYM) {
-      /* this is macro, and may return from this function on error */
-      hd_huff_decode_sym_emit(bufs, t->sym, avail);
+      *buf->last++ = t->sym;
     }
 
     ctx->state = t->state;
diff --git a/tests/nghttp2_hd_test.c b/tests/nghttp2_hd_test.c
index 5a4d7c5fb6bb1ee6e916f39d3d5c85c67a255553..ed954bde405aaca01acf72b6231a7b115384a937 100644
--- a/tests/nghttp2_hd_test.c
+++ b/tests/nghttp2_hd_test.c
@@ -1352,13 +1352,15 @@ void test_nghttp2_hd_decode_length(void) {
 void test_nghttp2_hd_huff_encode(void) {
   int rv;
   ssize_t len;
-  nghttp2_bufs bufs, outbufs;
+  nghttp2_buf outbuf;
+  nghttp2_bufs bufs;
   nghttp2_hd_huff_decode_context ctx;
   const uint8_t t1[] = {22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
                         10, 9,  8,  7,  6,  5,  4,  3,  2,  1,  0};
+  uint8_t b[256];
 
+  nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
   frame_pack_bufs_init(&bufs);
-  frame_pack_bufs_init(&outbufs);
 
   rv = nghttp2_hd_huff_encode(&bufs, t1, sizeof(t1));
 
@@ -1366,14 +1368,13 @@ void test_nghttp2_hd_huff_encode(void) {
 
   nghttp2_hd_huff_decode_context_init(&ctx);
 
-  len = nghttp2_hd_huff_decode(&ctx, &outbufs, bufs.cur->buf.pos,
+  len = nghttp2_hd_huff_decode(&ctx, &outbuf, bufs.cur->buf.pos,
                                nghttp2_bufs_len(&bufs), 1);
 
   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == len);
-  CU_ASSERT((ssize_t)sizeof(t1) == nghttp2_bufs_len(&outbufs));
+  CU_ASSERT((ssize_t)sizeof(t1) == nghttp2_buf_len(&outbuf));
 
-  CU_ASSERT(0 == memcmp(t1, outbufs.cur->buf.pos, sizeof(t1)));
+  CU_ASSERT(0 == memcmp(t1, outbuf.pos, sizeof(t1)));
 
   nghttp2_bufs_free(&bufs);
-  nghttp2_bufs_free(&outbufs);
 }