Use InputStreamBase for ZipDecoder.decodeBuffer
diff --git a/lib/src/io/input_file_stream.dart b/lib/src/io/input_file_stream.dart
index 276d5d2..e6a314e 100644
--- a/lib/src/io/input_file_stream.dart
+++ b/lib/src/io/input_file_stream.dart
@@ -36,6 +36,22 @@
     _readBuffer();
   }
 
+  InputFileStream.clone(InputFileStream other, {int? position, int? length})
+    : path = other.path,
+      _file = other._file,
+      byteOrder = other.byteOrder,
+      _fileSize = other._fileSize,
+      _filePosition = other._filePosition,
+      _bufferSize = other._bufferSize,
+      _buffer = Uint8List(other._bufferSize) {
+    if (position != null) {
+      this.position = position;
+    }
+    if (length != null) {
+      _fileSize = this.position + length;
+    }
+  }
+
   void close() {
     _file.closeSync();
     _fileSize = 0;
@@ -48,6 +64,15 @@
   int get position => _filePosition;
 
   @override
+  set position(int v) {
+    if (v < _filePosition) {
+      rewind(_filePosition - v);
+    } else if (v > _filePosition) {
+      skip(v - _filePosition);
+    }
+  }
+
+  @override
   bool get isEOS =>
       (_filePosition >= _fileSize) && (_bufferPosition >= _bufferSize);
 
@@ -83,6 +108,11 @@
     }
   }
 
+  @override
+  InputStreamBase subset([int? position, int? length]) {
+    return InputFileStream.clone(this, position:position, length:length);
+  }
+
   /// Read [count] bytes from an [offset] of the current read position, without
   /// moving the read position.
   @override
diff --git a/lib/src/util/input_stream.dart b/lib/src/util/input_stream.dart
index 051b64f..702718e 100644
--- a/lib/src/util/input_stream.dart
+++ b/lib/src/util/input_stream.dart
@@ -7,6 +7,8 @@
   ///  The current read position relative to the start of the buffer.
   int get position;
 
+  set position(int v);
+
   /// How many bytes are left in the stream.
   int get length;
 
@@ -32,6 +34,8 @@
   /// Read [count] bytes from the stream.
   InputStream readBytes(int count);
 
+  InputStreamBase subset([int? position, int? length]);
+
   /// Read a null-terminated string, or if [len] is provided, that number of
   /// bytes returned as a string.
   String readString({int? size, bool utf8 = true});
@@ -84,6 +88,9 @@
   @override
   int get position => offset - start;
 
+  @override
+  set position(int v) { offset = start + v; }
+
   /// How many bytes are left in the stream.
   @override
   int get length => _length - (offset - start);
@@ -115,7 +122,8 @@
   /// to the start of the buffer.  If [position] is not specified, the current
   /// read position is used. If [length] is not specified, the remainder of this
   /// stream is used.
