diff --git a/src/hammer.c b/src/hammer.c
index c257e07278dc58e2c0d4fe3a978a17e8b8a5debf..f66b96301a186d2e8c33e6bb90e43230dd67845e 100644
--- a/src/hammer.c
+++ b/src/hammer.c
@@ -34,6 +34,15 @@ static guint djbhash(const uint8_t *buf, size_t len) {
   return hash;
 }
 
+// short-hand for constructing HCachedResult's
+static HCachedResult *cached_result(const HParseState *state, HParseResult *result)
+{
+  HCachedResult *ret = a_new(HCachedResult, 1);
+  ret->result = result;
+  ret->input_stream = state->input_stream;
+  return ret;
+}
+
 HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) {
   HParserCacheValue *cached = g_hash_table_lookup(state->cache, k);
   HRecursionHead *head = g_hash_table_lookup(state->recursion_heads, k);
@@ -45,7 +54,7 @@ HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) {
       HParseResult *tmp = a_new(HParseResult, 1);
       tmp->ast = NULL; tmp->arena = state->arena;
       HParserCacheValue *ret = a_new(HParserCacheValue, 1);
-      ret->value_type = PC_RIGHT; ret->right = tmp;
+      ret->value_type = PC_RIGHT; ret->right = cached_result(state, tmp);
       return ret;
     }
     if (g_slist_find(head->eval_set, k->parser)) {
@@ -58,7 +67,7 @@ HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) {
       if (!cached)
 	cached = a_new(HParserCacheValue, 1);
       cached->value_type = PC_RIGHT;
-      cached->right = tmp_res;
+      cached->right = cached_result(state, tmp_res);
     }
     return cached;
   }
@@ -93,7 +102,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head)
   HParserCacheValue *old_cached = g_hash_table_lookup(state->cache, k);
   if (!old_cached || PC_LEFT == old_cached->value_type)
     errx(1, "impossible match");
-  HParseResult *old_res = old_cached->right;
+  HParseResult *old_res = old_cached->right->result;
   
   // reset the eval_set of the head of the recursion at each beginning of growth
   head->eval_set = head->involved_set;
@@ -108,7 +117,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head)
     if ((old_res->ast->index < tmp_res->ast->index) || 
 	(old_res->ast->index == tmp_res->ast->index && old_res->ast->bit_offset < tmp_res->ast->bit_offset)) {
       HParserCacheValue *v = a_new(HParserCacheValue, 1);
-      v->value_type = PC_RIGHT; v->right = tmp_res;
+      v->value_type = PC_RIGHT; v->right = cached_result(state, tmp_res);
       g_hash_table_replace(state->cache, k, v);
       return grow(k, state, head);
     } else {
@@ -116,7 +125,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head)
       g_hash_table_remove(state->recursion_heads, k);
       HParserCacheValue *cached = g_hash_table_lookup(state->cache, k);
       if (cached && PC_RIGHT == cached->value_type) {
-	return cached->right;
+	return cached->right->result;
       } else {
 	errx(1, "impossible match");
       }
@@ -136,7 +145,7 @@ HParseResult* lr_answer(HParserCacheKey *k, HParseState *state, HLeftRec *growab
     else {
       // update cache
       HParserCacheValue *v = a_new(HParserCacheValue, 1);
-      v->value_type = PC_RIGHT; v->right = growable->seed;
+      v->value_type = PC_RIGHT; v->right = cached_result(state, growable->seed);
       g_hash_table_replace(state->cache, k, v);
       if (!growable->seed)
 	return NULL;
@@ -194,7 +203,7 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) {
     // setupLR, used below, mutates the LR to have a head if appropriate, so we check to see if we have one
     if (NULL == base->head) {
       HParserCacheValue *right = a_new(HParserCacheValue, 1);
-      right->value_type = PC_RIGHT; right->right = tmp_res;
+      right->value_type = PC_RIGHT; right->right = cached_result(state, tmp_res);
       g_hash_table_replace(state->cache, key, right);
       return tmp_res;
     } else {
@@ -208,14 +217,8 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) {
       setupLR(parser, state, m->left);
       return m->left->seed; // BUG: this might not be correct
     } else {
-      HParseResult *res = m->right;
-
-      // skip over the previously-parsed input
-      long long offs = res->bit_length + state->input_stream.bit_offset;
-      state->input_stream.index += offs >> 3;
-      state->input_stream.bit_offset = offs & 7;
-
-      return res;
+      state->input_stream = m->right->input_stream;
+      return m->right->result;
     }
   }
 }
diff --git a/src/internal.h b/src/internal.h
index 73956328454ab58bcb61c527766184d3f358b416..cc35a8b6ce0d1f8fffe6d2b98acb1ef0b06e276c 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -108,6 +108,12 @@ typedef struct HLeftRec_ {
   HRecursionHead *head;
 } HLeftRec;
 
+/* Result and remaining input, for rerunning from a cached position. */
+typedef struct HCachedResult_ {
+  HParseResult *result;
+  HInputStream input_stream;
+} HCachedResult;
+
 /* Tagged union for values in the cache: either HLeftRec's (Left) or 
  * HParseResult's (Right).
  */
@@ -115,7 +121,7 @@ typedef struct HParserCacheValue_t {
   HParserCacheValueType value_type;
   union {
     HLeftRec *left;
-    HParseResult *right;
+    HCachedResult *right;
   };
 } HParserCacheValue;