Repository: sharksforarms/deku
Pull request #360 (2023-09-04 20:13:16)

Impl reader+writer seek
- Add `Seek` to `Reader` and `Writer`
- Add `as_mut` to `Reader`, and tests
- Add: `seek_rewind`, `seek_from_current`, `seek_from_end`,  `seek_from_start`,

See https://github.com/sharksforarms/deku/issues/105

Currently being used in https://github.com/wcampbell0x2a/cpio-deku

github-actions[bot]: ## Benchmark for c05f1ba
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| deku_read_bits | 784.1±1.34ns | 784.1±1.36ns | 0.00% |
| deku_read_byte | 23.5±0.11ns | 23.5±0.08ns | 0.00% |
| deku_read_enum | 10.1±0.08ns | 10.1±0.07ns | 0.00% |
| deku_read_vec | **65.4±0.34ns** | 68.2±0.77ns | **+4.28%** |
| deku_write_bits | **105.5±0.39ns** | 105.9±1.16ns | **+0.38%** |
| deku_write_byte | 164.3±0.91ns | **163.5±0.76ns** | **-0.49%** |
| deku_write_enum | 105.8±0.35ns | 105.8±0.31ns | 0.00% |
| deku_write_vec | 4.0±0.01µs | 4.0±0.01µs | 0.00% |

  </details>
  
github-actions[bot]: ## Benchmark for f9655f8
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| deku_read_bits | **1253.9±14.83ns** | 1293.6±23.46ns | **+3.17%** |
| deku_read_byte | 21.8±0.59ns | 21.8±0.54ns | 0.00% |
| deku_read_enum | 9.5±0.16ns | 9.4±0.15ns | -1.05% |
| deku_read_vec | 59.5±0.65ns | **58.6±0.82ns** | **-1.51%** |
| deku_write_bits | **142.6±5.32ns** | 225.8±16.05ns | **+58.35%** |
| deku_write_byte | 142.1±4.61ns | **20.9±0.36ns** | **-85.29%** |
| deku_write_enum | 84.4±2.43ns | **19.6±0.33ns** | **-76.78%** |
| deku_write_vec | 3.3±0.07µs | **300.4±4.12ns** | **-90.90%** |

  </details>
  
github-actions[bot]: ## Benchmark for 84fd5f3
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| deku_read_bits | **1116.3±18.52ns** | 1197.5±16.33ns | **+7.27%** |
| deku_read_byte | **21.6±0.49ns** | 22.2±1.48ns | **+2.78%** |
| deku_read_enum | 9.3±0.15ns | 9.3±0.13ns | 0.00% |
| deku_read_vec | 53.5±0.59ns | 53.9±0.51ns | +0.75% |
| deku_write_bits | **180.7±3.25ns** | 188.7±21.84ns | **+4.43%** |
| deku_write_byte | 21.2±2.63ns | **20.8±0.23ns** | **-1.89%** |
| deku_write_enum | 20.2±0.36ns | 20.1±0.18ns | -0.50% |
| deku_write_vec | 298.2±5.20ns | 296.1±3.47ns | -0.70% |

  </details>
  
github-actions[bot]: ## Benchmark for e6c5a67
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| deku_read_bits | **1229.2±16.47ns** | 1261.1±14.49ns | **+2.60%** |
| deku_read_byte | 3.3±0.12ns | 3.3±0.08ns | 0.00% |
| deku_read_enum | 2.6±0.07ns | 2.6±0.04ns | 0.00% |
| deku_read_vec | 33.7±0.47ns | 33.4±0.33ns | -0.89% |
| deku_write_bits | 149.5±4.52ns | 149.0±2.81ns | -0.33% |
| deku_write_byte | 21.8±0.51ns | 22.0±0.31ns | +0.92% |
| deku_write_enum | **21.1±0.31ns** | 21.4±0.26ns | **+1.42%** |
| deku_write_vec | **351.9±3.46ns** | 405.2±5.23ns | **+15.15%** |

  </details>
  
github-actions[bot]: ## Benchmark for cee1fd3
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| deku_read_bits | 1289.2±17.71ns | **1219.4±15.03ns** | **-5.41%** |
| deku_read_byte | **3.3±0.07ns** | 3.4±0.29ns | **+3.03%** |
| deku_read_enum | 2.6±0.06ns | 2.6±0.03ns | 0.00% |
| deku_read_vec | 34.5±0.40ns | 34.3±0.33ns | -0.58% |
| deku_write_bits | **148.8±2.97ns** | 155.7±3.30ns | **+4.64%** |
| deku_write_byte | 22.0±0.29ns | 21.9±0.40ns | -0.45% |
| deku_write_enum | 21.1±0.26ns | 21.2±0.79ns | +0.47% |
| deku_write_vec | 408.3±5.52ns | **354.0±3.25ns** | **-13.30%** |

  </details>
  
github-actions[bot]: ## Benchmark for 2a61000
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| deku_read_bits | **1222.2±15.48ns** | 1250.6±43.96ns | **+2.32%** |
| deku_read_byte | 3.5±0.07ns | **3.3±0.03ns** | **-5.71%** |
| deku_read_enum | 3.0±0.05ns | **2.6±0.06ns** | **-13.33%** |
| deku_read_vec | 34.9±0.67ns | 34.4±0.62ns | -1.43% |
| deku_write_bits | **157.5±3.33ns** | 235.5±3.68ns | **+49.52%** |
| deku_write_byte | **22.0±0.22ns** | 22.6±0.29ns | **+2.73%** |
| deku_write_enum | 21.4±0.37ns | 21.4±0.31ns | 0.00% |
| deku_write_vec | 423.2±4.81ns | **417.7±24.23ns** | **-1.30%** |

  </details>
  
github-actions[bot]: ## Benchmark for d862393
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| deku_read_bits | 1283.7±14.74ns | 1276.0±56.88ns | -0.60% |
| deku_read_byte | 3.5±0.06ns | **3.3±0.05ns** | **-5.71%** |
| deku_read_enum | 3.0±0.05ns | **2.6±0.05ns** | **-13.33%** |
| deku_read_vec | 33.7±0.64ns | 33.6±0.62ns | -0.30% |
| deku_write_bits | 154.8±4.91ns | **148.6±6.87ns** | **-4.01%** |
| deku_write_byte | 21.8±0.28ns | 21.6±0.40ns | -0.92% |
| deku_write_enum | 21.1±0.44ns | 21.1±0.31ns | 0.00% |
| deku_write_vec | 424.7±17.49ns | **350.7±4.28ns** | **-17.42%** |

  </details>
  
github-actions[bot]: ## Benchmark for 26c8d2a
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| deku_read_bits | **1234.8±24.41ns** | 1289.0±9.75ns | **+4.39%** |
| deku_read_byte | 3.5±0.07ns | **3.3±0.05ns** | **-5.71%** |
| deku_read_enum | 3.0±0.05ns | **2.6±0.05ns** | **-13.33%** |
| deku_read_vec | 34.4±0.58ns | **33.5±0.31ns** | **-2.62%** |
| deku_write_bits | **149.2±3.32ns** | 157.6±3.18ns | **+5.63%** |
| deku_write_byte | **21.9±0.20ns** | 24.5±0.37ns | **+11.87%** |
| deku_write_enum | **21.1±0.34ns** | 23.0±0.37ns | **+9.00%** |
| deku_write_vec | **404.8±5.36ns** | 439.4±5.98ns | **+8.55%** |

  </details>
  
vhdirk: This would be pretty useful in my project. Anything I can assist with to get this merged?
wcampbell0x2a: > This would be pretty useful in my project. Anything I can assist with to get this merged?

