Skip to content

Commit e96a701

Browse files
committed
Updates BytesIO to use "BufferedIO"
1 parent 8faab1f commit e96a701

File tree

1 file changed

+105
-49
lines changed

1 file changed

+105
-49
lines changed

vm/src/stdlib/io.rs

Lines changed: 105 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,70 @@ fn compute_c_flag(mode: &str) -> u16 {
3434
}
3535
}
3636

37+
fn byte_count(bytes: OptionalArg<Option<PyObjectRef>>) -> i64 {
38+
match bytes {
39+
OptionalArg::Present(Some(ref int)) => objint::get_value(int).to_i64().unwrap(),
40+
_ => (-1 as i64),
41+
}
42+
}
43+
44+
#[derive(Debug)]
45+
struct BufferedIO {
46+
cursor: Cursor<Vec<u8>>,
47+
}
48+
49+
impl BufferedIO {
50+
fn new(cursor: Cursor<Vec<u8>>) -> BufferedIO {
51+
BufferedIO { cursor: cursor }
52+
}
53+
54+
fn write(&mut self, data: Vec<u8>) -> Option<u64> {
55+
let length = data.len();
56+
57+
match self.cursor.write_all(&data) {
58+
Ok(_) => Some(length as u64),
59+
Err(_) => None,
60+
}
61+
}
62+
63+
//return the entire contents of the underlying
64+
fn getvalue(&self) -> Vec<u8> {
65+
self.cursor.clone().into_inner()
66+
}
67+
68+
//skip to the jth position
69+
fn seek(&mut self, offset: u64) -> Option<u64> {
70+
match self.cursor.seek(SeekFrom::Start(offset.clone())) {
71+
Ok(_) => Some(offset),
72+
Err(_) => None,
73+
}
74+
}
75+
76+
//Read k bytes from the object and return.
77+
fn read(&mut self, bytes: i64) -> Option<Vec<u8>> {
78+
let mut buffer = Vec::new();
79+
80+
//for a defined number of bytes, i.e. bytes != -1
81+
if bytes > 0 {
82+
let mut handle = self.cursor.clone().take(bytes as u64);
83+
//read handle into buffer
84+
if let Err(_) = handle.read_to_end(&mut buffer) {
85+
return None;
86+
}
87+
//the take above consumes the struct value
88+
//we add this back in with the takes into_inner method
89+
self.cursor = handle.into_inner();
90+
} else {
91+
//read handle into buffer
92+
if let Err(_) = self.cursor.read_to_end(&mut buffer) {
93+
return None;
94+
}
95+
};
96+
97+
Some(buffer)
98+
}
99+
}
100+
37101
#[derive(Debug)]
38102
struct PyStringIO {
39103
data: RefCell<Cursor<Vec<u8>>>,
@@ -131,7 +195,7 @@ fn string_io_new(
131195

132196
#[derive(Debug)]
133197
struct PyBytesIO {
134-
data: RefCell<Cursor<Vec<u8>>>,
198+
buffer: RefCell<BufferedIO>,
135199
}
136200

137201
type PyBytesIORef = PyRef<PyBytesIO>;
@@ -143,65 +207,36 @@ impl PyValue for PyBytesIO {
143207
}
144208

145209
impl PyBytesIORef {
146-
//write string to underlying vector
147210
fn write(self, data: objbytes::PyBytesRef, vm: &VirtualMachine) -> PyResult {
148211
let bytes = data.get_value();
149-
let length = bytes.len();
150212

151-
let mut cursor = self.data.borrow_mut();
152-
match cursor.write_all(bytes) {
153-
Ok(_) => Ok(vm.ctx.new_int(length)),
154-
Err(_) => Err(vm.new_type_error("Error Writing String".to_string())),
213+
match self.buffer.borrow_mut().write(bytes.to_vec()) {
214+
Some(value) => Ok(vm.ctx.new_int(value)),
215+
None => Err(vm.new_type_error("Error Writing Bytes".to_string())),
155216
}
156217
}
157-
158-
//return the entire contents of the underlying
218+
//Retrieves the entire bytes object value from the underlying buffer
159219
fn getvalue(self, vm: &VirtualMachine) -> PyResult {
160-
Ok(vm.ctx.new_bytes(self.data.borrow().clone().into_inner()))
161-
}
162-
163-
//skip to the jth position
164-
fn seek(self, offset: PyObjectRef, vm: &VirtualMachine) -> PyResult {
165-
let position = objint::get_value(&offset).to_u64().unwrap();
166-
if let Err(_) = self
167-
.data
168-
.borrow_mut()
169-
.seek(SeekFrom::Start(position.clone()))
170-
{
171-
return Err(vm.new_value_error("Error Retrieving Value".to_string()));
172-
}
173-
174-
Ok(vm.ctx.new_int(position))
220+
Ok(vm.ctx.new_bytes(self.buffer.borrow().getvalue()))
175221
}
176222

177-
//Read k bytes from the object and return.
223+
//Takes an integer k (bytes) and returns them from the underlying buffer
178224
//If k is undefined || k == -1, then we read all bytes until the end of the file.
179225
//This also increments the stream position by the value of k
180226
fn read(self, bytes: OptionalArg<Option<PyObjectRef>>, vm: &VirtualMachine) -> PyResult {
181-
let mut buffer = Vec::new();
182-
183-
match bytes {
184-
OptionalArg::Present(Some(ref integer)) => {
185-
let k = objint::get_value(integer).to_u64().unwrap();
186-
let mut handle = self.data.borrow().clone().take(k);
187-
188-
//read bytes into string
189-
if let Err(_) = handle.read_to_end(&mut buffer) {
190-
return Err(vm.new_value_error("Error Retrieving Value".to_string()));
191-
}
192-
193-
//the take above consumes the struct value
194-
//we add this back in with the takes into_inner method
195-
self.data.replace(handle.into_inner());
196-
}
197-
_ => {
198-
if let Err(_) = self.data.borrow_mut().read_to_end(&mut buffer) {
199-
return Err(vm.new_value_error("Error Retrieving Value".to_string()));
200-
}
201-
}
202-
};
227+
match self.buffer.borrow_mut().read(byte_count(bytes)) {
228+
Some(value) => Ok(vm.ctx.new_bytes(value)),
229+
None => Err(vm.new_value_error("Error Retrieving Value".to_string())),
230+
}
231+
}
203232

204-
Ok(vm.ctx.new_bytes(buffer))
233+
//skip to the jth position
234+
fn seek(self, offset: PyObjectRef, vm: &VirtualMachine) -> PyResult {
235+
let position = objint::get_value(&offset).to_u64().unwrap();
236+
match self.buffer.borrow_mut().seek(position) {
237+
Some(value) => Ok(vm.ctx.new_int(value)),
238+
None => Err(vm.new_value_error("Error Performing Operation".to_string())),
239+
}
205240
}
206241
}
207242

@@ -216,7 +251,7 @@ fn bytes_io_new(
216251
};
217252

218253
PyBytesIO {
219-
data: RefCell::new(Cursor::new(raw_bytes)),
254+
buffer: RefCell::new(BufferedIO::new(Cursor::new(raw_bytes))),
220255
}
221256
.into_ref_with_type(vm, cls)
222257
}
@@ -729,4 +764,25 @@ mod tests {
729764
);
730765
}
731766

767+
#[test]
768+
fn test_buffered_read() {
769+
let data = vec![1, 2, 3, 4];
770+
let bytes: i64 = -1;
771+
let mut buffered = BufferedIO {
772+
cursor: Cursor::new(data.clone()),
773+
};
774+
775+
assert_eq!(buffered.read(bytes).unwrap(), data);
776+
}
777+
778+
#[test]
779+
fn test_buffered_seek() {
780+
let data = vec![1, 2, 3, 4];
781+
let offset: u64 = 2;
782+
let mut buffered = BufferedIO {
783+
cursor: Cursor::new(data.clone()),
784+
};
785+
786+
assert_eq!(buffered.seek(offset.clone()).unwrap(), offset);
787+
}
732788
}

0 commit comments

Comments
 (0)