@@ -31,7 +31,7 @@ mod _io {
3131
3232 use bstr:: ByteSlice ;
3333 use crossbeam_utils:: atomic:: AtomicCell ;
34- use num_traits:: { NumCast , ToPrimitive } ;
34+ use num_traits:: ToPrimitive ;
3535 use std:: io:: { self , prelude:: * , Cursor , SeekFrom } ;
3636 use std:: ops:: Range ;
3737
@@ -641,6 +641,35 @@ mod _io {
641641 Ok ( offset)
642642 }
643643
644+ fn seek ( & mut self , target : Offset , whence : i32 , vm : & VirtualMachine ) -> PyResult < Offset > {
645+ if matches ! ( whence, 0 | 1 ) && self . readable ( ) {
646+ let current = self . raw_tell_cache ( vm) ?;
647+ let available = self . readahead ( ) ;
648+ if available > 0 {
649+ let offset = if whence == 0 {
650+ target - ( current - self . raw_offset ( ) )
651+ } else {
652+ target
653+ } ;
654+ if offset >= -self . pos && offset <= available {
655+ self . pos += offset;
656+ return Ok ( current - available + offset) ;
657+ }
658+ }
659+ }
660+ // vm.invoke(&vm.get_attribute(raw, "seek")?, args)
661+ if self . writable ( ) {
662+ self . flush ( vm) ?;
663+ }
664+ let target = if whence == 1 { -target } else { target } ;
665+ let n = self . raw_seek ( target, whence, vm) ?;
666+ self . raw_pos = -1 ;
667+ if self . readable ( ) {
668+ self . reset_read ( ) ;
669+ }
670+ Ok ( n)
671+ }
672+
644673 fn raw_tell ( & mut self , vm : & VirtualMachine ) -> PyResult < Offset > {
645674 let ret = vm. call_method ( self . check_init ( vm) ?, "seek" , ( ) ) ?;
646675 let offset = get_offset ( ret, vm) ?;
@@ -653,6 +682,14 @@ mod _io {
653682 Ok ( offset)
654683 }
655684
685+ fn raw_tell_cache ( & mut self , vm : & VirtualMachine ) -> PyResult < Offset > {
686+ if self . abs_pos == -1 {
687+ self . raw_tell ( vm)
688+ } else {
689+ Ok ( self . abs_pos )
690+ }
691+ }
692+
656693 /// None means non-blocking failed
657694 fn raw_write (
658695 & mut self ,
@@ -943,9 +980,9 @@ mod _io {
943980 }
944981
945982 fn get_offset ( obj : PyObjectRef , vm : & VirtualMachine ) -> PyResult < Offset > {
983+ use std:: convert:: TryInto ;
946984 let int = vm. to_index ( & obj) ?;
947- // TODO: patch num-traits to impl<T: ToPrimitive> ToPrimitive for &T
948- NumCast :: from ( int. borrow_value ( ) . clone ( ) ) . ok_or_else ( || {
985+ int. borrow_value ( ) . try_into ( ) . map_err ( |_| {
949986 vm. new_value_error ( format ! (
950987 "cannot fit '{}' into an offset-sized integer" ,
951988 obj. class( ) . name
@@ -1011,21 +1048,24 @@ mod _io {
10111048
10121049 Ok ( ( ) )
10131050 }
1014-
10151051 #[ pymethod]
10161052 fn seek (
10171053 & self ,
1018- pos : PyObjectRef ,
1054+ target : PyObjectRef ,
10191055 whence : OptionalArg < i32 > ,
10201056 vm : & VirtualMachine ,
10211057 ) -> PyResult < Offset > {
1022- let pos = get_offset ( pos, vm) ?;
10231058 let whence = whence. unwrap_or ( 0 ) ;
1024- self . lock ( vm) ?. raw_seek ( pos, whence, vm)
1059+ let mut data = self . lock ( vm) ?;
1060+ let raw = data. check_init ( vm) ?;
1061+ ensure_unclosed ( raw, "seek of closed file" , vm) ?;
1062+ let target = get_offset ( target, vm) ?;
1063+ data. seek ( target, whence, vm)
10251064 }
10261065 #[ pymethod]
10271066 fn tell ( & self , vm : & VirtualMachine ) -> PyResult < Offset > {
1028- self . lock ( vm) ?. raw_tell ( vm)
1067+ let mut data = self . lock ( vm) ?;
1068+ Ok ( data. raw_tell ( vm) ? - data. raw_offset ( ) )
10291069 }
10301070 #[ pymethod]
10311071 fn truncate (
@@ -1150,28 +1190,6 @@ mod _io {
11501190 None => data. read_all ( vm) ,
11511191 }
11521192 }
1153-
1154- #[ pymethod]
1155- fn readinto ( instance : PyObjectRef , obj : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
1156- vm. call_method ( & vm. get_attribute ( instance, "raw" ) ?, "readinto" , ( obj, ) )
1157- }
1158-
1159- #[ pymethod]
1160- fn seekable ( _self : PyObjectRef ) -> bool {
1161- true
1162- }
1163-
1164- #[ pymethod]
1165- fn seek (
1166- instance : PyObjectRef ,
1167- offset : PyObjectRef ,
1168- how : OptionalArg ,
1169- vm : & VirtualMachine ,
1170- ) -> PyResult {
1171- let raw = vm. get_attribute ( instance, "raw" ) ?;
1172- let args: Vec < _ > = std:: iter:: once ( offset) . chain ( how. into_option ( ) ) . collect ( ) ;
1173- vm. invoke ( & vm. get_attribute ( raw, "seek" ) ?, args)
1174- }
11751193 }
11761194
11771195 #[ pyclass( name = "BufferedWriter" , noattr) ]
@@ -1211,23 +1229,6 @@ mod _io {
12111229 //This should be replaced with a more appropriate chunking implementation
12121230 vm. call_method ( & raw , "write" , ( obj, ) )
12131231 }
1214-
1215- #[ pymethod]
1216- fn seekable ( _self : PyObjectRef ) -> bool {
1217- true
1218- }
1219-
1220- #[ pymethod]
1221- fn seek (
1222- instance : PyObjectRef ,
1223- offset : PyObjectRef ,
1224- how : OptionalArg ,
1225- vm : & VirtualMachine ,
1226- ) -> PyResult {
1227- let raw = vm. get_attribute ( instance, "raw" ) ?;
1228- let args: Vec < _ > = std:: iter:: once ( offset) . chain ( how. into_option ( ) ) . collect ( ) ;
1229- vm. invoke ( & vm. get_attribute ( raw, "seek" ) ?, args)
1230- }
12311232 }
12321233
12331234 #[ derive( FromArgs ) ]
0 commit comments