We need https://github.com/no-std-io/no-std-io/pull/5 and a final review by me and @sharksforarms 
wcampbell0x2a: > > This would be pretty useful in my project. Anything I can assist with to get this merged?
> 
> We need [no-std-io/no-std-io#5](https://github.com/no-std-io/no-std-io/pull/5) and a final review by me and @sharksforarms

Decided to just fork that repo and use my own `no-std-core2` for now, since that wasn't getting merged and i've tried contacting them a couple of times.
github-actions[bot]: ## Benchmark for 830408c
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| deku_read_bits | **1157.1±16.19ns** | 1197.3±10.14ns | **+3.47%** |
| deku_read_byte | 3.3±0.15ns | 3.3±0.02ns | 0.00% |
| deku_read_enum | **2.5±0.08ns** | 2.6±0.06ns | **+4.00%** |
| deku_read_vec | **33.7±0.21ns** | 34.5±0.25ns | **+2.37%** |
| deku_write_bits | 187.9±4.96ns | **181.1±8.26ns** | **-3.62%** |
| deku_write_byte | **22.7±0.43ns** | 25.2±0.26ns | **+11.01%** |
| deku_write_enum | **21.7±0.30ns** | 23.0±0.19ns | **+5.99%** |
| deku_write_vec | **387.4±3.96ns** | 404.9±4.90ns | **+4.52%** |

  </details>
  
github-actions[bot]: ## Benchmark for fe7abff
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| deku_read_bits | 1185.2±9.81ns | 1176.5±15.95ns | -0.73% |
| deku_read_byte | 3.3±0.04ns | 3.3±0.09ns | 0.00% |
| deku_read_enum | **2.5±0.05ns** | 2.6±0.05ns | **+4.00%** |
| deku_read_vec | 33.7±0.39ns | 33.9±0.49ns | +0.59% |
| deku_write_bits | 181.5±7.18ns | 181.2±3.77ns | -0.17% |
| deku_write_byte | **22.7±0.33ns** | 25.2±0.58ns | **+11.01%** |
| deku_write_enum | **21.7±0.39ns** | 22.7±0.36ns | **+4.61%** |
| deku_write_vec | **390.7±3.67ns** | 431.1±6.61ns | **+10.34%** |

  </details>
  
wcampbell0x2a: > Thanks! This is great. This got me thinking, it would be pretty cool if there was a way to add attributes like this without adding bounds to the generic, such that "seek_" could only be used if `T` is `Seek`, else it would be a compile error. This way, we don't impose more bounds than necessary?
> 
> The downside of this PR is that now types are now required to be `Seek` (maybe less of a concern with the reader interface... but I can for-see some folks not liking this, maybe?)

I'm not sure about any solutions that includes generic bounds, I think you'll always need to have `Seek` as a bounds on `Reader`, unless i'm wrong.

the friends at `binrw` 'solve' this by having a [NoSeek](https://docs.rs/binrw/latest/binrw/io/struct.NoSeek.html)

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 032b31e..b5c205e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
 # Changelog
 
 ## [Unreleased]
+- Add attributes `seek_from_start`, `seek_from_current`, `seek_from_end`, and `seek_rewind` to control the position of the reader before reading a field ([#360](https://github.com/sharksforarms/deku/pull/360))
 
 ## [0.17.0] - 2024-04-23
 
diff --git a/Cargo.toml b/Cargo.toml
index 04a0301..4d3ad5f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -31,7 +31,7 @@ error_in_core = []
 deku_derive = { version = "^0.17.0", path = "deku-derive", default-features = false}
 bitvec = { version = "1.0.1", default-features = false }
 log = { version = "0.4.21", optional = true }
-no_std_io = { version = "0.6.0", default-features = false, features = ["alloc"] }
+no_std_io = { version = "0.8.0", default-features = false, features = ["alloc"], package = "no_std_io2" }
 rustversion = "1.0.16"
 
 [dev-dependencies]
diff --git a/benches/deku.rs b/benches/deku.rs
index fdc9b9b..e3d38e5 100644
--- a/benches/deku.rs
+++ b/benches/deku.rs
@@ -1,4 +1,4 @@
-use std::io::{Cursor, Read};
+use std::io::{Cursor, Read, Seek};
 
 use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion};
 use deku::prelude::*;
@@ -38,7 +38,7 @@ fn deku_write<T: DekuContainerWrite>(input: &T) {
     let _v = input.to_bytes().unwrap();
 }
 
-fn deku_read<T: for<'a> DekuContainerRead<'a>>(mut reader: impl Read) {
+fn deku_read<T: for<'a> DekuContainerRead<'a>>(mut reader: impl Read + Seek) {
     let mut reader = Reader::new(&mut reader);
     let _v = T::from_reader_with_ctx(&mut reader, ()).unwrap();
 }
diff --git a/deku-derive/src/lib.rs b/deku-derive/src/lib.rs
index 8347075..fea289b 100644
--- a/deku-derive/src/lib.rs
+++ b/deku-derive/src/lib.rs
@@ -140,6 +140,18 @@ struct DekuData {
 
     /// enum only: byte size of the enum `id`
     bytes: Option<Num>,
+
+    /// struct only: seek from current position
+    seek_rewind: bool,
+
+    /// struct only: seek from current position
+    seek_from_current: Option<TokenStream>,
+
+    /// struct only: seek from end position
+    seek_from_end: Option<TokenStream>,
+
+    /// struct only: seek from start position
+    seek_from_start: Option<TokenStream>,
 }
 
 impl DekuData {
@@ -188,6 +200,10 @@ impl DekuData {
             id_type: receiver.id_type?,
             bits: receiver.bits,
             bytes: receiver.bytes,
+            seek_rewind: receiver.seek_rewind,
+            seek_from_current: receiver.seek_from_current?,
+            seek_from_end: receiver.seek_from_end?,
+            seek_from_start: receiver.seek_from_start?,
         };
 
         DekuData::validate(&data)?;
@@ -444,6 +460,18 @@ struct FieldData {
 
     // assert value of field
     assert_eq: Option<TokenStream>,
+
+    /// seek from current position
+    seek_rewind: bool,
+
+    /// seek from current position
+    seek_from_current: Option<TokenStream>,
+
+    /// seek from end position
+    seek_from_end: Option<TokenStream>,
+
+    /// seek from start position
+    seek_from_start: Option<TokenStream>,
 }
 
 impl FieldData {
@@ -481,6 +509,10 @@ impl FieldData {
             cond: receiver.cond?,
             assert: receiver.assert?,
             assert_eq: receiver.assert_eq?,
+            seek_rewind: receiver.seek_rewind,
+            seek_from_current: receiver.seek_from_current?,
+            seek_from_end: receiver.seek_from_end?,
+            seek_from_start: receiver.seek_from_start?,
         };
 
         FieldData::validate(&data)?;
@@ -544,6 +576,19 @@ impl FieldData {
             ));
         }
 
+        // Validate usage of seek_*
+        if (data.seek_from_current.is_some() as u8
+            + data.seek_from_end.is_some() as u8
+            + data.seek_from_start.is_some() as u8
+            + data.seek_rewind as u8)
+            > 1
+        {
+            return Err(cerror(
+                data.bits.span(),
+                "conflicting: only one `seek` attribute can be used at one time",
+            ));
+        }
+
         Ok(())
     }
 
@@ -668,6 +713,22 @@ struct DekuReceiver {
     /// enum only: byte size of the enum `id`
     #[darling(default)]
     bytes: Option<Num>,
+
+    /// struct only: seek from current position
+    #[darling(default)]
+    seek_rewind: bool,
+
+    /// struct only: seek from current position
+    #[darling(default = "default_res_opt", map = "map_litstr_as_tokenstream")]
+    seek_from_current: Result<Option<TokenStream>, ReplacementError>,
+
+    /// struct only: seek from end position
+    #[darling(default = "default_res_opt", map = "map_litstr_as_tokenstream")]
+    seek_from_end: Result<Option<TokenStream>, ReplacementError>,
+
+    /// struct only: seek from start position
+    #[darling(default = "default_res_opt", map = "map_litstr_as_tokenstream")]
+    seek_from_start: Result<Option<TokenStream>, ReplacementError>,
 }
 
 type ReplacementError = TokenStream;
@@ -848,6 +909,22 @@ struct DekuFieldReceiver {
     // assert value of field
     #[darling(default = "default_res_opt", map = "map_litstr_as_tokenstream")]
     assert_eq: Result<Option<TokenStream>, ReplacementError>,
+
+    /// seek from current position
+    #[darling(default)]
+    seek_rewind: bool,
+
+    /// seek from current position
+    #[darling(default = "default_res_opt", map = "map_litstr_as_tokenstream")]
+    seek_from_current: Result<Option<TokenStream>, ReplacementError>,
+
+    /// seek from end position
+    #[darling(default = "default_res_opt", map = "map_litstr_as_tokenstream")]
+    seek_from_end: Result<Option<TokenStream>, ReplacementError>,
+
+    /// seek from start position
+    #[darling(default = "default_res_opt", map = "map_litstr_as_tokenstream")]
+    seek_from_start: Result<Option<TokenStream>, ReplacementError>,
 }
 
 /// Receiver for the variant-level attributes inside a enum
diff --git a/deku-derive/src/macros/deku_read.rs b/deku-derive/src/macros/deku_read.rs
index a752702..287e03c 100644
--- a/deku-derive/src/macros/deku_read.rs
+++ b/deku-derive/src/macros/deku_read.rs
@@ -37,6 +37,49 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {
         fields,
     } = DekuDataStruct::try_from(input)?;
 
+    let seek = if let Some(num) = &input.seek_from_current {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                use ::#crate_::no_std_io::SeekFrom;
+                if let Err(e) = __deku_reader.seek(SeekFrom::Current(i64::try_from(#num).unwrap())) {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else if let Some(num) = &input.seek_from_end {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                use ::#crate_::no_std_io::SeekFrom;
+                if let Err(e) = __deku_reader.seek(SeekFrom::End(i64::try_from(#num).unwrap())) {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else if let Some(num) = &input.seek_from_start {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                use ::#crate_::no_std_io::SeekFrom;
+                if let Err(e) = __deku_reader.seek(SeekFrom::Start(u64::try_from(#num).unwrap())) {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else if input.seek_rewind {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                if let Err(e) = __deku_reader.rewind() {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else {
+        quote! {}
+    };
+
     let magic_read = emit_magic_read(input);
 
     // check if the first field has an ident, if not, it's a unnamed struct
@@ -107,6 +150,8 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {
     let read_body = quote! {
         use core::convert::TryFrom;
 
+        #seek
+
         #magic_read
 
         #(#field_reads)*
@@ -118,7 +163,7 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {
     tokens.extend(quote! {
         impl #imp ::#crate_::DekuReader<#lifetime, #ctx_types> for #ident #wher {
             #[inline]
-            fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read>(__deku_reader: &mut ::#crate_::reader::Reader<R>, #ctx_arg) -> core::result::Result<Self, ::#crate_::DekuError> {
+            fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read + ::#crate_::no_std_io::Seek>(__deku_reader: &mut ::#crate_::reader::Reader<R>, #ctx_arg) -> core::result::Result<Self, ::#crate_::DekuError> {
                 #read_body
             }
         }
@@ -130,7 +175,7 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {
         tokens.extend(quote! {
             impl #imp ::#crate_::DekuReader<#lifetime> for #ident #wher {
                 #[inline]
-                fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read>(__deku_reader: &mut ::#crate_::reader::Reader<R>, _: ()) -> core::result::Result<Self, ::#crate_::DekuError> {
+                fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read + ::#crate_::no_std_io::Seek>(__deku_reader: &mut ::#crate_::reader::Reader<R>, _: ()) -> core::result::Result<Self, ::#crate_::DekuError> {
                     #read_body
                 }
             }
@@ -381,7 +426,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
         #[allow(non_snake_case)]
         impl #imp ::#crate_::DekuReader<#lifetime, #ctx_types> for #ident #wher {
             #[inline]
-            fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read>(__deku_reader: &mut ::#crate_::reader::Reader<R>, #ctx_arg) -> core::result::Result<Self, ::#crate_::DekuError> {
+            fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read + ::#crate_::no_std_io::Seek>(__deku_reader: &mut ::#crate_::reader::Reader<R>, #ctx_arg) -> core::result::Result<Self, ::#crate_::DekuError> {
                 #read_body
             }
         }
@@ -394,7 +439,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
             #[allow(non_snake_case)]
             impl #imp ::#crate_::DekuReader<#lifetime> for #ident #wher {
                 #[inline]
-                fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read>(__deku_reader: &mut ::#crate_::reader::Reader<R>, _: ()) -> core::result::Result<Self, ::#crate_::DekuError> {
+                fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read + ::#crate_::no_std_io::Seek>(__deku_reader: &mut ::#crate_::reader::Reader<R>, _: ()) -> core::result::Result<Self, ::#crate_::DekuError> {
                     #read_body
                 }
             }
@@ -568,6 +613,49 @@ fn emit_field_read(
         &f.assert_eq,
     ];
 
+    let seek = if let Some(num) = &f.seek_from_current {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                use ::#crate_::no_std_io::SeekFrom;
+                if let Err(e) = __deku_reader.seek(SeekFrom::Current(i64::try_from(#num).unwrap())) {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else if let Some(num) = &f.seek_from_end {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                use ::#crate_::no_std_io::SeekFrom;
+                if let Err(e) = __deku_reader.seek(SeekFrom::End(i64::try_from(#num).unwrap())) {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else if let Some(num) = &f.seek_from_start {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                use ::#crate_::no_std_io::SeekFrom;
+                if let Err(e) = __deku_reader.seek(SeekFrom::Start(u64::try_from(#num).unwrap())) {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else if f.seek_rewind {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                if let Err(e) = __deku_reader.rewind() {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else {
+        quote! {}
+    };
+
     let (bit_offset, byte_offset) = emit_bit_byte_offsets(&field_check_vars);
 
     let field_map = f
@@ -761,6 +849,7 @@ fn emit_field_read(
     };
 
     let field_read = quote! {
+        #seek
         #pad_bits_before
 
         #bit_offset
@@ -795,7 +884,7 @@ pub fn emit_container_read(
         impl #imp ::#crate_::DekuContainerRead<#lifetime> for #ident #wher {
             #[allow(non_snake_case)]
             #[inline]
-            fn from_reader<'a, R: ::#crate_::no_std_io::Read>(__deku_input: (&'a mut R, usize)) -> core::result::Result<(usize, Self), ::#crate_::DekuError> {
+            fn from_reader<'a, R: ::#crate_::no_std_io::Read + ::#crate_::no_std_io::Seek>(__deku_input: (&'a mut R, usize)) -> core::result::Result<(usize, Self), ::#crate_::DekuError> {
                 #from_reader_body
             }
 
diff --git a/deku-derive/src/macros/deku_write.rs b/deku-derive/src/macros/deku_write.rs
index 871d162..4ca8d0d 100644
--- a/deku-derive/src/macros/deku_write.rs
+++ b/deku-derive/src/macros/deku_write.rs
@@ -28,6 +28,49 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {
         fields,
     } = DekuDataStruct::try_from(input)?;
 
+    let seek = if let Some(num) = &input.seek_from_current {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                use ::#crate_::no_std_io::SeekFrom;
+                if let Err(e) = __deku_writer.seek(SeekFrom::Current(i64::try_from(#num).unwrap())) {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else if let Some(num) = &input.seek_from_end {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                use ::#crate_::no_std_io::SeekFrom;
+                if let Err(e) = __deku_writer.seek(SeekFrom::End(i64::try_from(#num).unwrap())) {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else if let Some(num) = &input.seek_from_start {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                use ::#crate_::no_std_io::SeekFrom;
+                if let Err(e) = __deku_writer.seek(SeekFrom::Start(u64::try_from(#num).unwrap())) {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else if input.seek_rewind {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                if let Err(e) = __deku_writer.rewind() {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else {
+        quote! {}
+    };
+
     let magic_write = emit_magic_write(input);
 
     let field_writes = emit_field_writes(input, &fields, None, &ident)?;
@@ -76,6 +119,7 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {
     let write_body = quote! {
         match *self {
             #destructured => {
+                #seek
                 #magic_write
                 #(#field_writes)*
 
@@ -101,7 +145,7 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {
         impl #imp ::#crate_::DekuWriter<#ctx_types> for #ident #wher {
             #[allow(unused_variables)]
             #[inline]
-            fn to_writer<W: ::#crate_::no_std_io::Write>(&self, __deku_writer: &mut ::#crate_::writer::Writer<W>, #ctx_arg) -> core::result::Result<(), ::#crate_::DekuError> {
+            fn to_writer<W: ::#crate_::no_std_io::Write + ::#crate_::no_std_io::Seek>(&self, __deku_writer: &mut ::#crate_::writer::Writer<W>, #ctx_arg) -> core::result::Result<(), ::#crate_::DekuError> {
                 #write_body
             }
         }
@@ -114,7 +158,7 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {
             impl #imp ::#crate_::DekuWriter for #ident #wher {
                 #[allow(unused_variables)]
                 #[inline]
-                fn to_writer<W: ::#crate_::no_std_io::Write>(&self, __deku_writer: &mut ::#crate_::writer::Writer<W>, _: ()) -> core::result::Result<(), ::#crate_::DekuError> {
+                fn to_writer<W: ::#crate_::no_std_io::Write + ::#crate_::no_std_io::Seek>(&self, __deku_writer: &mut ::#crate_::writer::Writer<W>, _: ()) -> core::result::Result<(), ::#crate_::DekuError> {
                     #write_body
                 }
             }
@@ -299,7 +343,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
         impl #imp ::#crate_::DekuWriter<#ctx_types> for #ident #wher {
             #[allow(unused_variables)]
             #[inline]
-            fn to_writer<W: ::#crate_::no_std_io::Write>(&self, __deku_writer: &mut ::#crate_::writer::Writer<W>, #ctx_arg) -> core::result::Result<(), ::#crate_::DekuError> {
+            fn to_writer<W: ::#crate_::no_std_io::Write + ::#crate_::no_std_io::Seek>(&self, __deku_writer: &mut ::#crate_::writer::Writer<W>, #ctx_arg) -> core::result::Result<(), ::#crate_::DekuError> {
                 #write_body
             }
         }
@@ -312,7 +356,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
             impl #imp ::#crate_::DekuWriter for #ident #wher {
                 #[allow(unused_variables)]
                 #[inline]
-                fn to_writer<W: ::#crate_::no_std_io::Write>(&self, __deku_writer: &mut ::#crate_::writer::Writer<W>, _: ()) -> core::result::Result<(), ::#crate_::DekuError> {
+                fn to_writer<W: ::#crate_::no_std_io::Write + ::#crate_::no_std_io::Seek>(&self, __deku_writer: &mut ::#crate_::writer::Writer<W>, _: ()) -> core::result::Result<(), ::#crate_::DekuError> {
                     #write_body
                 }
             }
@@ -438,6 +482,49 @@ fn emit_field_write(
     let crate_ = super::get_crate_name();
     let field_endian = f.endian.as_ref().or(input.endian.as_ref());
 
+    let seek = if let Some(num) = &f.seek_from_current {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                use ::#crate_::no_std_io::SeekFrom;
+                if let Err(e) = __deku_writer.seek(SeekFrom::Current(i64::try_from(#num).unwrap())) {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else if let Some(num) = &f.seek_from_end {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                use ::#crate_::no_std_io::SeekFrom;
+                if let Err(e) = __deku_writer.seek(SeekFrom::End(i64::try_from(#num).unwrap())) {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else if let Some(num) = &f.seek_from_start {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                use ::#crate_::no_std_io::SeekFrom;
+                if let Err(e) = __deku_writer.seek(SeekFrom::Start(u64::try_from(#num).unwrap())) {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else if f.seek_rewind {
+        quote! {
+            {
+                use ::#crate_::no_std_io::Seek;
+                if let Err(e) = __deku_writer.rewind() {
+                    return Err(DekuError::Io(e.kind()));
+                }
+            }
+        }
+    } else {
+        quote! {}
+    };
+
     // fields to check usage of bit/byte offset
     let field_check_vars = [
         &f.writer,
@@ -559,6 +646,7 @@ fn emit_field_write(
     };
 
     let field_write = quote! {
+        #seek
         #pad_bits_before
 
         #bit_offset
diff --git a/examples/custom_reader_and_writer.rs b/examples/custom_reader_and_writer.rs
index 10a5511..d3903af 100644
--- a/examples/custom_reader_and_writer.rs
+++ b/examples/custom_reader_and_writer.rs
@@ -3,9 +3,9 @@ use std::convert::TryInto;
 use deku::ctx::BitSize;
 use deku::writer::Writer;
 use deku::{prelude::*, DekuWriter};
-use no_std_io::io::Write;
+use no_std_io::io::{Seek, Write};
 
-fn bit_flipper_read<R: std::io::Read>(
+fn bit_flipper_read<R: std::io::Read + std::io::Seek>(
     field_a: u8,
     reader: &mut Reader<R>,
     bit_size: BitSize,
@@ -25,7 +25,7 @@ fn bit_flipper_read<R: std::io::Read>(
     Ok(value)
 }
 
-fn bit_flipper_write<W: Write>(
+fn bit_flipper_write<W: Write + Seek>(
     field_a: u8,
     field_b: u8,
     writer: &mut Writer<W>,
@@ -59,8 +59,9 @@ struct DekuTest {
 
 fn main() {
     let test_data = [0x01, 0b1001_0110];
+    let mut cursor = std::io::Cursor::new(test_data);
 
-    let (_read_amt, ret_read) = DekuTest::from_reader((&mut test_data.as_slice(), 0)).unwrap();
+    let (_read_amt, ret_read) = DekuTest::from_reader((&mut cursor, 0)).unwrap();
 
     assert_eq!(
         ret_read,
diff --git a/examples/deku_input.rs b/examples/deku_input.rs
index 34974a5..7614eaf 100644
--- a/examples/deku_input.rs
+++ b/examples/deku_input.rs
@@ -1,15 +1,15 @@
 //! Example of a close replacement for deku::input
 use deku::prelude::*;
-use std::io::{self, Cursor, Read};
+use std::io::{self, Cursor, Read, Seek, SeekFrom};
 
 /// Every read to this struct will be saved into an internal cache. This is to keep the cache
 /// around for the crc without reading from the buffer twice
-struct ReaderCrc<R: Read> {
+struct ReaderCrc<R: Read + Seek> {
     reader: R,
     pub cache: Vec<u8>,
 }
 
-impl<R: Read> ReaderCrc<R> {
+impl<R: Read + Seek> ReaderCrc<R> {
     pub fn new(reader: R) -> Self {
         Self {
             reader,
@@ -18,7 +18,7 @@ impl<R: Read> ReaderCrc<R> {
     }
 }
 
-impl<R: Read> Read for ReaderCrc<R> {
+impl<R: Read + Seek> Read for ReaderCrc<R> {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         let n = self.reader.read(buf);
         self.cache.extend_from_slice(buf);
@@ -26,6 +26,12 @@ impl<R: Read> Read for ReaderCrc<R> {
     }
 }
 
+impl<R: Read + Seek> Seek for ReaderCrc<R> {
+    fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
+        self.reader.seek(pos)
+    }
+}
+
 #[derive(Debug, DekuRead)]
 pub struct DekuStruct {
     pub a: u8,
diff --git a/src/attributes.rs b/src/attributes.rs
index ba66f25..3be50e8 100644
--- a/src/attributes.rs
+++ b/src/attributes.rs
@@ -34,6 +34,10 @@ enum DekuEnum {
 |-----------|------------------|------------
 | [endian](#endian) | top-level, field | Set the endianness
 | [magic](#magic) | top-level | A magic value that must be present at the start of this struct/enum
+| [seek_from_current](#seek_from_current) | top-level, field | Sets the offset of reader and writer to the current position plus the specified number of bytes
+| [seek_from_end](#seek_from_end) | top-level, field | Sets the offset to the size of reader and writer plus the specified number of bytes
+| [seek_from_start](#seek_from_start) | top-level, field | Sets the offset of reader and writer to provided number of bytes
+| [seek_rewind](#seek_rewind) | top-level, field | Rewind the reader and writer to the beginning
 | [assert](#assert) | field | Assert a condition
 | [assert_eq](#assert_eq) | field | Assert equals on the field
 | [bits](#bits) | field | Set the bit-size of the field
@@ -53,7 +57,7 @@ enum DekuEnum {
 | [pad_bits_after](#pad_bits_after) | field | Skip bits after reading, pad after writing
 | [cond](#cond) | field | Conditional expression for the field
 | [default](#default) | field | Provide default value. Used with [skip](#skip) or [cond](#cond)
-| [map](#map) | field | Apply a function over the result of reading
+| [bits](#bits) | field | Set the bit-size of the field
 | [reader](#readerwriter) | variant, field | Custom reader code
 | [writer](#readerwriter) | variant, field | Custom writer code
 | [ctx](#ctx) | top-level, field| Context list for context sensitive parsing
@@ -172,6 +176,256 @@ let value: Vec<u8> = value.try_into().unwrap();
 assert_eq!(data, value);
 ```
 
+# seek_from_current
+
+Using the internal reader, seek to current position plus offset before reading field.
+
+Field Example:
+
+```rust
+# use deku::prelude::*;
+# use std::io::Cursor;
+# use std::convert::{TryInto, TryFrom};
+#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
+struct DekuTest {
+    // how many following bytes to skip
+    skip_u8: u8,
+    #[deku(seek_from_current = "*skip_u8")]
+    byte: u8,
+}
+
+let data: &[u8] = &[0x01, 0x00, 0x02];
+let mut cursor = Cursor::new(data);
+
+let (_amt_read, value) = DekuTest::from_reader((&mut cursor, 0)).unwrap();
+
+assert_eq!(
+    DekuTest { skip_u8: 0x01, byte: 0x02 },
+    value
+);
+
+let bytes = value.to_bytes().unwrap();
+assert_eq!(bytes, data);
+```
+
+Top-Level Example (with ctx usage):
+
+```rust
+# use deku::prelude::*;
+# use std::io::Cursor;
+# use std::convert::{TryInto, TryFrom};
+#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
+#[deku(seek_from_current = "skip", ctx = "skip: usize")]
+struct DekuTest {
+    byte: u8,
+}
+
+let data: &[u8] = &[0x00, 0x02];
+let mut cursor = Cursor::new(data);
+let mut reader = Reader::new(&mut cursor);
+
+let value = DekuTest::from_reader_with_ctx(&mut reader, 1).unwrap();
+
+assert_eq!(
+    DekuTest { byte: 0x02 },
+    value
+);
+
+let mut buf = vec![];
+let mut cursor = Cursor::new(&mut buf);
+let mut writer = Writer::new(&mut cursor);
+let bytes = value.to_writer(&mut writer, 1).unwrap();
+assert_eq!(buf, data);
+```
+
+# seek_from_end
+
+Using the internal reader, seek to size of reader plus offset before reading field.
+
+Field Example:
+
+```rust
+# use deku::prelude::*;
+# use std::io::Cursor;
+# use std::convert::{TryInto, TryFrom};
+#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
+struct DekuTest {
+    #[deku(seek_from_end = "-2")]
+    byte: u8,
+}
+
+let data: &[u8] = &[0x01, 0xff, 0x02];
+let mut cursor = Cursor::new(data);
+
+let (_amt_read, value) = DekuTest::from_reader((&mut cursor, 0)).unwrap();
+
+assert_eq!(
+    DekuTest { byte: 0xff },
+    value
+);
+
+// NOTE: to_bytes() doesn't work, because we need `seek_from_end` to already
+// have a correct allocated buffer length!
+let mut buf = vec![0x01, 0x00, 0x02];
+let mut cursor = Cursor::new(&mut buf);
+let mut writer = Writer::new(&mut cursor);
+let _ = value.to_writer(&mut writer, ()).unwrap();
+assert_eq!(buf, data);
+```
+
+Top-Level Example:
+
+```rust
+# use deku::prelude::*;
+# use std::io::Cursor;
+# use std::convert::{TryInto, TryFrom};
+#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
+#[deku(seek_from_end = "-2")]
+struct DekuTest {
+    byte: u8,
+}
+
+let data: &[u8] = &[0x01, 0xff, 0x02];
+let mut cursor = Cursor::new(data);
+
+let (_amt_read, value) = DekuTest::from_reader((&mut cursor, 0)).unwrap();
+
+assert_eq!(
+    DekuTest { byte: 0xff },
+    value
+);
+
+// NOTE: to_bytes() doesn't work, because we need `seek_from_end` to already
+// have a correct allocated buffer length!
+let mut buf = vec![0x01, 0x00, 0x02];
+let mut cursor = Cursor::new(&mut buf);
+let mut writer = Writer::new(&mut cursor);
+let _ = value.to_writer(&mut writer, ()).unwrap();
+assert_eq!(buf, data);
+```
+
+# seek_from_start
+
+Using the internal reader, seek from reader start plus offset before reading field.
+
+Field Example:
+
+```rust
+# use deku::prelude::*;
+# use std::io::Cursor;
+# use std::convert::{TryInto, TryFrom};
+#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
+struct DekuTest {
+    #[deku(seek_from_start = "2")]
+    byte: u8,
+}
+
+let data: &[u8] = &[0x01, 0xff, 0x02];
+let mut cursor = Cursor::new(data);
+
+let (_amt_read, value) = DekuTest::from_reader((&mut cursor, 0)).unwrap();
+
+assert_eq!(
+    DekuTest { byte: 0x02 },
+    value
+);
+
+// NOTE: to_bytes() doesn't work, because we need `seek_from_start` to already
+// have a correct allocated buffer length!
+let mut buf = vec![0x01, 0xff, 0x00];
+let mut cursor = Cursor::new(&mut buf);
+let mut writer = Writer::new(&mut cursor);
+let _ = value.to_writer(&mut writer, ()).unwrap();
+assert_eq!(buf, data);
+```
+
+Top-Leve Example:
+
+```rust
+# use deku::prelude::*;
+# use std::io::Cursor;
+# use std::convert::{TryInto, TryFrom};
+#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
+#[deku(seek_from_start = "2")]
+struct DekuTest {
+    byte: u8,
+}
+
+let data: &[u8] = &[0x01, 0xff, 0x02];
+let mut cursor = Cursor::new(data);
+
+let (_amt_read, value) = DekuTest::from_reader((&mut cursor, 0)).unwrap();
+
+assert_eq!(
+    DekuTest { byte: 0x02 },
+    value
+);
+
+// NOTE: to_bytes() doesn't work, because we need `seek_from_start` to already
+// have a correct allocated buffer length!
+let mut buf = vec![0x01, 0xff, 0x00];
+let mut cursor = Cursor::new(&mut buf);
+let mut writer = Writer::new(&mut cursor);
+let _ = value.to_writer(&mut writer, ()).unwrap();
+assert_eq!(buf, data);
+```
+
+# seek_rewind
+
+Rewind the internal reader to starting position.
+
+Field Example:
+
+```rust
+# use deku::prelude::*;
+# use std::io::Cursor;
+# use std::convert::{TryInto, TryFrom};
+#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
+struct DekuTest {
+    byte_01: u8,
+    #[deku(seek_rewind)]
+    byte_02: u8,
+}
+
+let data: &[u8] = &[0xff];
+let mut cursor = Cursor::new(data);
+
+let (_amt_read, value) = DekuTest::from_reader((&mut cursor, 0)).unwrap();
+
+assert_eq!(
+    DekuTest { byte_01: 0xff, byte_02: 0xff },
+    value
+);
+let bytes = value.to_bytes().unwrap();
+assert_eq!(bytes, data);
+```
+
+Top-Level Example:
+
+```rust
+# use deku::prelude::*;
+# use std::io::Cursor;
+# use std::convert::{TryInto, TryFrom};
+#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
+#[deku(seek_rewind)]
+struct DekuTest {
+    byte: u8,
+}
+
+let data: &[u8] = &[0xff];
+let mut cursor = Cursor::new(data);
+
+let (_amt_read, value) = DekuTest::from_reader((&mut cursor, 0)).unwrap();
+
+assert_eq!(
+    DekuTest { byte: 0xff},
+    value
+);
+let bytes = value.to_bytes().unwrap();
+assert_eq!(bytes, data);
+```
+
+
 # assert
 
 Assert a condition after reading and before writing a field
@@ -848,7 +1102,7 @@ struct DekuTest {
 
 impl DekuTest {
     /// Read and convert to String
-    fn read<R: std::io::Read>(
+    fn read<R: std::io::Read + std::io::Seek>(
         reader: &mut deku::reader::Reader<R>,
     ) -> Result<String, DekuError> {
         let value = u8::from_reader_with_ctx(reader, ())?;
@@ -856,7 +1110,7 @@ impl DekuTest {
     }
 
     /// Parse from String to u8 and write
-    fn write<W: std::io::Write>(writer: &mut Writer<W>, field_a: &str) -> Result<(), DekuError> {
+    fn write<W: std::io::Write + std::io::Seek>(writer: &mut Writer<W>, field_a: &str) -> Result<(), DekuError> {
         let value = field_a.parse::<u8>().unwrap();
         value.to_writer(writer, ())
     }
diff --git a/src/impls/bool.rs b/src/impls/bool.rs
index 1b1ee96..e8f2743 100644
--- a/src/impls/bool.rs
+++ b/src/impls/bool.rs
@@ -1,4 +1,4 @@
-use no_std_io::io::{Read, Write};
+use no_std_io::io::{Read, Seek, Write};
 
 #[cfg(feature = "alloc")]
 use alloc::borrow::Cow;
@@ -14,7 +14,7 @@ where
     Ctx: Copy,
     u8: DekuReader<'a, Ctx>,
 {
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut Reader<R>,
         inner_ctx: Ctx,
     ) -> Result<bool, DekuError> {
@@ -37,7 +37,11 @@ where
     u8: DekuWriter<Ctx>,
 {
     /// wrapper around u8::write with consideration to context, such as bit size
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, inner_ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        inner_ctx: Ctx,
+    ) -> Result<(), DekuError> {
         match self {
             true => (0x01u8).to_writer(writer, inner_ctx),
             false => (0x00u8).to_writer(writer, inner_ctx),
@@ -62,8 +66,9 @@ mod tests {
         #[should_panic(expected = "Parse(\"cannot parse bool value: 2\")")]
         case(&hex!("02"), false),
     )]
-    fn test_bool(mut input: &[u8], expected: bool) {
-        let mut reader = Reader::new(&mut input);
+    fn test_bool(input: &[u8], expected: bool) {
+        let mut cursor = Cursor::new(input);
+        let mut reader = Reader::new(&mut cursor);
         let res_read = bool::from_reader_with_ctx(&mut reader, ()).unwrap();
         assert_eq!(expected, res_read);
     }
@@ -80,16 +85,16 @@ mod tests {
 
     #[test]
     fn test_writer() {
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         true.to_writer(&mut writer, BitSize(1)).unwrap();
         assert_eq!(vec![true], writer.rest());
 
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         true.to_writer(&mut writer, ()).unwrap();
-        assert_eq!(vec![1], writer.inner);
+        assert_eq!(vec![1], writer.inner.into_inner());
 
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         false.to_writer(&mut writer, ()).unwrap();
-        assert_eq!(vec![0], writer.inner);
+        assert_eq!(vec![0], writer.inner.into_inner());
     }
 }
diff --git a/src/impls/boxed.rs b/src/impls/boxed.rs
index a24a47f..46011b0 100644
--- a/src/impls/boxed.rs
+++ b/src/impls/boxed.rs
@@ -1,4 +1,4 @@
-use no_std_io::io::{Read, Write};
+use no_std_io::io::{Read, Seek, Write};
 
 use alloc::boxed::Box;
 use alloc::vec::Vec;
@@ -13,7 +13,7 @@ where
     T: DekuReader<'a, Ctx>,
     Ctx: Copy,
 {
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut Reader<R>,
         inner_ctx: Ctx,
     ) -> Result<Self, DekuError> {
@@ -28,7 +28,7 @@ where
     Ctx: Copy,
     Predicate: FnMut(&T) -> bool,
 {
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut Reader<R>,
         (limit, inner_ctx): (Limit<T, Predicate>, Ctx),
     ) -> Result<Self, DekuError> {
@@ -44,7 +44,11 @@ where
     Ctx: Copy,
 {
     /// Write all `T`s to bits
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        ctx: Ctx,
+    ) -> Result<(), DekuError> {
         for v in self.as_ref() {
             v.to_writer(writer, ctx)?;
         }
@@ -58,7 +62,11 @@ where
     Ctx: Copy,
 {
     /// Write all `T`s to bits
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        ctx: Ctx,
+    ) -> Result<(), DekuError> {
         self.as_ref().to_writer(writer, ctx)?;
         Ok(())
     }
@@ -87,9 +95,9 @@ mod tests {
         let res_read = <Box<u16>>::from_reader_with_ctx(&mut reader, ()).unwrap();
         assert_eq!(expected, res_read);
 
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         res_read.to_writer(&mut writer, ()).unwrap();
-        assert_eq!(input.to_vec(), writer.inner);
+        assert_eq!(input.to_vec(), writer.inner.into_inner());
     }
 
     // Note: Copied tests from vec.rs impl
@@ -130,11 +138,11 @@ mod tests {
 
         assert_eq!(input[..expected_write.len()].to_vec(), expected_write);
 
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         res_read
             .to_writer(&mut writer, (endian, BitSize(bit_size)))
             .unwrap();
-        assert_eq!(expected_write, writer.inner);
+        assert_eq!(expected_write, writer.inner.into_inner());
 
         assert_eq!(input[..expected_write.len()].to_vec(), expected_write);
     }
diff --git a/src/impls/cow.rs b/src/impls/cow.rs
index c2461ab..e903f0e 100644
--- a/src/impls/cow.rs
+++ b/src/impls/cow.rs
@@ -1,6 +1,6 @@
 use std::borrow::{Borrow, Cow};
 
-use no_std_io::io::{Read, Write};
+use no_std_io::io::{Read, Seek, Write};
 
 use crate::reader::Reader;
 use crate::writer::Writer;
@@ -11,7 +11,7 @@ where
     T: DekuReader<'a, Ctx> + Clone,
     Ctx: Copy,
 {
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut Reader<R>,
         inner_ctx: Ctx,
     ) -> Result<Self, DekuError> {
@@ -26,7 +26,11 @@ where
     Ctx: Copy,
 {
     /// Write T from Cow<T>
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, inner_ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        inner_ctx: Ctx,
+    ) -> Result<(), DekuError> {
         (self.borrow() as &T).to_writer(writer, inner_ctx)
     }
 }
@@ -51,8 +55,8 @@ mod tests {
         let res_read = <Cow<u16>>::from_reader_with_ctx(&mut reader, ()).unwrap();
         assert_eq!(expected, res_read);
 
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         res_read.to_writer(&mut writer, ()).unwrap();
-        assert_eq!(input.to_vec(), writer.inner);
+        assert_eq!(input.to_vec(), writer.inner.into_inner());
     }
 }
diff --git a/src/impls/cstring.rs b/src/impls/cstring.rs
index 02ba1c8..d0796b1 100644
--- a/src/impls/cstring.rs
+++ b/src/impls/cstring.rs
@@ -1,5 +1,5 @@
 use alloc::borrow::Cow;
-use no_std_io::io::{Read, Write};
+use no_std_io::io::{Read, Seek, Write};
 use std::ffi::CString;
 
 use crate::reader::Reader;
@@ -11,7 +11,11 @@ impl<Ctx: Copy> DekuWriter<Ctx> for CString
 where
     u8: DekuWriter<Ctx>,
 {
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        ctx: Ctx,
+    ) -> Result<(), DekuError> {
         let bytes = self.as_bytes_with_nul();
         bytes.to_writer(writer, ctx)
     }
@@ -21,7 +25,7 @@ impl<'a, Ctx: Copy> DekuReader<'a, Ctx> for CString
 where
     u8: DekuReader<'a, Ctx>,
 {
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut Reader<R>,
         inner_ctx: Ctx,
     ) -> Result<Self, DekuError> {
@@ -69,8 +73,11 @@ mod tests {
         cursor.read_to_end(&mut buf).unwrap();
         assert_eq!(expected_rest, buf);
 
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         res_read.to_writer(&mut writer, ()).unwrap();
-        assert_eq!(vec![b't', b'e', b's', b't', b'\0'], writer.inner);
+        assert_eq!(
+            vec![b't', b'e', b's', b't', b'\0'],
+            writer.inner.into_inner()
+        );
     }
 }
diff --git a/src/impls/hashmap.rs b/src/impls/hashmap.rs
index 7851810..c4bdcb0 100644
--- a/src/impls/hashmap.rs
+++ b/src/impls/hashmap.rs
@@ -1,7 +1,7 @@
 use std::collections::HashMap;
 use std::hash::{BuildHasher, Hash};
 
-use no_std_io::io::{Read, Write};
+use no_std_io::io::{Read, Seek, Write};
 
 use crate::ctx::*;
 use crate::writer::Writer;
@@ -15,7 +15,7 @@ use crate::{DekuError, DekuReader, DekuWriter};
 /// and a borrow of the latest value to have been read. It should return `true` if reading
 /// should now stop, and `false` otherwise
 #[allow(clippy::type_complexity)]
-fn from_reader_with_ctx_hashmap_with_predicate<'a, K, V, S, Ctx, Predicate, R: Read>(
+fn from_reader_with_ctx_hashmap_with_predicate<'a, K, V, S, Ctx, Predicate, R: Read + Seek>(
     reader: &mut crate::reader::Reader<R>,
     capacity: Option<usize>,
     ctx: Ctx,
@@ -42,7 +42,7 @@ where
     Ok(res)
 }
 
-fn from_reader_with_ctx_hashmap_to_end<'a, K, V, S, Ctx, R: Read>(
+fn from_reader_with_ctx_hashmap_to_end<'a, K, V, S, Ctx, R: Read + Seek>(
     reader: &mut crate::reader::Reader<R>,
     capacity: Option<usize>,
     ctx: Ctx,
@@ -92,7 +92,7 @@ where
     /// expected.insert(100, 0x04030201);
     /// assert_eq!(expected, map)
     /// ```
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut crate::reader::Reader<R>,
         (limit, inner_ctx): (Limit<(K, V), Predicate>, Ctx),
     ) -> Result<Self, DekuError>
@@ -175,7 +175,7 @@ where
     Predicate: FnMut(&(K, V)) -> bool,
 {
     /// Read `K, V`s until the given limit from input for types which don't require context.
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut crate::reader::Reader<R>,
         limit: Limit<(K, V), Predicate>,
     ) -> Result<Self, DekuError>
@@ -198,15 +198,21 @@ impl<K: DekuWriter<Ctx>, V: DekuWriter<Ctx>, S, Ctx: Copy> DekuWriter<Ctx> for H
     /// # use deku::writer::Writer;
     /// # use deku::bitvec::{Msb0, bitvec};
     /// # use std::collections::HashMap;
+    /// # use std::io::Cursor;
     /// let mut out_buf = vec![];
-    /// let mut writer = Writer::new(&mut out_buf);
+    /// let mut cursor = Cursor::new(&mut out_buf);
+    /// let mut writer = Writer::new(&mut cursor);
     /// let mut map = HashMap::<u8, u32>::default();
     /// map.insert(100, 0x04030201);
     /// map.to_writer(&mut writer, Endian::Big).unwrap();
     /// let expected: Vec<u8> = vec![100, 4, 3, 2, 1];
     /// assert_eq!(expected, out_buf);
     /// ```
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, inner_ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        inner_ctx: Ctx,
+    ) -> Result<(), DekuError> {
         for kv in self {
             kv.to_writer(writer, inner_ctx)?;
         }
@@ -302,8 +308,8 @@ mod tests {
         case::normal(fxhashmap!{0x11u8 => 0xAABBu16, 0x23u8 => 0xCCDDu16}, Endian::Little, vec![0x11, 0xBB, 0xAA, 0x23, 0xDD, 0xCC]),
     )]
     fn test_hashmap_write(input: FxHashMap<u8, u16>, endian: Endian, expected: Vec<u8>) {
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         input.to_writer(&mut writer, endian).unwrap();
-        assert_eq!(expected, writer.inner);
+        assert_eq!(expected, writer.inner.into_inner());
     }
 }
diff --git a/src/impls/hashset.rs b/src/impls/hashset.rs
index 39f61ce..4938261 100644
--- a/src/impls/hashset.rs
+++ b/src/impls/hashset.rs
@@ -2,7 +2,7 @@ use std::collections::HashSet;
 use std::hash::{BuildHasher, Hash};
 
 use crate::writer::Writer;
-use no_std_io::io::{Read, Write};
+use no_std_io::io::{Read, Seek, Write};
 
 use crate::ctx::*;
 use crate::{DekuError, DekuReader, DekuWriter};
@@ -15,7 +15,7 @@ use crate::{DekuError, DekuReader, DekuWriter};
 /// and a borrow of the latest value to have been read. It should return `true` if reading
 /// should now stop, and `false` otherwise
 #[allow(clippy::type_complexity)]
-fn from_reader_with_ctx_hashset_with_predicate<'a, T, S, Ctx, Predicate, R: Read>(
+fn from_reader_with_ctx_hashset_with_predicate<'a, T, S, Ctx, Predicate, R: Read + Seek>(
     reader: &mut crate::reader::Reader<R>,
     capacity: Option<usize>,
     ctx: Ctx,
@@ -41,7 +41,7 @@ where
     Ok(res)
 }
 
-fn from_reader_with_ctx_hashset_to_end<'a, T, S, Ctx, R: Read>(
+fn from_reader_with_ctx_hashset_to_end<'a, T, S, Ctx, R: Read + Seek>(
     reader: &mut crate::reader::Reader<R>,
     capacity: Option<usize>,
     ctx: Ctx,
@@ -86,7 +86,7 @@ where
     /// let set = HashSet::<u32>::from_reader_with_ctx(&mut reader, (1.into(), Endian::Little)).unwrap();
     /// assert_eq!(expected, set)
     /// ```
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut crate::reader::Reader<R>,
         (limit, inner_ctx): (Limit<T, Predicate>, Ctx),
     ) -> Result<Self, DekuError>
@@ -165,7 +165,7 @@ impl<'a, T: DekuReader<'a> + Eq + Hash, S: BuildHasher + Default, Predicate: FnM
     DekuReader<'a, Limit<T, Predicate>> for HashSet<T, S>
 {
     /// Read `T`s until the given limit from input for types which don't require context.
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut crate::reader::Reader<R>,
         limit: Limit<T, Predicate>,
     ) -> Result<Self, DekuError>
@@ -188,13 +188,19 @@ impl<T: DekuWriter<Ctx>, S, Ctx: Copy> DekuWriter<Ctx> for HashSet<T, S> {
     /// # use deku::writer::Writer;
     /// # use deku::bitvec::{Msb0, bitvec};
     /// # use std::collections::HashSet;
+    /// # use std::io::Cursor;
     /// let mut out_buf = vec![];
-    /// let mut writer = Writer::new(&mut out_buf);
+    /// let mut cursor = Cursor::new(&mut out_buf);
+    /// let mut writer = Writer::new(&mut cursor);
     /// let set: HashSet<u8> = vec![1].into_iter().collect();
     /// set.to_writer(&mut writer, Endian::Big).unwrap();
     /// assert_eq!(out_buf, vec![1]);
     /// ```
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, inner_ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        inner_ctx: Ctx,
+    ) -> Result<(), DekuError> {
         for v in self {
             v.to_writer(writer, inner_ctx)?;
         }
@@ -271,9 +277,9 @@ mod tests {
         case::normal(vec![0xAABB, 0xCCDD].into_iter().collect(), Endian::Little, vec![0xDD, 0xCC, 0xBB, 0xAA]),
     )]
     fn test_hashset_write(input: FxHashSet<u16>, endian: Endian, expected: Vec<u8>) {
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         input.to_writer(&mut writer, endian).unwrap();
-        assert_eq!(expected, writer.inner);
+        assert_eq!(expected, writer.inner.into_inner());
     }
 
     // Note: These tests also exist in boxed.rs
@@ -314,10 +320,10 @@ mod tests {
         cursor.read_to_end(&mut buf).unwrap();
         assert_eq!(expected_rest_bytes, buf);
 
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         res_read
             .to_writer(&mut writer, (endian, BitSize(bit_size)))
             .unwrap();
-        assert_eq!(expected_write, writer.inner);
+        assert_eq!(expected_write, writer.inner.into_inner());
     }
 }
diff --git a/src/impls/ipaddr.rs b/src/impls/ipaddr.rs
index 36e3053..182a687 100644
--- a/src/impls/ipaddr.rs
+++ b/src/impls/ipaddr.rs
@@ -1,6 +1,6 @@
 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
 
-use no_std_io::io::{Read, Write};
+use no_std_io::io::{Read, Seek, Write};
 
 use crate::reader::Reader;
 use crate::writer::Writer;
@@ -10,7 +10,7 @@ impl<'a, Ctx> DekuReader<'a, Ctx> for Ipv4Addr
 where
     u32: DekuReader<'a, Ctx>,
 {
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut Reader<R>,
         inner_ctx: Ctx,
     ) -> Result<Self, DekuError> {
@@ -23,7 +23,11 @@ impl<Ctx> DekuWriter<Ctx> for Ipv4Addr
 where
     u32: DekuWriter<Ctx>,
 {
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        ctx: Ctx,
+    ) -> Result<(), DekuError> {
         let ip: u32 = (*self).into();
         ip.to_writer(writer, ctx)
     }
@@ -33,7 +37,7 @@ impl<'a, Ctx> DekuReader<'a, Ctx> for Ipv6Addr
 where
     u128: DekuReader<'a, Ctx>,
 {
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut Reader<R>,
         inner_ctx: Ctx,
     ) -> Result<Self, DekuError> {
@@ -46,7 +50,11 @@ impl<Ctx> DekuWriter<Ctx> for Ipv6Addr
 where
     u128: DekuWriter<Ctx>,
 {
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        ctx: Ctx,
+    ) -> Result<(), DekuError> {
         let ip: u128 = (*self).into();
         ip.to_writer(writer, ctx)
     }
@@ -57,7 +65,11 @@ where
     Ipv6Addr: DekuWriter<Ctx>,
     Ipv4Addr: DekuWriter<Ctx>,
 {
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        ctx: Ctx,
+    ) -> Result<(), DekuError> {
         match self {
             IpAddr::V4(ipv4) => ipv4.to_writer(writer, ctx),
             IpAddr::V6(ipv6) => ipv6.to_writer(writer, ctx),
@@ -83,9 +95,9 @@ mod tests {
         let res_read = Ipv4Addr::from_reader_with_ctx(&mut reader, endian).unwrap();
         assert_eq!(expected, res_read);
 
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         res_read.to_writer(&mut writer, endian).unwrap();
-        assert_eq!(input.to_vec(), writer.inner);
+        assert_eq!(input.to_vec(), writer.inner.into_inner());
     }
 
     #[rstest(input, endian, expected,
@@ -98,28 +110,28 @@ mod tests {
         let res_read = Ipv6Addr::from_reader_with_ctx(&mut reader, endian).unwrap();
         assert_eq!(expected, res_read);
 
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         res_read.to_writer(&mut writer, endian).unwrap();
-        assert_eq!(input.to_vec(), writer.inner);
+        assert_eq!(input.to_vec(), writer.inner.into_inner());
     }
 
     #[test]
     fn test_ip_addr_write() {
         let ip_addr = IpAddr::V4(Ipv4Addr::new(145, 254, 160, 237));
 
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         ip_addr.to_writer(&mut writer, Endian::Little).unwrap();
-        assert_eq!(vec![237, 160, 254, 145], writer.inner);
+        assert_eq!(vec![237, 160, 254, 145], writer.inner.into_inner());
 
         let ip_addr = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x02ff));
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         ip_addr.to_writer(&mut writer, Endian::Little).unwrap();
         assert_eq!(
             vec![
                 0xff, 0x02, 0x0a, 0xc0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                 0x00, 0x00
             ],
-            writer.inner
+            writer.inner.into_inner()
         );
     }
 }
diff --git a/src/impls/nonzero.rs b/src/impls/nonzero.rs
index 62e6539..a9eefc8 100644
--- a/src/impls/nonzero.rs
+++ b/src/impls/nonzero.rs
@@ -3,7 +3,7 @@ use alloc::borrow::Cow;
 #[cfg(feature = "alloc")]
 use alloc::format;
 use core::num::*;
-use no_std_io::io::{Read, Write};
+use no_std_io::io::{Read, Seek, Write};
 
 use crate::ctx::*;
 use crate::reader::Reader;
@@ -13,7 +13,7 @@ use crate::{DekuError, DekuReader, DekuWriter};
 macro_rules! ImplDekuTraitsCtx {
     ($typ:ty, $readtype:ty, $ctx_arg:tt, $ctx_type:tt) => {
         impl DekuReader<'_, $ctx_type> for $typ {
-            fn from_reader_with_ctx<R: Read>(
+            fn from_reader_with_ctx<R: Read + Seek>(
                 reader: &mut Reader<R>,
                 $ctx_arg: $ctx_type,
             ) -> Result<Self, DekuError> {
@@ -28,7 +28,7 @@ macro_rules! ImplDekuTraitsCtx {
         }
 
         impl DekuWriter<$ctx_type> for $typ {
-            fn to_writer<W: Write>(
+            fn to_writer<W: Write + Seek>(
                 &self,
                 writer: &mut Writer<W>,
                 $ctx_arg: $ctx_type,
@@ -66,6 +66,7 @@ ImplDekuTraits!(NonZeroIsize, isize);
 mod tests {
     use hexlit::hex;
     use rstest::rstest;
+    use std::io::Cursor;
 
     use crate::reader::Reader;
 
@@ -79,14 +80,13 @@ mod tests {
         case(&hex!("00"), NonZeroU8::new(0xFF).unwrap()),
     )]
     fn test_non_zero(input: &[u8], expected: NonZeroU8) {
-        let mut bit_slice = input.view_bits::<Msb0>();
-
-        let mut reader = Reader::new(&mut bit_slice);
+        let mut cursor = std::io::Cursor::new(input);
+        let mut reader = Reader::new(&mut cursor);
         let res_read = NonZeroU8::from_reader_with_ctx(&mut reader, ()).unwrap();
         assert_eq!(expected, res_read);
 
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         res_read.to_writer(&mut writer, ()).unwrap();
-        assert_eq!(input.to_vec(), writer.inner);
+        assert_eq!(input.to_vec(), writer.inner.into_inner());
     }
 }
diff --git a/src/impls/option.rs b/src/impls/option.rs
index 7800e7d..e087248 100644
--- a/src/impls/option.rs
+++ b/src/impls/option.rs
@@ -1,9 +1,9 @@
-use no_std_io::io::{Read, Write};
+use no_std_io::io::{Read, Seek, Write};
 
 use crate::{writer::Writer, DekuError, DekuReader, DekuWriter};
 
 impl<'a, T: DekuReader<'a, Ctx>, Ctx: Copy> DekuReader<'a, Ctx> for Option<T> {
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut crate::reader::Reader<R>,
         inner_ctx: Ctx,
     ) -> Result<Self, DekuError> {
@@ -13,7 +13,11 @@ impl<'a, T: DekuReader<'a, Ctx>, Ctx: Copy> DekuReader<'a, Ctx> for Option<T> {
 }
 
 impl<T: DekuWriter<Ctx>, Ctx: Copy> DekuWriter<Ctx> for Option<T> {
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, inner_ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        inner_ctx: Ctx,
+    ) -> Result<(), DekuError> {
         self.as_ref()
             .map_or(Ok(()), |v| v.to_writer(writer, inner_ctx))
     }
@@ -38,8 +42,8 @@ mod tests {
 
     #[test]
     fn test_option_write() {
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         Some(true).to_writer(&mut writer, ()).unwrap();
-        assert_eq!(vec![1], writer.inner);
+        assert_eq!(vec![1], writer.inner.into_inner());
     }
 }
diff --git a/src/impls/primitive.rs b/src/impls/primitive.rs
index 17184c8..8b047fe 100644
--- a/src/impls/primitive.rs
+++ b/src/impls/primitive.rs
@@ -4,7 +4,7 @@ use alloc::format;
 use core::convert::TryInto;
 
 use bitvec::prelude::*;
-use no_std_io::io::{Read, Write};
+use no_std_io::io::{Read, Seek, Write};
 
 use crate::ctx::*;
 use crate::reader::{Reader, ReaderRet};
@@ -50,7 +50,7 @@ impl DekuRead<'_, (Endian, ByteSize)> for u8 {
 impl DekuReader<'_, (Endian, ByteSize)> for u8 {
     /// Ignore endian, as this is a `u8`
     #[inline(always)]
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut Reader<R>,
         (endian, size): (Endian, ByteSize),
     ) -> Result<u8, DekuError> {
@@ -74,7 +74,7 @@ impl DekuReader<'_, (Endian, ByteSize)> for u8 {
 impl DekuWriter<(Endian, BitSize)> for u8 {
     /// Ignore endian, as this is a `u8`
     #[inline(always)]
-    fn to_writer<W: Write>(
+    fn to_writer<W: Write + Seek>(
         &self,
         writer: &mut Writer<W>,
         (_, size): (Endian, BitSize),
@@ -113,7 +113,7 @@ impl DekuWriter<(Endian, BitSize)> for u8 {
 impl DekuWriter<(Endian, ByteSize)> for u8 {
     /// Ignore endian and byte_size, as this is a `u8`
     #[inline(always)]
-    fn to_writer<W: Write>(
+    fn to_writer<W: Write + Seek>(
         &self,
         writer: &mut Writer<W>,
         (_, _): (Endian, ByteSize),
@@ -204,7 +204,7 @@ macro_rules! ImplDekuReadBits {
 
         impl DekuReader<'_, (Endian, BitSize)> for $typ {
             #[inline(always)]
-            fn from_reader_with_ctx<R: Read>(
+            fn from_reader_with_ctx<R: Read + Seek>(
                 reader: &mut Reader<R>,
                 (endian, size): (Endian, BitSize),
             ) -> Result<$typ, DekuError> {
@@ -253,7 +253,7 @@ macro_rules! ImplDekuReadBytes {
 
         impl DekuReader<'_, (Endian, ByteSize)> for $typ {
             #[inline(always)]
-            fn from_reader_with_ctx<R: Read>(
+            fn from_reader_with_ctx<R: Read + Seek>(
                 reader: &mut Reader<R>,
                 (endian, size): (Endian, ByteSize),
             ) -> Result<$typ, DekuError> {
@@ -314,7 +314,7 @@ macro_rules! ImplDekuReadSignExtend {
 
         impl DekuReader<'_, (Endian, ByteSize)> for $typ {
             #[inline(always)]
-            fn from_reader_with_ctx<R: Read>(
+            fn from_reader_with_ctx<R: Read + Seek>(
                 reader: &mut Reader<R>,
                 (endian, size): (Endian, ByteSize),
             ) -> Result<$typ, DekuError> {
@@ -364,7 +364,7 @@ macro_rules! ImplDekuReadSignExtend {
 
         impl DekuReader<'_, (Endian, BitSize)> for $typ {
             #[inline(always)]
-            fn from_reader_with_ctx<R: Read>(
+            fn from_reader_with_ctx<R: Read + Seek>(
                 reader: &mut Reader<R>,
                 (endian, size): (Endian, BitSize),
             ) -> Result<$typ, DekuError> {
@@ -391,7 +391,7 @@ macro_rules! ForwardDekuRead {
         // Only have `endian`, specialize and use read_bytes_const
         impl DekuReader<'_, Endian> for $typ {
             #[inline(always)]
-            fn from_reader_with_ctx<R: Read>(
+            fn from_reader_with_ctx<R: Read + Seek>(
                 reader: &mut Reader<R>,
                 endian: Endian,
             ) -> Result<$typ, DekuError> {
@@ -421,7 +421,7 @@ macro_rules! ForwardDekuRead {
         // Only have `byte_size`, set `endian` to `Endian::default`.
         impl DekuReader<'_, ByteSize> for $typ {
             #[inline(always)]
-            fn from_reader_with_ctx<R: Read>(
+            fn from_reader_with_ctx<R: Read + Seek>(
                 reader: &mut Reader<R>,
                 byte_size: ByteSize,
             ) -> Result<$typ, DekuError> {
@@ -435,7 +435,7 @@ macro_rules! ForwardDekuRead {
         //// Only have `bit_size`, set `endian` to `Endian::default`.
         impl DekuReader<'_, BitSize> for $typ {
             #[inline(always)]
-            fn from_reader_with_ctx<R: Read>(
+            fn from_reader_with_ctx<R: Read + Seek>(
                 reader: &mut Reader<R>,
                 bit_size: BitSize,
             ) -> Result<$typ, DekuError> {
@@ -451,7 +451,7 @@ macro_rules! ForwardDekuRead {
 
         impl DekuReader<'_> for $typ {
             #[inline(always)]
-            fn from_reader_with_ctx<R: Read>(
+            fn from_reader_with_ctx<R: Read + Seek>(
                 reader: &mut Reader<R>,
                 _: (),
             ) -> Result<$typ, DekuError> {
@@ -465,7 +465,7 @@ macro_rules! ImplDekuWrite {
     ($typ:ty) => {
         impl DekuWriter<(Endian, BitSize)> for $typ {
             #[inline(always)]
-            fn to_writer<W: Write>(
+            fn to_writer<W: Write + Seek>(
                 &self,
                 writer: &mut Writer<W>,
                 (endian, size): (Endian, BitSize),
@@ -536,7 +536,7 @@ macro_rules! ImplDekuWrite {
 
         impl DekuWriter<(Endian, ByteSize)> for $typ {
             #[inline(always)]
-            fn to_writer<W: Write>(
+            fn to_writer<W: Write + Seek>(
                 &self,
                 writer: &mut Writer<W>,
                 (endian, size): (Endian, ByteSize),
@@ -571,7 +571,7 @@ macro_rules! ImplDekuWriteOnlyEndian {
     ($typ:ty) => {
         impl DekuWriter<Endian> for $typ {
             #[inline(always)]
-            fn to_writer<W: Write>(
+            fn to_writer<W: Write + Seek>(
                 &self,
                 writer: &mut Writer<W>,
                 endian: Endian,
@@ -591,7 +591,7 @@ macro_rules! ForwardDekuWrite {
     ($typ:ty) => {
         impl DekuWriter<BitSize> for $typ {
             #[inline(always)]
-            fn to_writer<W: Write>(
+            fn to_writer<W: Write + Seek>(
                 &self,
                 writer: &mut Writer<W>,
                 bit_size: BitSize,
@@ -602,7 +602,7 @@ macro_rules! ForwardDekuWrite {
 
         impl DekuWriter<ByteSize> for $typ {
             #[inline(always)]
-            fn to_writer<W: Write>(
+            fn to_writer<W: Write + Seek>(
                 &self,
                 writer: &mut Writer<W>,
                 byte_size: ByteSize,
@@ -613,7 +613,11 @@ macro_rules! ForwardDekuWrite {
 
         impl DekuWriter for $typ {
             #[inline(always)]
-            fn to_writer<W: Write>(&self, writer: &mut Writer<W>, _: ()) -> Result<(), DekuError> {
+            fn to_writer<W: Write + Seek>(
+                &self,
+                writer: &mut Writer<W>,
+                _: (),
+            ) -> Result<(), DekuError> {
                 <$typ>::to_writer(self, writer, Endian::default())
             }
         }
@@ -685,6 +689,7 @@ ImplDekuTraitsBytes!(f64, u64);
 #[cfg(test)]
 mod tests {
     use rstest::rstest;
+    use std::io::Cursor;
 
     use super::*;
     use crate::{native_endian, reader::Reader};
@@ -700,9 +705,9 @@ mod tests {
                 let res_read = <$typ>::from_reader_with_ctx(&mut reader, ENDIAN).unwrap();
                 assert_eq!($expected, res_read);
 
-                let mut writer = Writer::new(vec![]);
+                let mut writer = Writer::new(Cursor::new(vec![]));
                 res_read.to_writer(&mut writer, ENDIAN).unwrap();
-                assert_eq!($input, writer.inner);
+                assert_eq!($input, writer.inner.into_inner());
             }
         };
     }
@@ -807,15 +812,15 @@ mod tests {
         case::too_much_data([0xAA, 0xBB, 0xCC, 0xDD, 0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Little, Some(63), 0xFF, bits![u8, Msb0;], &[]),
     )]
     fn test_bit_read(
-        mut input: &[u8],
+        input: &[u8],
         endian: Endian,
         bit_size: Option<usize>,
         expected: u32,
         expected_rest_bits: &BitSlice<u8, Msb0>,
         expected_rest_bytes: &[u8],
     ) {
-        // test both Read &[u8] and Read BitVec
-        let mut reader = Reader::new(&mut input);
+        let mut cursor = std::io::Cursor::new(input);
+        let mut reader = Reader::new(&mut cursor);
         let res_read = match bit_size {
             Some(bit_size) => {
                 u32::from_reader_with_ctx(&mut reader, (endian, BitSize(bit_size))).unwrap()
@@ -828,7 +833,7 @@ mod tests {
             expected_rest_bits.iter().by_vals().collect::<Vec<bool>>()
         );
         let mut buf = vec![];
-        input.read_to_end(&mut buf).unwrap();
+        cursor.read_to_end(&mut buf).unwrap();
         assert_eq!(expected_rest_bytes, buf);
     }
 
@@ -845,16 +850,16 @@ mod tests {
         case::too_much_data([0xAA, 0xBB, 0xCC, 0xDD, 0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Little, Some(8), 0xFF, &[]),
     )]
     fn test_byte_read(
-        mut input: &[u8],
+        input: &[u8],
         endian: Endian,
         byte_size: Option<usize>,
         expected: u32,
         expected_rest_bytes: &[u8],
     ) {
-        let mut bit_slice = input.view_bits::<Msb0>();
+        let mut cursor = std::io::Cursor::new(input);
+        let mut reader = Reader::new(&mut cursor);
 
         // test both Read &[u8] and Read BitVec
-        let mut reader = Reader::new(&mut input);
         let res_read = match byte_size {
             Some(byte_size) => {
                 u32::from_reader_with_ctx(&mut reader, (endian, ByteSize(byte_size))).unwrap()
@@ -863,16 +868,8 @@ mod tests {
         };
         assert_eq!(expected, res_read);
 
-        let mut reader = Reader::new(&mut bit_slice);
-        let res_read = match byte_size {
-            Some(byte_size) => {
-                u32::from_reader_with_ctx(&mut reader, (endian, ByteSize(byte_size))).unwrap()
-            }
-            None => u32::from_reader_with_ctx(&mut reader, endian).unwrap(),
-        };
-        assert_eq!(expected, res_read);
         let mut buf = vec![];
-        input.read_to_end(&mut buf).unwrap();
+        cursor.read_to_end(&mut buf).unwrap();
         assert_eq!(expected_rest_bytes, buf);
     }
 
@@ -892,7 +889,7 @@ mod tests {
         expected: Vec<u8>,
         expected_leftover: Vec<bool>,
     ) {
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         match bit_size {
             Some(bit_size) => input
                 .to_writer(&mut writer, (endian, BitSize(bit_size)))
@@ -900,7 +897,7 @@ mod tests {
             None => input.to_writer(&mut writer, endian).unwrap(),
         };
         assert_eq!(expected_leftover, writer.rest());
-        assert_eq!(expected, writer.inner);
+        assert_eq!(expected, writer.inner.into_inner());
     }
 
     #[rstest(input, endian, byte_size, expected,
@@ -911,14 +908,14 @@ mod tests {
         case::byte_size_le_bigger(0x03AB, Endian::Little, Some(10), vec![0xAB, 0b11_000000]),
     )]
     fn test_byte_writer(input: u32, endian: Endian, byte_size: Option<usize>, expected: Vec<u8>) {
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         match byte_size {
             Some(byte_size) => input
                 .to_writer(&mut writer, (endian, ByteSize(byte_size)))
                 .unwrap(),
             None => input.to_writer(&mut writer, endian).unwrap(),
         };
-        assert_hex::assert_eq_hex!(expected, writer.inner);
+        assert_hex::assert_eq_hex!(expected, writer.inner.into_inner());
     }
 
     #[rstest(input, endian, bit_size, expected, expected_write,
@@ -931,9 +928,8 @@ mod tests {
         expected: u32,
         expected_write: Vec<u8>,
     ) {
-        let mut bit_slice = input.view_bits::<Msb0>();
-
-        let mut reader = Reader::new(&mut bit_slice);
+        let mut cursor = std::io::Cursor::new(input);
+        let mut reader = Reader::new(&mut cursor);
         let res_read = match bit_size {
             Some(bit_size) => {
                 u32::from_reader_with_ctx(&mut reader, (endian, BitSize(bit_size))).unwrap()
@@ -942,22 +938,23 @@ mod tests {
         };
         assert_eq!(expected, res_read);
 
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         match bit_size {
             Some(bit_size) => res_read
                 .to_writer(&mut writer, (endian, BitSize(bit_size)))
                 .unwrap(),
             None => res_read.to_writer(&mut writer, endian).unwrap(),
         };
-        assert_hex::assert_eq_hex!(expected_write, writer.inner);
+        assert_hex::assert_eq_hex!(expected_write, writer.inner.into_inner());
     }
 
     macro_rules! TestSignExtending {
         ($test_name:ident, $typ:ty) => {
             #[test]
             fn $test_name() {
-                let mut slice = [0b10101_000].as_slice();
-                let mut reader = Reader::new(&mut slice);
+                let slice = [0b10101_000].as_slice();
+                let mut cursor = std::io::Cursor::new(slice);
+                let mut reader = Reader::new(&mut cursor);
                 let res_read =
                     <$typ>::from_reader_with_ctx(&mut reader, (Endian::Little, BitSize(5)))
                         .unwrap();
@@ -977,8 +974,9 @@ mod tests {
         ($test_name:ident, $typ:ty, $size:expr) => {
             #[test]
             fn $test_name() {
-                let mut slice = [0b10101_000].as_slice();
-                let mut reader = Reader::new(&mut slice);
+                let slice = [0b10101_000].as_slice();
+                let mut cursor = std::io::Cursor::new(slice);
+                let mut reader = Reader::new(&mut cursor);
                 let res_read =
                     <$typ>::from_reader_with_ctx(&mut reader, (Endian::Little, BitSize($size + 1)));
                 assert_eq!(
diff --git a/src/impls/slice.rs b/src/impls/slice.rs
index b9df306..4026906 100644
--- a/src/impls/slice.rs
+++ b/src/impls/slice.rs
@@ -4,13 +4,16 @@ use crate::reader::Reader;
 use crate::writer::Writer;
 use crate::{DekuError, DekuReader, DekuWriter};
 use core::mem::MaybeUninit;
-use no_std_io::io::{Read, Write};
+use no_std_io::io::{Read, Seek, Write};
 
 impl<'a, Ctx: Copy, T, const N: usize> DekuReader<'a, Ctx> for [T; N]
 where
     T: DekuReader<'a, Ctx>,
 {
-    fn from_reader_with_ctx<R: Read>(reader: &mut Reader<R>, ctx: Ctx) -> Result<Self, DekuError>
+    fn from_reader_with_ctx<R: Read + Seek>(
+        reader: &mut Reader<R>,
+        ctx: Ctx,
+    ) -> Result<Self, DekuError>
     where
         Self: Sized,
     {
@@ -46,7 +49,11 @@ impl<Ctx: Copy, T, const N: usize> DekuWriter<Ctx> for [T; N]
 where
     T: DekuWriter<Ctx>,
 {
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        ctx: Ctx,
+    ) -> Result<(), DekuError> {
         for v in self {
             v.to_writer(writer, ctx)?;
         }
@@ -58,7 +65,11 @@ impl<Ctx: Copy, T> DekuWriter<Ctx> for &[T]
 where
     T: DekuWriter<Ctx>,
 {
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        ctx: Ctx,
+    ) -> Result<(), DekuError> {
         for v in *self {
             v.to_writer(writer, ctx)?;
         }
@@ -70,7 +81,11 @@ impl<Ctx: Copy, T> DekuWriter<Ctx> for [T]
 where
     T: DekuWriter<Ctx>,
 {
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        ctx: Ctx,
+    ) -> Result<(), DekuError> {
         for v in self {
             v.to_writer(writer, ctx)?;
         }
@@ -83,6 +98,7 @@ mod tests {
     use super::*;
     use bitvec::prelude::*;
     use rstest::rstest;
+    use std::io::Cursor;
 
     use crate::{ctx::Endian, reader::Reader, writer::Writer, DekuReader};
 
@@ -93,9 +109,8 @@ mod tests {
         case::normal_be([0xDD, 0xCC].as_ref(), Endian::Big, [0xDDCC, 0xBBAA]),
     )]
     fn test_bit_read(input: &[u8], endian: Endian, expected: [u16; 2]) {
-        let mut bit_slice = input.view_bits::<Msb0>();
-
-        let mut reader = Reader::new(&mut bit_slice);
+        let mut cursor = std::io::Cursor::new(input);
+        let mut reader = Reader::new(&mut cursor);
         let res_read = <[u16; 2]>::from_reader_with_ctx(&mut reader, endian).unwrap();
         assert_eq!(expected, res_read);
     }
@@ -106,9 +121,11 @@ mod tests {
     )]
     fn test_bit_write(input: [u16; 2], endian: Endian, expected: Vec<u8>) {
         // test writer
-        let mut writer = Writer::new(vec![]);
+
+        use std::io::Cursor;
+        let mut writer = Writer::new(Cursor::new(vec![]));
         input.to_writer(&mut writer, endian).unwrap();
-        assert_eq!(expected, writer.inner);
+        assert_eq!(expected, writer.inner.into_inner());
     }
 
     #[rstest(input,endian,expected,
@@ -125,14 +142,15 @@ mod tests {
     )]
     fn test_nested_array_bit_write(input: [[u16; 2]; 2], endian: Endian, expected: Vec<u8>) {
         // test writer
-        let mut writer = Writer::new(vec![]);
+
+        let mut writer = Writer::new(Cursor::new(vec![]));
         input.to_writer(&mut writer, endian).unwrap();
-        assert_eq!(expected, writer.inner);
+        assert_eq!(expected, writer.inner.into_inner());
 
         // test &slice
         let input = input.as_ref();
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         input.to_writer(&mut writer, endian).unwrap();
-        assert_eq!(expected, writer.inner);
+        assert_eq!(expected, writer.inner.into_inner());
     }
 }
diff --git a/src/impls/tuple.rs b/src/impls/tuple.rs
index 677942a..1b7354f 100644
--- a/src/impls/tuple.rs
+++ b/src/impls/tuple.rs
@@ -2,7 +2,7 @@
 
 use crate::writer::Writer;
 
-use no_std_io::io::{Read, Write};
+use no_std_io::io::{Read, Seek, Write};
 
 use crate::{DekuError, DekuReader, DekuWriter};
 
@@ -39,7 +39,7 @@ macro_rules! ImplDekuTupleTraits {
 
         impl<'a, Ctx: Copy, $($T:DekuReader<'a, Ctx>+Sized),+> DekuReader<'a, Ctx> for ($($T,)+)
         {
-            fn from_reader_with_ctx<R: Read>(
+            fn from_reader_with_ctx<R: Read + Seek>(
                 reader: &mut crate::reader::Reader<R>,
                 ctx: Ctx,
             ) -> Result<Self, DekuError>
@@ -58,7 +58,7 @@ macro_rules! ImplDekuTupleTraits {
         impl<Ctx: Copy, $($T:DekuWriter<Ctx>),+> DekuWriter<Ctx> for ($($T,)+)
         {
             #[allow(non_snake_case)]
-            fn to_writer<W: Write>(&self, writer: &mut Writer<W>, ctx: Ctx) -> Result<(), DekuError> {
+            fn to_writer<W: Write + Seek>(&self, writer: &mut Writer<W>, ctx: Ctx) -> Result<(), DekuError> {
                 let ($(ref $T,)+) = *self;
                 $(
                     $T.to_writer(writer, ctx)?;
@@ -97,8 +97,10 @@ mod tests {
     where
         T: DekuWriter,
     {
-        let mut writer = Writer::new(vec![]);
+        use std::io::Cursor;
+
+        let mut writer = Writer::new(Cursor::new(vec![]));
         input.to_writer(&mut writer, ()).unwrap();
-        assert_eq!(expected, writer.inner);
+        assert_eq!(expected, writer.inner.into_inner());
     }
 }
diff --git a/src/impls/unit.rs b/src/impls/unit.rs
index 7d3c93b..919db30 100644
--- a/src/impls/unit.rs
+++ b/src/impls/unit.rs
@@ -1,9 +1,9 @@
-use no_std_io::io::{Read, Write};
+use no_std_io::io::{Read, Seek, Write};
 
 use crate::{reader::Reader, writer::Writer, DekuError, DekuReader, DekuWriter};
 
 impl<Ctx: Copy> DekuReader<'_, Ctx> for () {
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         _reader: &mut Reader<R>,
         _inner_ctx: Ctx,
     ) -> Result<Self, DekuError> {
@@ -13,7 +13,7 @@ impl<Ctx: Copy> DekuReader<'_, Ctx> for () {
 
 impl<Ctx: Copy> DekuWriter<Ctx> for () {
     /// NOP on write
-    fn to_writer<W: Write>(
+    fn to_writer<W: Write + Seek>(
         &self,
         _writer: &mut Writer<W>,
         _inner_ctx: Ctx,
@@ -40,8 +40,8 @@ mod tests {
         let res_read = <()>::from_reader_with_ctx(&mut reader, ()).unwrap();
         assert_eq!((), res_read);
 
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         res_read.to_writer(&mut writer, ()).unwrap();
-        assert!(writer.inner.is_empty());
+        assert!(writer.inner.into_inner().is_empty());
     }
 }
diff --git a/src/impls/vec.rs b/src/impls/vec.rs
index 664ffff..5f76104 100644
--- a/src/impls/vec.rs
+++ b/src/impls/vec.rs
@@ -1,4 +1,4 @@
-use no_std_io::io::{Read, Write};
+use no_std_io::io::{Read, Seek, Write};
 
 #[cfg(feature = "alloc")]
 use alloc::vec::Vec;
@@ -15,7 +15,7 @@ use crate::{DekuError, DekuWriter};
 /// The predicate takes two parameters: the number of bits that have been read so far,
 /// and a borrow of the latest value to have been read. It should return `true` if reading
 /// should now stop, and `false` otherwise
-fn reader_vec_with_predicate<'a, T, Ctx, Predicate, R: Read>(
+fn reader_vec_with_predicate<'a, T, Ctx, Predicate, R: Read + Seek>(
     reader: &mut Reader<R>,
     capacity: Option<usize>,
     ctx: Ctx,
@@ -44,7 +44,7 @@ where
     Ok(res)
 }
 
-fn reader_vec_to_end<'a, T, Ctx, R: Read>(
+fn reader_vec_to_end<'a, T, Ctx, R: Read + Seek>(
     reader: &mut crate::reader::Reader<R>,
     capacity: Option<usize>,
     ctx: Ctx,
@@ -71,7 +71,7 @@ where
     Ctx: Copy,
     Predicate: FnMut(&T) -> bool,
 {
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut Reader<R>,
         (limit, inner_ctx): (Limit<T, Predicate>, Ctx),
     ) -> Result<Self, DekuError>
@@ -135,7 +135,7 @@ impl<'a, T: DekuReader<'a>, Predicate: FnMut(&T) -> bool> DekuReader<'a, Limit<T
     for Vec<T>
 {
     /// Read `T`s until the given limit from input for types which don't require context.
-    fn from_reader_with_ctx<R: Read>(
+    fn from_reader_with_ctx<R: Read + Seek>(
         reader: &mut Reader<R>,
         limit: Limit<T, Predicate>,
     ) -> Result<Self, DekuError>
@@ -154,13 +154,19 @@ impl<T: DekuWriter<Ctx>, Ctx: Copy> DekuWriter<Ctx> for Vec<T> {
     /// # use deku::{ctx::Endian, DekuWriter};
     /// # use deku::writer::Writer;
     /// # use deku::bitvec::{Msb0, bitvec};
+    /// # use std::io::Cursor;
     /// let data = vec![1u8];
     /// let mut out_buf = vec![];
-    /// let mut writer = Writer::new(&mut out_buf);
+    /// let mut cursor = Cursor::new(&mut out_buf);
+    /// let mut writer = Writer::new(&mut cursor);
     /// data.to_writer(&mut writer, Endian::Big).unwrap();
     /// assert_eq!(data, out_buf.to_vec());
     /// ```
-    fn to_writer<W: Write>(&self, writer: &mut Writer<W>, inner_ctx: Ctx) -> Result<(), DekuError> {
+    fn to_writer<W: Write + Seek>(
+        &self,
+        writer: &mut Writer<W>,
+        inner_ctx: Ctx,
+    ) -> Result<(), DekuError> {
         for v in self {
             v.to_writer(writer, inner_ctx)?;
         }
@@ -172,6 +178,7 @@ impl<T: DekuWriter<Ctx>, Ctx: Copy> DekuWriter<Ctx> for Vec<T> {
 mod tests {
     use crate::bitvec::{bits, BitSlice, Msb0};
     use rstest::rstest;
+    use std::io::Cursor;
 
     use crate::reader::Reader;
 
@@ -191,7 +198,8 @@ mod tests {
         expected_rest_bits: &BitSlice<u8, Msb0>,
         expected_rest_bytes: &[u8],
     ) {
-        let mut reader = Reader::new(&mut input);
+        let mut cursor = Cursor::new(&mut input);
+        let mut reader = Reader::new(&mut cursor);
         let res_read = Vec::<u8>::from_reader_with_ctx(&mut reader, limit).unwrap();
         assert_eq!(expected, res_read);
         assert_eq!(
@@ -199,7 +207,7 @@ mod tests {
             expected_rest_bits.iter().by_vals().collect::<Vec<bool>>()
         );
         let mut buf = vec![];
-        input.read_to_end(&mut buf).unwrap();
+        cursor.read_to_end(&mut buf).unwrap();
         assert_eq!(expected_rest_bytes, buf);
     }
 
@@ -226,7 +234,7 @@ mod tests {
         case::too_much_data([0xAA, 0xBB].as_ref(), Endian::Little, Some(9), 1.into(), vec![], bits![u8, Msb0;], &[]),
     )]
     fn test_vec_reader<Predicate: FnMut(&u8) -> bool>(
-        mut input: &[u8],
+        input: &[u8],
         endian: Endian,
         bit_size: Option<usize>,
         limit: Limit<u8, Predicate>,
@@ -234,7 +242,8 @@ mod tests {
         expected_rest_bits: &BitSlice<u8, Msb0>,
         expected_rest_bytes: &[u8],
     ) {
-        let mut reader = Reader::new(&mut input);
+        let mut cursor = Cursor::new(input);
+        let mut reader = Reader::new(&mut cursor);
         let res_read = match bit_size {
             Some(bit_size) => {
                 Vec::<u8>::from_reader_with_ctx(&mut reader, (limit, (endian, BitSize(bit_size))))
@@ -248,7 +257,7 @@ mod tests {
             expected_rest_bits.iter().by_vals().collect::<Vec<bool>>()
         );
         let mut buf = vec![];
-        input.read_to_end(&mut buf).unwrap();
+        cursor.read_to_end(&mut buf).unwrap();
         assert_eq!(expected_rest_bytes, buf);
     }
 
@@ -256,9 +265,9 @@ mod tests {
         case::normal(vec![0xAABB, 0xCCDD], Endian::Little, vec![0xBB, 0xAA, 0xDD, 0xCC]),
     )]
     fn test_vec_write(input: Vec<u16>, endian: Endian, expected: Vec<u8>) {
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         input.to_writer(&mut writer, endian).unwrap();
-        assert_eq!(expected, writer.inner);
+        assert_eq!(expected, writer.inner.into_inner());
     }
 
     // Note: These tests also exist in boxed.rs
@@ -271,7 +280,7 @@ mod tests {
         case::bytes_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), BitSize(16).into(), vec![0xAABB], bits![u8, Msb0;], &[0xcc, 0xdd], vec![0xAA, 0xBB]),
     )]
     fn test_vec_reader_write<Predicate: FnMut(&u16) -> bool>(
-        mut input: &[u8],
+        input: &[u8],
         endian: Endian,
         bit_size: Option<usize>,
         limit: Limit<u16, Predicate>,
@@ -284,7 +293,8 @@ mod tests {
         // Unwrap here because all test cases are `Some`.
         let bit_size = bit_size.unwrap();
 
-        let mut reader = Reader::new(&mut input);
+        let mut cursor = Cursor::new(input);
+        let mut reader = Reader::new(&mut cursor);
         let res_read =
             Vec::<u16>::from_reader_with_ctx(&mut reader, (limit, (endian, BitSize(bit_size))))
                 .unwrap();
@@ -294,14 +304,14 @@ mod tests {
             expected_rest_bits.iter().by_vals().collect::<Vec<bool>>()
         );
         let mut buf = vec![];
-        input.read_to_end(&mut buf).unwrap();
+        cursor.read_to_end(&mut buf).unwrap();
         assert_eq!(expected_rest_bytes, buf);
 
-        let mut writer = Writer::new(vec![]);
+        let mut writer = Writer::new(Cursor::new(vec![]));
         res_read
             .to_writer(&mut writer, (endian, BitSize(bit_size)))
             .unwrap();
-        assert_eq!(expected_write, writer.inner);
+        assert_eq!(expected_write, writer.inner.into_inner());
 
         assert_eq!(input_clone[..expected_write.len()].to_vec(), expected_write);
     }
diff --git a/src/lib.rs b/src/lib.rs
index b2fec92..c20622c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -354,6 +354,8 @@ pub mod no_std_io {
     pub use no_std_io::io::Cursor;
     pub use no_std_io::io::Read;
     pub use no_std_io::io::Result;
+    pub use no_std_io::io::Seek;
+    pub use no_std_io::io::SeekFrom;
     pub use no_std_io::io::Write;
 }
 
@@ -406,7 +408,7 @@ pub trait DekuReader<'a, Ctx = ()> {
     /// let mut reader = Reader::new(&mut file);
     /// let ec = EcHdr::from_reader_with_ctx(&mut reader, Endian::Big).unwrap();
     /// ```
-    fn from_reader_with_ctx<R: no_std_io::Read>(
+    fn from_reader_with_ctx<R: no_std_io::Read + no_std_io::Seek>(
         reader: &mut Reader<R>,
         ctx: Ctx,
     ) -> Result<Self, DekuError>
@@ -443,12 +445,12 @@ pub trait DekuContainerRead<'a>: DekuReader<'a, ()> {
     ///     magic: [u8; 4],
     ///     version: u8,
     /// }
-    ///
+    /// ```
     /// let mut file = File::options().read(true).open("file").unwrap();
     /// file.seek(SeekFrom::Start(0)).unwrap();
     /// let ec = EcHdr::from_reader((&mut file, 0)).unwrap();
     /// ```
-    fn from_reader<R: no_std_io::Read>(
+    fn from_reader<R: no_std_io::Read + no_std_io::Seek>(
         input: (&'a mut R, usize),
     ) -> Result<(usize, Self), DekuError>
     where
@@ -473,7 +475,7 @@ pub trait DekuContainerRead<'a>: DekuReader<'a, ()> {
 )]
 pub trait DekuWriter<Ctx = ()> {
     /// Write type to bytes
-    fn to_writer<W: no_std_io::Write>(
+    fn to_writer<W: no_std_io::Write + no_std_io::Seek>(
         &self,
         writer: &mut Writer<W>,
         ctx: Ctx,
@@ -509,7 +511,8 @@ pub trait DekuContainerWrite: DekuWriter<()> {
     #[inline(always)]
     fn to_bytes(&self) -> Result<Vec<u8>, DekuError> {
         let mut out_buf = Vec::new();
-        let mut __deku_writer = Writer::new(&mut out_buf);
+        let mut cursor = no_std_io::Cursor::new(&mut out_buf);
+        let mut __deku_writer = Writer::new(&mut cursor);
         DekuWriter::to_writer(self, &mut __deku_writer, ())?;
         __deku_writer.finalize()?;
         Ok(out_buf)
@@ -535,11 +538,12 @@ pub trait DekuContainerWrite: DekuWriter<()> {
     /// ````
     #[inline(always)]
     fn to_slice(&self, buf: &mut [u8]) -> Result<usize, DekuError> {
-        let mut __deku_writer = Writer::new(buf);
-        DekuWriter::to_writer(self, &mut __deku_writer, ())?;
-        __deku_writer.finalize()?;
+        let mut cursor = no_std_io::Cursor::new(buf);
+        let mut writer = Writer::new(&mut cursor);
+        DekuWriter::to_writer(self, &mut writer, ())?;
+        writer.finalize()?;
 
-        Ok(__deku_writer.bits_written / 8)
+        Ok(writer.bits_written / 8)
     }
 
     /// Write struct/enum to BitVec
@@ -566,7 +570,8 @@ pub trait DekuContainerWrite: DekuWriter<()> {
     #[inline(always)]
     fn to_bits(&self) -> Result<bitvec::BitVec<u8, bitvec::Msb0>, DekuError> {
         let mut out_buf = Vec::new();
-        let mut __deku_writer = Writer::new(&mut out_buf);
+        let mut cursor = no_std_io::Cursor::new(&mut out_buf);
+        let mut __deku_writer = Writer::new(&mut cursor);
         DekuWriter::to_writer(self, &mut __deku_writer, ())?;
         let mut leftover = __deku_writer.leftover;
         let mut bv = bitvec::BitVec::from_slice(&out_buf);
@@ -593,7 +598,7 @@ where
     Ctx: Copy,
 {
     #[inline(always)]
-    fn to_writer<W: no_std_io::Write>(
+    fn to_writer<W: no_std_io::Write + no_std_io::Seek>(
         &self,
         writer: &mut Writer<W>,
         ctx: Ctx,
diff --git a/src/reader.rs b/src/reader.rs
index 19283e8..78c4f4c 100644
--- a/src/reader.rs
+++ b/src/reader.rs
@@ -3,7 +3,7 @@
 use core::cmp::Ordering;
 
 use bitvec::prelude::*;
-use no_std_io::io::{ErrorKind, Read};
+use no_std_io::io::{ErrorKind, Read, Seek, SeekFrom};
 
 use crate::{prelude::NeedSize, DekuError};
 use alloc::vec::Vec;
@@ -23,7 +23,7 @@ pub enum ReaderRet {
 pub const MAX_BITS_AMT: usize = 128;
 
 /// Reader to use with `from_reader_with_ctx`
-pub struct Reader<'a, R: Read> {
+pub struct Reader<'a, R: Read + Seek> {
     inner: &'a mut R,
     /// bits stored from previous reads that didn't read to the end of a byte size
     leftover: BitVec<u8, Msb0>,
@@ -31,7 +31,23 @@ pub struct Reader<'a, R: Read> {
     pub bits_read: usize,
 }
 
-impl<'a, R: Read> Reader<'a, R> {
+impl<R: Read + Seek> Seek for Reader<'_, R> {
+    fn seek(&mut self, pos: SeekFrom) -> no_std_io::io::Result<u64> {
+        #[cfg(feature = "logging")]
+        log::trace!("seek: {pos:?}");
+        // clear leftover
+        self.leftover = BitVec::new();
+        self.inner.seek(pos)
+    }
+}
+
+impl<R: Read + Seek> AsMut<R> for Reader<'_, R> {
+    fn as_mut(&mut self) -> &mut R {
+        self.inner
+    }
+}
+
+impl<'a, R: Read + Seek> Reader<'a, R> {
     /// Create a new `Reader`
     #[inline]
     pub fn new(inner: &'a mut R) -> Self {
diff --git a/src/writer.rs b/src/writer.rs
index bf4ed92..188e0fb 100644
--- a/src/writer.rs
+++ b/src/writer.rs
@@ -2,7 +2,7 @@
 
 use bitvec::bitvec;
 use bitvec::{field::BitField, prelude::*};
-use no_std_io::io::Write;
+use no_std_io::io::{Seek, SeekFrom, Write};
 
 #[cfg(feature = "logging")]
 use log;
@@ -17,7 +17,7 @@ const fn bits_of<T>() -> usize {
 pub const MAX_BITS_AMT: usize = 128;
 
 /// Container to use with `to_writer`
-pub struct Writer<W: Write> {
+pub struct Writer<W: Write + Seek> {
     pub(crate) inner: W,
     /// Leftover bits
     pub leftover: BitVec<u8, Msb0>,
@@ -25,7 +25,17 @@ pub struct Writer<W: Write> {
     pub bits_written: usize,
 }
 
-impl<W: Write> Writer<W> {
+impl<W: Write + Seek> Seek for Writer<W> {
+    fn seek(&mut self, pos: SeekFrom) -> no_std_io::io::Result<u64> {
+        #[cfg(feature = "logging")]
+        log::trace!("seek: {pos:?}");
+        // clear leftover
+        self.leftover = BitVec::new();
+        self.inner.seek(pos)
+    }
+}
+
+impl<W: Write + Seek> Writer<W> {
     /// Create a new `Writer`
     #[inline]
     pub fn new(inner: W) -> Self {
@@ -162,12 +172,14 @@ impl<W: Write> Writer<W> {
 
 #[cfg(test)]
 mod tests {
+    use std::io::Cursor;
+
     use super::*;
     use hexlit::hex;
 
     #[test]
     fn test_writer() {
-        let mut out_buf = vec![];
+        let mut out_buf = Cursor::new(vec![]);
         let mut writer = Writer::new(&mut out_buf);
 
         let mut input = hex!("aa");
@@ -199,7 +211,7 @@ mod tests {
         writer.write_bits(&mut bv).unwrap();
 
         assert_eq!(
-            &mut out_buf,
+            &mut out_buf.into_inner(),
             &mut vec![0xaa, 0xbb, 0xf1, 0xaa, 0x1f, 0x1a, 0xaf]
         );
     }


Test patch:
diff --git a/tests/test_alloc.rs b/tests/test_alloc.rs
index 86072b4..5da05c8 100644
--- a/tests/test_alloc.rs
+++ b/tests/test_alloc.rs
@@ -54,10 +54,11 @@ mod tests {
     #[cfg_attr(miri, ignore)]
     fn test_simple() {
         let input = hex!("aa_bbbb_cc_0102_dd_ffffff_aa_0100ff");
+        let mut cursor = std::io::Cursor::new(input);
 
         assert_eq!(
             count_alloc(|| {
-                let _ = TestDeku::from_reader((&mut input.as_slice(), 0)).unwrap();
+                let _ = TestDeku::from_reader((&mut cursor, 0)).unwrap();
             })
             .0,
             (5, 0, 5)
@@ -68,7 +69,8 @@ mod tests {
     #[cfg_attr(miri, ignore)]
     fn test_simple_write() {
         let input = hex!("aa_bbbb_cc_0102_dd_ffffff_aa_0100ff");
-        let t = TestDeku::from_reader((&mut input.as_slice(), 0)).unwrap().1;
+        let mut cursor = std::io::Cursor::new(input);
+        let t = TestDeku::from_reader((&mut cursor, 0)).unwrap().1;
 
         assert_eq!(
             count_alloc(|| {
@@ -83,7 +85,8 @@ mod tests {
     #[cfg_attr(miri, ignore)]
     fn test_to_slice() {
         let input = hex!("aa_bbbb_cc_0102_dd_ffffff_aa_0100ff");
-        let t = TestDeku::from_reader((&mut input.as_slice(), 0)).unwrap().1;
+        let mut cursor = std::io::Cursor::new(input);
+        let t = TestDeku::from_reader((&mut cursor, 0)).unwrap().1;
 
         let mut out = [0x00; 100];
 
diff --git a/tests/test_attributes/test_ctx.rs b/tests/test_attributes/test_ctx.rs
index fd7fb42..2decec6 100644
--- a/tests/test_attributes/test_ctx.rs
+++ b/tests/test_attributes/test_ctx.rs
@@ -70,7 +70,8 @@ fn test_top_level_ctx_enum() {
     assert_eq!(ret_read, TopLevelCtxEnum::VariantA(0x06));
 
     let mut out_buf = vec![];
-    let mut writer = Writer::new(&mut out_buf);
+    let mut cursor = Cursor::new(&mut out_buf);
+    let mut writer = Writer::new(&mut cursor);
     ret_read.to_writer(&mut writer, (1, 2)).unwrap();
     assert_eq!(out_buf.to_vec(), &test_data[..]);
 }
@@ -107,7 +108,8 @@ fn test_top_level_ctx_enum_default() {
     .unwrap();
     assert_eq!(ret_read, TopLevelCtxEnumDefault::VariantA(0x06));
     let mut out_buf = vec![];
-    let mut writer = Writer::new(&mut out_buf);
+    let mut cursor = Cursor::new(&mut out_buf);
+    let mut writer = Writer::new(&mut cursor);
     ret_read.to_writer(&mut writer, (1, 2)).unwrap();
     assert_eq!(test_data.to_vec(), out_buf.to_vec());
 }
@@ -181,7 +183,8 @@ fn test_struct_enum_ctx_id() {
 
     // VarC
     let test_data = [0x02_u8, 0x03, 0xcc];
-    let (_, ret_read) = StructEnumId::from_reader((&mut test_data.as_slice(), 0)).unwrap();
+    let mut cursor = Cursor::new(test_data);
+    let (_, ret_read) = StructEnumId::from_reader((&mut cursor, 0)).unwrap();
 
     assert_eq!(
         StructEnumId {
@@ -229,7 +232,8 @@ fn test_ctx_default_struct() {
     .unwrap();
     assert_eq!(expected, ret_read);
     let mut out_buf = vec![];
-    let mut writer = Writer::new(&mut out_buf);
+    let mut cursor = Cursor::new(&mut out_buf);
+    let mut writer = Writer::new(&mut cursor);
     ret_read.to_writer(&mut writer, (1, 2)).unwrap();
     assert_eq!(test_data.to_vec(), out_buf.to_vec());
 }
diff --git a/tests/test_compile/cases/internal_variables.rs b/tests/test_compile/cases/internal_variables.rs
index 561f910..74422ca 100644
--- a/tests/test_compile/cases/internal_variables.rs
+++ b/tests/test_compile/cases/internal_variables.rs
@@ -49,7 +49,7 @@ struct TestMap {
     field_b: usize,
 }
 
-fn dummy_reader<R: std::io::Read>(
+fn dummy_reader<R: std::io::Read + std::io::Seek>(
     offset: usize,
     _reader: &mut Reader<R>,
 ) -> Result<usize, DekuError> {
diff --git a/tests/test_compile/cases/internal_variables.stderr b/tests/test_compile/cases/internal_variables.stderr
index faddbb3..a1b76aa 100644
--- a/tests/test_compile/cases/internal_variables.stderr
+++ b/tests/test_compile/cases/internal_variables.stderr
@@ -4,6 +4,22 @@ error: Unexpected meta-item format `attribute cannot contain `__deku_` these are
 88 |     #[deku(cond = "__deku_bit_offset == *field_a as usize")]
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0277]: the trait bound `W: Seek` is not satisfied
+  --> tests/test_compile/cases/internal_variables.rs:75:66
+   |
+75 | fn dummy_writer<W: std::io::Write>(_offset: usize, _writer: &mut deku::writer::Writer<W>) -> Result<(), DekuError> {
+   |                                                                  ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Seek` is not implemented for `W`
+   |
+note: required by a bound in `Writer`
+  --> src/writer.rs
+   |
+   | pub struct Writer<W: Write + Seek> {
+   |                              ^^^^ required by this bound in `Writer`
+help: consider further restricting this bound
+   |
+75 | fn dummy_writer<W: std::io::Write + std::io::Seek>(_offset: usize, _writer: &mut deku::writer::Writer<W>) -> Result<(), DekuError> {
+   |                                   +++++++++++++++
+
 warning: unused variable: `offset`
   --> tests/test_compile/cases/internal_variables.rs:53:5
    |
diff --git a/tests/test_compile/cases/seek_conflict.rs b/tests/test_compile/cases/seek_conflict.rs
new file mode 100644
index 0000000..ce09909
--- /dev/null
+++ b/tests/test_compile/cases/seek_conflict.rs
@@ -0,0 +1,11 @@
+use deku::prelude::*;
+
+#[derive(DekuRead, Debug, PartialEq, Eq)]
+pub struct Test {
+    #[deku(seek_rewind, seek_from_current = "0")]
+    byte_a: u8,
+    #[deku(seek_from_current = "1", seek_from_end = "-1")]
+    byte_b: u8,
+}
+
+fn main() {}
diff --git a/tests/test_compile/cases/seek_conflict.stderr b/tests/test_compile/cases/seek_conflict.stderr
new file mode 100644
index 0000000..0666f5e
--- /dev/null
+++ b/tests/test_compile/cases/seek_conflict.stderr
@@ -0,0 +1,7 @@
+error: conflicting: only one `seek` attribute can be used at one time
+ --> tests/test_compile/cases/seek_conflict.rs:3:10
+  |
+3 | #[derive(DekuRead, Debug, PartialEq, Eq)]
+  |          ^^^^^^^^
+  |
+  = note: this error originates in the derive macro `DekuRead` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/test_enum.rs b/tests/test_enum.rs
index cbe3947..4459ff0 100644
--- a/tests/test_enum.rs
+++ b/tests/test_enum.rs
@@ -1,4 +1,5 @@
 use std::convert::{TryFrom, TryInto};
+use std::io::Cursor;
 
 use deku::prelude::*;
 use hexlit::hex;
@@ -131,7 +132,8 @@ fn test_id_pat_with_id() {
     }
 
     let input = [0x01, 0x02];
-    let (_, v) = DekuTest::from_reader((&mut input.as_slice(), 0)).unwrap();
+    let mut cursor = Cursor::new(input);
+    let (_, v) = DekuTest::from_reader((&mut cursor, 0)).unwrap();
     assert_eq!(
         v,
         DekuTest {
@@ -142,7 +144,8 @@ fn test_id_pat_with_id() {
     assert_eq!(input, &*v.to_bytes().unwrap());
 
     let input = [0x05];
-    let (_, v) = DekuTest::from_reader((&mut input.as_slice(), 0)).unwrap();
+    let mut cursor = Cursor::new(input);
+    let (_, v) = DekuTest::from_reader((&mut cursor, 0)).unwrap();
     assert_eq!(
         v,
         DekuTest {
diff --git a/tests/test_own_impl.rs b/tests/test_own_impl.rs
new file mode 100644
index 0000000..e28cc22
--- /dev/null
+++ b/tests/test_own_impl.rs
@@ -0,0 +1,29 @@
+#[test]
+fn test_own_impl() {
+    use deku::prelude::*;
+    use std::io::{Read, Seek, SeekFrom};
+    pub trait ReadSeek: Read + Seek {}
+    pub enum Data {
+        /// On read: Save current stream_position() as `Offset`, seek `header.filesize`
+        /// This will be used to seek this this position if we want to extract *just* this file
+        Offset(u64),
+    }
+
+    impl DekuReader<'_, u32> for Data {
+        fn from_reader_with_ctx<R: Read + Seek>(
+            reader: &mut Reader<R>,
+            filesize: u32,
+        ) -> Result<Data, DekuError> {
+            let reader = reader.as_mut();
+
+            // Save the current offset, this is where the file exists for reading later
+            let current_pos = reader.stream_position().unwrap();
+
+            // Seek past that file
+            let position = filesize as i64;
+            let _ = reader.seek(SeekFrom::Current(position));
+
+            Ok(Self::Offset(current_pos))
+        }
+    }
+}
diff --git a/tests/test_regression.rs b/tests/test_regression.rs
index 57e5ac4..0bf30b8 100644
--- a/tests/test_regression.rs
+++ b/tests/test_regression.rs
@@ -1,4 +1,5 @@
 use deku::prelude::*;
+use std::io::Cursor;
 
 // Invalid alignment assumptions when converting
 // BitSlice to type
@@ -90,8 +91,8 @@ mod issue_282 {
         assert_eq!(zero, 0);
 
         let data = [a, b, c, a, b, c];
-        let (_, BitsBytes { bits, bytes }) =
-            BitsBytes::from_reader((&mut data.as_slice(), 0)).unwrap();
+        let mut cursor = Cursor::new(data);
+        let (_, BitsBytes { bits, bytes }) = BitsBytes::from_reader((&mut cursor, 0)).unwrap();
 
         assert_eq!(bits, expected);
         assert_eq!(bytes, expected);
@@ -116,8 +117,8 @@ mod issue_282 {
         assert_eq!(zero, 0);
 
         let data = [a, b, c, a, b, c];
-        let (_, BitsBytes { bits, bytes }) =
-            BitsBytes::from_reader((&mut data.as_slice(), 0)).unwrap();
+        let mut cursor = Cursor::new(data);
+        let (_, BitsBytes { bits, bytes }) = BitsBytes::from_reader((&mut cursor, 0)).unwrap();
 
         assert_eq!(bits, expected);
         assert_eq!(bytes, expected);
@@ -141,10 +142,9 @@ fn test_regression_292() {
         field3: u8,
     }
 
+    let mut cursor = Cursor::new(test_data);
     assert_eq!(
-        Reader::from_reader((&mut test_data.as_slice(), 0))
-            .unwrap()
-            .1,
+        Reader::from_reader((&mut cursor, 0)).unwrap().1,
         Reader {
             field1: 0,
             field2: 0xff,
@@ -163,10 +163,9 @@ fn test_regression_292() {
         field3: u8,
     }
 
+    let mut cursor = Cursor::new(test_data);
     assert_eq!(
-        ReaderBits::from_reader((&mut test_data.as_slice(), 0))
-            .unwrap()
-            .1,
+        ReaderBits::from_reader((&mut cursor, 0)).unwrap().1,
         ReaderBits {
             field1: 0,
             field2: 0xff,
@@ -183,10 +182,9 @@ fn test_regression_292() {
         field3: u8,
     }
 
+    let mut cursor = Cursor::new(test_data);
     assert_eq!(
-        ReaderByteNoEndian::from_reader((&mut test_data.as_slice(), 0))
-            .unwrap()
-            .1,
+        ReaderByteNoEndian::from_reader((&mut cursor, 0)).unwrap().1,
         ReaderByteNoEndian {
             field1: 0,
             field2: 0xff,
@@ -202,10 +200,9 @@ fn test_regression_292() {
         field3: u8,
     }
 
+    let mut cursor = Cursor::new(test_data);
     assert_eq!(
-        ReaderBitPadding::from_reader((&mut test_data.as_slice(), 0))
-            .unwrap()
-            .1,
+        ReaderBitPadding::from_reader((&mut cursor, 0)).unwrap().1,
         ReaderBitPadding {
             field2: 0xff,
             field3: 0,
@@ -222,10 +219,9 @@ fn test_regression_292() {
         field3: u8,
     }
 
+    let mut cursor = Cursor::new(test_data);
     assert_eq!(
-        ReaderBitPadding1::from_reader((&mut test_data.as_slice(), 0))
-            .unwrap()
-            .1,
+        ReaderBitPadding1::from_reader((&mut cursor, 0)).unwrap().1,
         ReaderBitPadding1 {
             field1: 0,
             field2: 0xff,
@@ -245,10 +241,9 @@ fn test_regression_292() {
         field3: u8,
     }
 
+    let mut cursor = Cursor::new(test_data);
     assert_eq!(
-        ReaderTwo::from_reader((&mut test_data.as_slice(), 0))
-            .unwrap()
-            .1,
+        ReaderTwo::from_reader((&mut cursor, 0)).unwrap().1,
         ReaderTwo {
             field1: 0b11,
             field2: 0,
@@ -268,10 +263,9 @@ fn test_regression_292() {
         field3: u8,
     }
 
+    let mut cursor = Cursor::new(test_data);
     assert_eq!(
-        ReaderU16Le::from_reader((&mut test_data.as_slice(), 0))
-            .unwrap()
-            .1,
+        ReaderU16Le::from_reader((&mut cursor, 0)).unwrap().1,
         ReaderU16Le {
             field1: 0b11,
             field2: 0,
@@ -291,10 +285,9 @@ fn test_regression_292() {
         field3: u8,
     }
 
+    let mut cursor = Cursor::new(test_data);
     assert_eq!(
-        ReaderU16Be::from_reader((&mut test_data.as_slice(), 0))
-            .unwrap()
-            .1,
+        ReaderU16Be::from_reader((&mut cursor, 0)).unwrap().1,
         ReaderU16Be {
             field1: 0b11,
             field2: 0,
@@ -314,10 +307,9 @@ fn test_regression_292() {
         field3: i8,
     }
 
+    let mut cursor = Cursor::new(test_data);
     assert_eq!(
-        ReaderI16Le::from_reader((&mut test_data.as_slice(), 0))
-            .unwrap()
-            .1,
+        ReaderI16Le::from_reader((&mut cursor, 0)).unwrap().1,
         ReaderI16Le {
             field1: -0b01,
             field2: 1,
@@ -337,10 +329,9 @@ fn test_regression_292() {
         field3: i8,
     }
 
+    let mut cursor = Cursor::new(test_data);
     assert_eq!(
-        ReaderI16Be::from_reader((&mut test_data.as_slice(), 0))
-            .unwrap()
-            .1,
+        ReaderI16Be::from_reader((&mut cursor, 0)).unwrap().1,
         ReaderI16Be {
             field1: -0b01,
             field2: 1,
diff --git a/tests/test_seek.rs b/tests/test_seek.rs
new file mode 100644
index 0000000..6d3d611
--- /dev/null
+++ b/tests/test_seek.rs
@@ -0,0 +1,117 @@
+use deku::prelude::*;
+use hexlit::hex;
+use rstest::*;
+
+#[derive(DekuRead, DekuWrite, Debug, PartialEq, Eq)]
+pub struct Test {
+    // how many following bytes to skip
+    skip_u8: u8,
+    #[deku(seek_from_current = "*skip_u8")]
+    byte: u8,
+    #[deku(seek_from_current = "0")]
+    byte_after: u8,
+    #[deku(seek_rewind)]
+    byte_after_rewind: u8,
+    #[deku(seek_from_start = "2")]
+    byte_again: u8,
+    #[deku(seek_from_end = "-1")]
+    another: u8,
+}
+
+#[rstest(input, expected,
+    case(&hex!("01002030"), Test{ skip_u8: 1, byte: 0x20, byte_after: 0x30, byte_after_rewind: 0x01, byte_again: 0x20, another: 0x30 }),
+    case(&hex!("0200002030"), Test{ skip_u8: 2, byte: 0x20, byte_after: 0x30, byte_after_rewind: 0x02, byte_again: 0x00, another: 0x30 }),
+    case(&hex!("00ffaa"), Test{ skip_u8: 0, byte: 0xff, byte_after: 0xaa, byte_after_rewind: 0x00, byte_again: 0xaa, another: 0xaa }),
+)]
+fn test_seek(input: &[u8], expected: Test) {
+    let input = input.to_vec();
+
+    let mut cursor = std::io::Cursor::new(input.clone());
+    let (_, ret_read) = Test::from_reader((&mut cursor, 0)).unwrap();
+
+    assert_eq!(ret_read, expected);
+
+    let bytes = ret_read.to_bytes().unwrap();
+    assert_eq!(bytes, input);
+}
+
+#[derive(DekuRead, DekuWrite, Debug, PartialEq, Eq)]
+#[deku(seek_from_current = "skip", ctx = "skip: usize")]
+pub struct SeekCtxBefore {
+    byte: u8,
+}
+
+#[rstest(input, ctx, expected,
+    case(&hex!("0003"), 1, SeekCtxBefore{ byte: 0x03 }),
+    case(&hex!("000004"), 2, SeekCtxBefore{ byte: 0x04 }),
+)]
+fn test_seek_ctx_before(input: &[u8], ctx: usize, expected: SeekCtxBefore) {
+    use std::io::Cursor;
+    let input = input.to_vec();
+
+    let mut cursor = std::io::Cursor::new(input.clone());
+    let mut reader = Reader::new(&mut cursor);
+    let ret_read = SeekCtxBefore::from_reader_with_ctx(&mut reader, ctx).unwrap();
+
+    assert_eq!(ret_read, expected);
+
+    let mut buf = vec![];
+    let mut cursor = Cursor::new(&mut buf);
+    let mut writer = Writer::new(&mut cursor);
+    let _ = ret_read.to_writer(&mut writer, ctx).unwrap();
+    assert_eq!(buf, input);
+}
+
+#[derive(DekuRead, DekuWrite, Debug, PartialEq, Eq)]
+#[deku(seek_from_start = "1")]
+pub struct SeekCtxBeforeStart {
+    byte: u8,
+}
+
+#[rstest(input, expected,
+    case(&hex!("0003"), SeekCtxBeforeStart{ byte: 0x03 }),
+    case(&hex!("00ff"), SeekCtxBeforeStart{ byte: 0xff }),
+)]
+fn test_seek_ctx_start(input: &[u8], expected: SeekCtxBeforeStart) {
+    use std::io::Cursor;
+    let input = input.to_vec();
+
+    let mut cursor = std::io::Cursor::new(input.clone());
+    let mut reader = Reader::new(&mut cursor);
+    let ret_read = SeekCtxBeforeStart::from_reader_with_ctx(&mut reader, ()).unwrap();
+
+    assert_eq!(ret_read, expected);
+
+    let mut buf = vec![];
+    let mut cursor = Cursor::new(&mut buf);
+    let mut writer = Writer::new(&mut cursor);
+    let _ = ret_read.to_writer(&mut writer, ()).unwrap();
+    assert_eq!(buf, input);
+}
+
+#[derive(DekuRead, DekuWrite, Debug, PartialEq, Eq)]
+#[deku(seek_from_end = "-2")]
+pub struct SeekCtxBeforeEnd {
+    byte: u8,
+}
+
+#[rstest(input, expected,
+    case(&hex!("000300"), SeekCtxBeforeEnd{ byte: 0x03 }),
+    case(&hex!("00ff00"), SeekCtxBeforeEnd{ byte: 0xff }),
+)]
+fn test_seek_ctx_end(input: &[u8], expected: SeekCtxBeforeEnd) {
+    use std::io::Cursor;
+    let input = input.to_vec();
+
+    let mut cursor = std::io::Cursor::new(input.clone());
+    let mut reader = Reader::new(&mut cursor);
+    let ret_read = SeekCtxBeforeEnd::from_reader_with_ctx(&mut reader, ()).unwrap();
+
+    assert_eq!(ret_read, expected);
+
+    let mut buf = vec![0, 0, 0];
+    let mut cursor = Cursor::new(&mut buf);
+    let mut writer = Writer::new(&mut cursor);
+    let _ = ret_read.to_writer(&mut writer, ()).unwrap();
+    assert_eq!(buf, input);
+}