1212import unicodedata
1313from collections .abc import Iterable , Iterator
1414from pathlib import Path
15- from typing import Literal , Optional , Union
15+ from typing import Literal , Optional , Protocol , Union , overload
1616
1717from dissect .cstruct import cstruct
1818from structlog import get_logger
@@ -269,8 +269,18 @@ def iterate_patterns(
269269 file .seek (initial_position )
270270
271271
272+ class RandomReader (Protocol ):
273+ # File implements this interface
274+
275+ @overload
276+ def read (self ) -> bytes : ...
277+ @overload
278+ def read (self , n : int , / ) -> bytes : ...
279+ def seek (self , pos : int , / , whence : int = io .SEEK_SET ) -> int : ...
280+
281+
272282def iterate_file (
273- file : File ,
283+ file : RandomReader ,
274284 start_offset : int ,
275285 size : int ,
276286 # default buffer size in shutil for unix based systems
@@ -297,7 +307,7 @@ def iterate_file(
297307 yield data
298308
299309
300- def carve (carve_path : Path , file : File , start_offset : int , size : int ):
310+ def carve (carve_path : Path , file : RandomReader , start_offset : int , size : int ):
301311 """Extract part of a file."""
302312 carve_path .parent .mkdir (parents = True , exist_ok = True )
303313
0 commit comments