-  InputStream subset([int? position, int? length]) {
+  @override
+  InputStreamBase subset([int? position, int? length]) {
     if (position == null) {
       position = offset;
     } else {
@@ -149,7 +157,7 @@
   /// moving the read position.
   @override
   InputStream peekBytes(int count, [int offset = 0]) {
-    return subset((this.offset - start) + offset, count);
+    return subset((this.offset - start) + offset, count) as InputStream;
   }
 
   /// Move the read position by [count] bytes.
@@ -169,7 +177,7 @@
   InputStream readBytes(int count) {
     final bytes = subset(offset - start, count);
     offset += bytes.length;
-    return bytes;
+    return bytes as InputStream;
   }
 
   /// Read a null-terminated string, or if [len] is provided, that number of
diff --git a/lib/src/zip/zip_directory.dart b/lib/src/zip/zip_directory.dart
index 6382914..b60f7f7 100644
--- a/lib/src/zip/zip_directory.dart
+++ b/lib/src/zip/zip_directory.dart
@@ -24,9 +24,9 @@
 
   ZipDirectory();
 
-  ZipDirectory.read(InputStream input, {String? password}) {
+  ZipDirectory.read(InputStreamBase input, {String? password}) {
     filePosition = _findSignature(input);
-    input.offset = filePosition;
+    input.position = filePosition;
     final signature = input.readUint32(); // ignore: unused_local_variable
     numberOfThisDisk = input.readUint16();
     diskWithTheStartOfTheCentralDirectory = input.readUint16();
@@ -54,8 +54,8 @@
     }
   }
 
-  void _readZip64Data(InputStream input) {
-    final ip = input.offset;
+  void _readZip64Data(InputStreamBase input) {
+    final ip = input.position;
     // Check for zip64 data.
 
     // Zip64 end of central directory locator
@@ -76,7 +76,7 @@
     var sig = zip64.readUint32();
     // If this ins't the signature we're looking for, nothing more to do.
     if (sig != ZIP64_EOCD_LOCATOR_SIGNATURE) {
-      input.offset = ip;
+      input.position = ip;
       return;
     }
 
@@ -84,7 +84,7 @@
     final zip64DirOffset = zip64.readUint64();
     final numZip64Disks = zip64.readUint32(); // ignore: unused_local_variable
 
-    input.offset = zip64DirOffset;
+    input.position = zip64DirOffset;
 
     // Zip64 end of central directory record
     // signature                       4 bytes  (0x06064b50)
@@ -106,7 +106,7 @@
     // zip64 extensible data sector    (variable size)
     sig = input.readUint32();
     if (sig != ZIP64_EOCD_SIGNATURE) {
-      input.offset = ip;
+      input.position = ip;
       return;
     }
 
@@ -128,25 +128,24 @@
     centralDirectorySize = dirSize;
     centralDirectoryOffset = dirOffset;
 
-    input.offset = ip;
+    input.position = ip;
   }
 
-  int _findSignature(InputStream input) {
-    final pos = input.offset;
+  int _findSignature(InputStreamBase input) {
+    final pos = input.position;
     final length = input.length;
 
     // The directory and archive contents are written to the end of the zip
-    // file.  We need to search from the end to find these structures,
+    // file. We need to search from the end to find these structures,
     // starting with the 'End of central directory' record (EOCD).
     for (var ip = length - 4; ip >= 0; --ip) {
-      input.offset = ip;
+      input.position = ip;
       final sig = input.readUint32();
       if (sig == SIGNATURE) {
-        input.offset = pos;
+        input.position = pos;
         return ip;
       }
     }
-
     throw ArchiveException('Could not find End of Central Directory Record');
   }
 }
diff --git a/lib/src/zip/zip_file.dart b/lib/src/zip/zip_file.dart
index 7d5a2e5..2bf07e0 100644
--- a/lib/src/zip/zip_file.dart
+++ b/lib/src/zip/zip_file.dart
@@ -24,7 +24,7 @@
   List<int> extraField = []; // 2 bytes length, n-bytes data
   ZipFileHeader? header;
 
-  ZipFile([InputStream? input, this.header, String? password]) {
+  ZipFile([InputStreamBase? input, this.header, String? password]) {
     if (input != null) {
       signature = input.readUint32();
       if (signature != SIGNATURE) {
diff --git a/lib/src/zip/zip_file_header.dart b/lib/src/zip/zip_file_header.dart
index 94bfaf5..5a61042 100644
--- a/lib/src/zip/zip_file_header.dart
+++ b/lib/src/zip/zip_file_header.dart
@@ -21,7 +21,8 @@
   String fileComment = '';
   ZipFile? file;
 
-  ZipFileHeader([InputStream? input, InputStream? bytes, String? password]) {
+  ZipFileHeader([InputStreamBase? input, InputStreamBase? bytes,
+                 String? password]) {
     if (input != null) {
       versionMadeBy = input.readUint16();
       versionNeededToExtract = input.readUint16();
@@ -81,7 +82,7 @@
       }
 
       if (bytes != null) {
-        bytes.offset = localHeaderOffset!;
+        bytes.position = localHeaderOffset!;
         file = ZipFile(bytes, this, password);
       }
     }
diff --git a/lib/src/zip_decoder.dart b/lib/src/zip_decoder.dart
index 84f200e..fa27dc0 100644
--- a/lib/src/zip_decoder.dart
+++ b/lib/src/zip_decoder.dart
@@ -14,7 +14,7 @@
     return decodeBuffer(InputStream(data), verify: verify, password: password);
   }
 
-  Archive decodeBuffer(InputStream input,
+  Archive decodeBuffer(InputStreamBase input,
       {bool verify = false, String? password}) {
     directory = ZipDirectory.read(input, password: password);
     final archive = Archive();