diff --git a/src/buf/byte.rs b/src/buf/byte.rs
index 6b6cdb5d766040628d6c1cddb0061ac4e4d8492a..2fc77e647e28e4c56e7d68ee86bf9c3c79f00335 100644
--- a/src/buf/byte.rs
+++ b/src/buf/byte.rs
@@ -13,7 +13,8 @@ pub struct ByteBuf {
     mem: alloc::MemRef,
     cap: u32,
     pos: u32,
-    lim: u32
+    lim: u32,
+    mark: Option<u32>,
 }
 
 impl ByteBuf {
@@ -35,6 +36,7 @@ impl ByteBuf {
             cap: 0,
             pos: 0,
             lim: 0,
+            mark: None,
         }
     }
 
@@ -46,6 +48,7 @@ impl ByteBuf {
             cap: cap,
             pos: pos,
             lim: lim,
+            mark: None,
         }
     }
 
@@ -70,7 +73,8 @@ impl ByteBuf {
             mem: mem,
             cap: capacity,
             pos: 0,
-            lim: capacity
+            lim: capacity,
+            mark: None,
         }
     }
 
@@ -112,6 +116,27 @@ impl ByteBuf {
         Bytes::of(self.to_seq_byte_str())
     }
 
+    /// Marks the current read location.
+    ///
+    /// Together with `reset`, this can be used to read from a section of the
+    /// buffer multiple times. The marked location will be cleared when the
+    /// buffer is flipped.
+    pub fn mark(&mut self) {
+        self.mark = Some(self.pos);
+    }
+
+    /// Resets the read position to the previously marked position.
+    ///
+    /// Together with `mark`, this can be used to read from a section of the
+    /// buffer multiple times.
+    ///
+    /// # Panics
+    ///
+    /// This method will panic if no mark has been set.
+    pub fn reset(&mut self) {
+        self.pos = self.mark.take().expect("no mark set");
+    }
+
     #[inline]
     fn pos(&self) -> usize {
         self.pos as usize
@@ -177,6 +202,26 @@ impl ROByteBuf {
     pub fn to_bytes(self) -> Bytes {
         self.buf.to_bytes()
     }
+
+    /// Marks the current read location.
+    ///
+    /// Together with `reset`, this can be used to read from a section of the
+    /// buffer multiple times.
+    pub fn mark(&mut self) {
+        self.buf.mark = Some(self.buf.pos);
+    }
+
+    /// Resets the read position to the previously marked position.
+    ///
+    /// Together with `mark`, this can be used to read from a section of the
+    /// buffer multiple times.
+    ///
+    /// # Panics
+    ///
+    /// This method will panic if no mark has been set.
+    pub fn reset(&mut self) {
+        self.buf.pos = self.buf.mark.take().expect("no mark set");
+    }
 }
 
 impl Buf for ROByteBuf {
diff --git a/src/buf/ring.rs b/src/buf/ring.rs
index e20a0dcbc598baf596e8b927b7ad3f7990c72482..ca1df7f9e476fb4a86cd3c27177366f0b9c8f1f5 100644
--- a/src/buf/ring.rs
+++ b/src/buf/ring.rs
@@ -8,7 +8,8 @@ pub struct RingBuf {
     ptr: alloc::MemRef,  // Pointer to the memory
     cap: usize,          // Capacity of the buffer
     pos: usize,          // Offset of read cursor
-    len: usize           // Number of bytes to read
+    len: usize,          // Number of bytes to read
+    mark: Option<usize>, // Marked read position
 }
 
 // TODO: There are most likely many optimizations that can be made
@@ -20,7 +21,8 @@ impl RingBuf {
                 ptr: alloc::MemRef::none(),
                 cap: 0,
                 pos: 0,
-                len: 0
+                len: 0,
+                mark: None,
             }
         }
 
@@ -33,7 +35,8 @@ impl RingBuf {
             ptr: mem,
             cap: capacity,
             pos: 0,
-            len: 0
+            len: 0,
+            mark: None,
         }
     }
 
@@ -49,6 +52,29 @@ impl RingBuf {
         self.cap
     }
 
