Skip to content

Commit 9efc68e

Browse files
committed
Generalized Mode Handling
1 parent dda3d7f commit 9efc68e

File tree

2 files changed

+53
-19
lines changed

2 files changed

+53
-19
lines changed

vm/src/stdlib/io.rs

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* I/O core tools.
33
*/
44

5+
use std::collections::HashSet;
6+
57
use std::io::prelude::*;
68
use std::os::unix::io::{FromRawFd,IntoRawFd};
79

@@ -12,7 +14,7 @@ use super::super::obj::objstr;
1214
use super::super::obj::objint;
1315
use super::super::obj::objbytes;
1416
use super::super::obj::objtype;
15-
use super::os::os_open;
17+
use super::os;
1618

1719
use num_bigint::{ToBigInt};
1820
use num_traits::ToPrimitive;
@@ -23,6 +25,16 @@ use super::super::pyobject::{
2325

2426
use super::super::vm::VirtualMachine;
2527

28+
fn compute_c_flag(mode : &String) -> u16 {
29+
match mode.as_ref() {
30+
"w" => 512,
31+
"x" => 512,
32+
"a" => 8,
33+
"+" => 2,
34+
_ => 0
35+
}
36+
}
37+
2638
fn string_io_init(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult {
2739
// arg_check!(vm, args, required = [(s, Some(vm.ctx.str_type()))]);
2840
// TODO
@@ -71,6 +83,9 @@ fn buffered_reader_read(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
7183

7284
let raw = vm.ctx.get_attr(&buffered, "raw").unwrap();
7385

86+
//Iterates through the raw class, invoking the readinto method
87+
//to obtain buff_size many bytes. Exit when less than buff_size many
88+
//bytes are returned (when the end of the file is reached).
7489
while length == buff_size {
7590
let raw_read = vm.get_method(raw.clone(), &"readinto".to_string()).unwrap();
7691
match vm.invoke(raw_read, PyFuncArgs::new(vec![buffer.clone()], vec![])) {
@@ -80,6 +95,7 @@ fn buffered_reader_read(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
8095
}
8196
}
8297

98+
//Copy bytes from the buffer vector into the results vector
8399
match buffer.borrow_mut().kind {
84100
PyObjectKind::Bytes { ref mut value } => {
85101
result.extend(value.iter().cloned());
@@ -103,23 +119,22 @@ fn file_io_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
103119
optional = [(mode, Some(vm.ctx.str_type()))]
104120
);
105121

106-
let mode = if let Some(m) = mode {
107-
objstr::get_value(m)
108-
} else {
109-
"r".to_string()
110-
};
111-
112-
let os_mode = match mode.as_ref() {
113-
"r" => 0.to_bigint(),
114-
_ => 512.to_bigint()
122+
let rust_mode = match mode {
123+
Some(m) => objstr::get_value(m),
124+
None => "r".to_string()
115125
};
116-
let args = vec![name.clone(), vm.ctx.new_int(os_mode.unwrap())];
117-
let fileno = os_open(vm, PyFuncArgs::new(args, vec![]));
118126

127+
match compute_c_flag(&rust_mode).to_bigint() {
128+
Some(os_mode) => {
129+
let args = vec![name.clone(), vm.ctx.new_int(os_mode)];
130+
let fileno = os::os_open(vm, PyFuncArgs::new(args, vec![]));
119131

120-
vm.ctx.set_attr(&file_io, "name", name.clone());
121-
vm.ctx.set_attr(&file_io, "fileno", fileno.unwrap());
122-
Ok(vm.get_none())
132+
vm.ctx.set_attr(&file_io, "name", name.clone());
133+
vm.ctx.set_attr(&file_io, "fileno", fileno.unwrap());
134+
Ok(vm.get_none())
135+
},
136+
None => Err(vm.new_type_error(format!("invalid mode {}", rust_mode)))
137+
}
123138
}
124139

125140
fn file_io_read(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -174,7 +189,7 @@ fn file_io_readinto(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
174189
};
175190

176191
let mut f = handle.take(length);
177-
match obj.borrow_mut().kind {
192+
match obj.borrow_mut().kind {
178193
PyObjectKind::Bytes { ref mut value } => {
179194
value.clear();
180195
match f.read_to_end(&mut *value) {
@@ -252,7 +267,6 @@ fn text_io_wrapper_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
252267
Ok(vm.get_none())
253268
}
254269

255-
256270
fn text_io_base_read(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
257271
arg_check!(
258272
vm,
@@ -278,7 +292,7 @@ pub fn io_open(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
278292
arg_check!(
279293
vm,
280294
args,
281-
required = [(_file, Some(vm.ctx.str_type()))],
295+
required = [(file, Some(vm.ctx.str_type()))],
282296
optional = [(mode, Some(vm.ctx.str_type()))]
283297
);
284298

@@ -291,6 +305,24 @@ pub fn io_open(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
291305
"rt".to_string()
292306
};
293307

308+
let mut raw_modes = HashSet::new();
309+
310+
// Add some books.
311+
raw_modes.insert("a".to_string());
312+
raw_modes.insert("r".to_string());
313+
raw_modes.insert("x".to_string());
314+
raw_modes.insert("w".to_string());
315+
316+
//This is not a terribly elegant way to separate the file mode from
317+
//the "type" flag - this should be improved. The intention here is to
318+
//match a valid flag for the file_io_init call:
319+
//https://docs.python.org/3/library/io.html#io.FileIO
320+
let modes: Vec<char> = rust_mode.chars().filter(|a| raw_modes.contains(&a.to_string())).collect();
321+
322+
if modes.len() == 0 || modes.len() > 1 {
323+
return Err(vm.new_value_error("Invalid Mode".to_string()))
324+
}
325+
294326
//Class objects (potentially) consumed by io.open
295327
//RawIO: FileIO
296328
//Buffered: BufferedWriter, BufferedReader
@@ -302,7 +334,8 @@ pub fn io_open(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
302334

303335
//Construct a FileIO (subclass of RawIOBase)
304336
//This is subsequently consumed by a Buffered Class.
305-
let file_io = vm.invoke(file_io_class, args.clone()).unwrap();
337+
let file_args = PyFuncArgs::new(vec![file.clone(), vm.ctx.new_str(modes[0].to_string())] , vec![]);
338+
let file_io = vm.invoke(file_io_class, file_args).unwrap();
306339

307340
//Create Buffered class to consume FileIO. The type of buffered class depends on
308341
//the operation in the mode.

vm/src/stdlib/os.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
5151
ctx.set_attr(&py_mod, "O_WRONLY", ctx.new_int(1.to_bigint().unwrap()));
5252
ctx.set_attr(&py_mod, "O_RDWR", ctx.new_int(2.to_bigint().unwrap()));
5353
ctx.set_attr(&py_mod, "O_NONBLOCK", ctx.new_int(3.to_bigint().unwrap()));
54+
ctx.set_attr(&py_mod, "O_APPEND", ctx.new_int(8.to_bigint().unwrap()));
5455
ctx.set_attr(&py_mod, "O_CREAT", ctx.new_int(512.to_bigint().unwrap()));
5556
py_mod
5657
}

0 commit comments

Comments
 (0)