3
3
*/
4
4
use std:: cell:: { RefCell , RefMut } ;
5
5
use std:: fs;
6
- use std:: io:: prelude:: * ;
7
- use std:: io:: Cursor ;
8
- use std:: io:: SeekFrom ;
6
+ use std:: io:: { self , prelude:: * , Cursor , SeekFrom } ;
9
7
10
8
use num_traits:: ToPrimitive ;
11
9
10
+ use crate :: exceptions:: PyBaseExceptionRef ;
12
11
use crate :: function:: { OptionalArg , OptionalOption , PyFuncArgs } ;
13
12
use crate :: obj:: objbool;
14
13
use crate :: obj:: objbytearray:: PyByteArray ;
@@ -26,9 +25,31 @@ use crate::vm::VirtualMachine;
26
25
fn byte_count ( bytes : OptionalOption < i64 > ) -> i64 {
27
26
bytes. flat_option ( ) . unwrap_or ( -1 as i64 )
28
27
}
28
+ fn os_err ( vm : & VirtualMachine , err : io:: Error ) -> PyBaseExceptionRef {
29
+ #[ cfg( any( not( target_arch = "wasm32" ) , target_os = "wasi" ) ) ]
30
+ {
31
+ super :: os:: convert_io_error ( vm, err)
32
+ }
33
+ #[ cfg( all( target_arch = "wasm32" , not( target_os = "wasi" ) ) ) ]
34
+ {
35
+ vm. new_os_error ( err. to_string ( ) )
36
+ }
37
+ }
29
38
30
39
const DEFAULT_BUFFER_SIZE : usize = 8 * 1024 ;
31
40
41
+ fn seekfrom ( vm : & VirtualMachine , offset : PyObjectRef , how : OptionalArg < i32 > ) -> PyResult < SeekFrom > {
42
+ let seek = match how {
43
+ OptionalArg :: Present ( 0 ) | OptionalArg :: Missing => {
44
+ SeekFrom :: Start ( u64:: try_from_object ( vm, offset) ?)
45
+ }
46
+ OptionalArg :: Present ( 1 ) => SeekFrom :: Current ( i64:: try_from_object ( vm, offset) ?) ,
47
+ OptionalArg :: Present ( 2 ) => SeekFrom :: End ( i64:: try_from_object ( vm, offset) ?) ,
48
+ _ => return Err ( vm. new_value_error ( "invalid value for how" . to_owned ( ) ) ) ,
49
+ } ;
50
+ Ok ( seek)
51
+ }
52
+
32
53
#[ derive( Debug ) ]
33
54
struct BufferedIO {
34
55
cursor : Cursor < Vec < u8 > > ,
@@ -54,11 +75,8 @@ impl BufferedIO {
54
75
}
55
76
56
77
//skip to the jth position
57
- fn seek ( & mut self , offset : u64 ) -> Option < u64 > {
58
- match self . cursor . seek ( SeekFrom :: Start ( offset) ) {
59
- Ok ( _) => Some ( offset) ,
60
- Err ( _) => None ,
61
- }
78
+ fn seek ( & mut self , seek : SeekFrom ) -> io:: Result < u64 > {
79
+ self . cursor . seek ( seek)
62
80
}
63
81
64
82
//Read k bytes from the object and return.
@@ -142,11 +160,15 @@ impl PyStringIORef {
142
160
}
143
161
144
162
//skip to the jth position
145
- fn seek ( self , offset : u64 , vm : & VirtualMachine ) -> PyResult {
146
- match self . buffer ( vm) ?. seek ( offset) {
147
- Some ( value) => Ok ( vm. ctx . new_int ( value) ) ,
148
- None => Err ( vm. new_value_error ( "Error Performing Operation" . to_owned ( ) ) ) ,
149
- }
163
+ fn seek (
164
+ self ,
165
+ offset : PyObjectRef ,
166
+ how : OptionalArg < i32 > ,
167
+ vm : & VirtualMachine ,
168
+ ) -> PyResult < u64 > {
169
+ self . buffer ( vm) ?
170
+ . seek ( seekfrom ( vm, offset, how) ?)
171
+ . map_err ( |err| os_err ( vm, err) )
150
172
}
151
173
152
174
fn seekable ( self ) -> bool {
@@ -264,11 +286,15 @@ impl PyBytesIORef {
264
286
}
265
287
266
288
//skip to the jth position
267
- fn seek ( self , offset : u64 , vm : & VirtualMachine ) -> PyResult {
268
- match self . buffer ( vm) ?. seek ( offset) {
269
- Some ( value) => Ok ( vm. ctx . new_int ( value) ) ,
270
- None => Err ( vm. new_value_error ( "Error Performing Operation" . to_owned ( ) ) ) ,
271
- }
289
+ fn seek (
290
+ self ,
291
+ offset : PyObjectRef ,
292
+ how : OptionalArg < i32 > ,
293
+ vm : & VirtualMachine ,
294
+ ) -> PyResult < u64 > {
295
+ self . buffer ( vm) ?
296
+ . seek ( seekfrom ( vm, offset, how) ?)
297
+ . map_err ( |err| os_err ( vm, err) )
272
298
}
273
299
274
300
fn seekable ( self ) -> bool {
@@ -509,6 +535,22 @@ fn buffered_reader_seekable(_self: PyObjectRef) -> bool {
509
535
true
510
536
}
511
537
538
+ fn buffered_reader_seek (
539
+ instance : PyObjectRef ,
540
+ offset : PyObjectRef ,
541
+ how : OptionalArg ,
542
+ vm : & VirtualMachine ,
543
+ ) -> PyResult {
544
+ let raw = vm. get_attribute ( instance, "raw" ) ?;
545
+ let args: Vec < _ > = std:: iter:: once ( offset) . chain ( how. into_option ( ) ) . collect ( ) ;
546
+ vm. invoke ( & vm. get_attribute ( raw, "seek" ) ?, args)
547
+ }
548
+
549
+ fn buffered_reader_tell ( instance : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
550
+ let raw = vm. get_attribute ( instance, "raw" ) ?;
551
+ vm. invoke ( & vm. get_attribute ( raw, "tell" ) ?, vec ! [ ] )
552
+ }
553
+
512
554
fn buffered_reader_close ( instance : PyObjectRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
513
555
let raw = vm. get_attribute ( instance, "raw" ) ?;
514
556
vm. invoke ( & vm. get_attribute ( raw, "close" ) ?, vec ! [ ] ) ?;
@@ -670,6 +712,35 @@ mod fileio {
670
712
true
671
713
}
672
714
715
+ fn file_io_seek (
716
+ instance : PyObjectRef ,
717
+ offset : PyObjectRef ,
718
+ how : OptionalArg < i32 > ,
719
+ vm : & VirtualMachine ,
720
+ ) -> PyResult < u64 > {
721
+ let mut handle = fio_get_fileno ( & instance, vm) ?;
722
+
723
+ let new_pos = handle
724
+ . seek ( seekfrom ( vm, offset, how) ?)
725
+ . map_err ( |e| os:: convert_io_error ( vm, e) ) ?;
726
+
727
+ fio_set_fileno ( & instance, handle, vm) ?;
728
+
729
+ Ok ( new_pos)
730
+ }
731
+
732
+ fn file_io_tell ( instance : PyObjectRef , vm : & VirtualMachine ) -> PyResult < u64 > {
733
+ let mut handle = fio_get_fileno ( & instance, vm) ?;
734
+
735
+ let pos = handle
736
+ . seek ( SeekFrom :: Current ( 0 ) )
737
+ . map_err ( |e| os:: convert_io_error ( vm, e) ) ?;
738
+
739
+ fio_set_fileno ( & instance, handle, vm) ?;
740
+
741
+ Ok ( pos)
742
+ }
743
+
673
744
fn file_io_fileno ( instance : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
674
745
vm. get_attribute ( instance, "__fileno" )
675
746
}
@@ -683,6 +754,8 @@ mod fileio {
683
754
"write" => ctx. new_method( file_io_write) ,
684
755
"close" => ctx. new_method( file_io_close) ,
685
756
"seekable" => ctx. new_method( file_io_seekable) ,
757
+ "seek" => ctx. new_method( file_io_seek) ,
758
+ "tell" => ctx. new_method( file_io_tell) ,
686
759
"fileno" => ctx. new_method( file_io_fileno) ,
687
760
} )
688
761
}
@@ -968,6 +1041,8 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
968
1041
"__init__" => ctx. new_method( buffered_io_base_init) ,
969
1042
"read" => ctx. new_method( buffered_reader_read) ,
970
1043
"seekable" => ctx. new_method( buffered_reader_seekable) ,
1044
+ "seek" => ctx. new_method( buffered_reader_seek) ,
1045
+ "tell" => ctx. new_method( buffered_reader_tell) ,
971
1046
"close" => ctx. new_method( buffered_reader_close) ,
972
1047
"fileno" => ctx. new_method( buffered_io_base_fileno) ,
973
1048
} ) ;
@@ -1146,10 +1221,10 @@ mod tests {
1146
1221
let data = vec ! [ 1 , 2 , 3 , 4 ] ;
1147
1222
let count: u64 = 2 ;
1148
1223
let mut buffered = BufferedIO {
1149
- cursor : Cursor :: new ( data. clone ( ) ) ,
1224
+ cursor : Cursor :: new ( data) ,
1150
1225
} ;
1151
1226
1152
- assert_eq ! ( buffered. seek( count . clone ( ) ) . unwrap( ) , count) ;
1227
+ assert_eq ! ( buffered. seek( SeekFrom :: Start ( count ) ) . unwrap( ) , count) ;
1153
1228
assert_eq ! ( buffered. read( count. clone( ) as i64 ) . unwrap( ) , vec![ 3 , 4 ] ) ;
1154
1229
}
1155
1230
0 commit comments