+    /// Marks the current read location.
+    ///
+    /// Together with `reset`, this can be used to read from a section of the
+    /// buffer multiple times. The mark will be cleared if it is overwritten
+    /// during a write.
+    pub fn mark(&mut self) {
+        self.mark = Some(self.pos);
+    }
+
+    /// Resets the read position to the previously marked position.
+    ///
+    /// Together with `mark`, this can be used to read from a section of the
+    /// buffer multiple times.
+    ///
+    /// # Panics
+    ///
+    /// This method will panic if no mark has been set,
+    pub fn reset(&mut self){
+        let mark = self.mark.take().expect("no mark set");
+        self.len = (self.len + self.pos + self.cap - mark) % self.cap;
+        self.pos = mark;
+    }
+
     fn read_remaining(&self) -> usize {
         self.len
     }
@@ -71,6 +97,11 @@ impl RingBuf {
     fn advance_writer(&mut self, mut cnt: usize) {
         cnt = cmp::min(cnt, self.write_remaining());
         self.len += cnt;
+        if let Some(mark) = self.mark {
+            if (self.pos + self.len) % self.cap > mark {
+                self.mark = None;
+            }
+        }
     }
 }
 
diff --git a/test/test_byte_buf.rs b/test/test_byte_buf.rs
index 1c3fd24722134c0c9ea8f484e196485d5f945c55..7557ddcad019f9a5ed3c9a60cbad2803e9862368 100644
--- a/test/test_byte_buf.rs
+++ b/test/test_byte_buf.rs
@@ -30,6 +30,10 @@ pub fn test_byte_buf_read_write() {
     let mut buf = buf.flip();
     let mut dst = [0; 5];
 
+    buf.mark();
+    assert_eq!(5, buf.read(&mut dst[..]).unwrap());
+    assert_eq!(b"hello", &dst);
+    buf.reset();
     assert_eq!(5, buf.read(&mut dst[..]).unwrap());
     assert_eq!(b"hello", &dst);
 
diff --git a/test/test_ring.rs b/test/test_ring.rs
index e740d232e9b712271535a7c81e1607ff62288833..d2c1ba957d5f98e43f69c5f35ba276f88eb97a74 100644
--- a/test/test_ring.rs
+++ b/test/test_ring.rs
@@ -19,9 +19,16 @@ pub fn test_initial_buf_empty() {
     assert_eq!(buf.bytes(), [1, 2, 3]);
 
     let mut out = [0u8; 3];
+
+    buf.mark();
+    let bytes_read = buf.read(&mut out[..]).unwrap();;
+    assert_eq!(bytes_read, 3);
+    assert_eq!(out, [1, 2, 3]);
+    buf.reset();
     let bytes_read = buf.read(&mut out[..]).unwrap();;
     assert_eq!(bytes_read, 3);
     assert_eq!(out, [1, 2, 3]);
+
     assert_eq!(MutBuf::remaining(&buf), 16);
     assert_eq!(Buf::remaining(&buf), 0);
 }
@@ -39,6 +46,11 @@ fn test_wrapping_write() {
     let bytes_written = buf.write(&[23;8][..]).unwrap();
     assert_eq!(bytes_written, 8);
 
+    buf.mark();
+    let bytes_read = buf.read(&mut out[..]).unwrap();
+    assert_eq!(bytes_read, 10);
+    assert_eq!(out, [42, 42, 23, 23, 23, 23, 23, 23, 23, 23]);
+    buf.reset();
     let bytes_read = buf.read(&mut out[..]).unwrap();
     assert_eq!(bytes_read, 10);
     assert_eq!(out, [42, 42, 23, 23, 23, 23, 23, 23, 23, 23]);
@@ -64,3 +76,16 @@ fn test_io_write_and_read() {
     assert_eq!(bytes_read, 8);
     assert_eq!(out, [2;8]);
 }
+
+#[test]
+#[should_panic]
+fn test_wrap_reset() {
+    use std::io::{Read, Write};
+
+    let mut buf = RingBuf::new(8);
+    buf.write(&[1, 2, 3, 4, 5, 6, 7]).unwrap();
+    buf.mark();
+    buf.read(&mut [0; 4]).unwrap();
+    buf.write(&[1, 2, 3, 4]).unwrap();
+    buf.reset();
+}