Skip to content

Commit 2d71f6d

Browse files
bytes and bytearray
1 parent e7fb116 commit 2d71f6d

File tree

5 files changed

+100
-58
lines changed

5 files changed

+100
-58
lines changed

vm/src/obj/objbytearray.rs

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,47 @@
11
//! Implementation of the python bytearray object.
22
33
use std::cell::RefCell;
4+
use std::ops::{Deref, DerefMut};
45

5-
use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol};
6+
use crate::pyobject::{
7+
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult,
8+
TypeProtocol,
9+
};
610

711
use super::objint;
812

9-
use super::objbytes::get_mut_value;
10-
use super::objbytes::get_value;
1113
use super::objtype;
1214
use crate::vm::VirtualMachine;
1315
use num_traits::ToPrimitive;
1416

17+
#[derive(Debug)]
18+
pub struct PyByteArray {
19+
// TODO: shouldn't be public
20+
pub value: RefCell<Vec<u8>>,
21+
}
22+
23+
impl PyByteArray {
24+
pub fn new(data: Vec<u8>) -> Self {
25+
PyByteArray {
26+
value: RefCell::new(data),
27+
}
28+
}
29+
}
30+
31+
impl PyObjectPayload2 for PyByteArray {
32+
fn required_type(ctx: &PyContext) -> PyObjectRef {
33+
ctx.bytearray_type()
34+
}
35+
}
36+
37+
pub fn get_value<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<u8>> + 'a {
38+
obj.payload::<PyByteArray>().unwrap().value.borrow()
39+
}
40+
41+
pub fn get_mut_value<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<u8>> + 'a {
42+
obj.payload::<PyByteArray>().unwrap().value.borrow_mut()
43+
}
44+
1545
// Binary data support
1646

1747
/// Fill bytearray class methods dictionary.
@@ -143,8 +173,8 @@ fn bytearray_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
143173
vec![]
144174
};
145175
Ok(PyObject::new(
146-
PyObjectPayload::Bytes {
147-
value: RefCell::new(value),
176+
PyObjectPayload::AnyRustValue {
177+
value: Box::new(PyByteArray::new(value)),
148178
},
149179
cls.clone(),
150180
))
@@ -290,13 +320,8 @@ fn bytearray_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
290320

291321
fn bytearray_clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
292322
arg_check!(vm, args, required = [(zelf, Some(vm.ctx.bytearray_type()))]);
293-
match zelf.payload {
294-
PyObjectPayload::Bytes { ref value } => {
295-
value.borrow_mut().clear();
296-
Ok(vm.get_none())
297-
}
298-
_ => panic!("Bytearray has incorrect payload."),
299-
}
323+
get_mut_value(zelf).clear();
324+
Ok(vm.get_none())
300325
}
301326

302327
fn bytearray_pop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {

vm/src/obj/objbytes.rs

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,41 @@
1-
use std::cell::{Cell, RefCell};
1+
use std::cell::Cell;
22
use std::hash::{Hash, Hasher};
33
use std::ops::Deref;
4-
use std::ops::DerefMut;
54

65
use super::objint;
76
use super::objtype;
87
use crate::pyobject::{
9-
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
8+
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult,
9+
TypeProtocol,
1010
};
1111
use crate::vm::VirtualMachine;
1212
use num_traits::ToPrimitive;
1313

14+
#[derive(Debug)]
15+
pub struct PyBytes {
16+
value: Vec<u8>,
17+
}
18+
19+
impl PyBytes {
20+
pub fn new(data: Vec<u8>) -> Self {
21+
PyBytes { value: data }
22+
}
23+
}
24+
25+
impl Deref for PyBytes {
26+
type Target = [u8];
27+
28+
fn deref(&self) -> &[u8] {
29+
&self.value
30+
}
31+
}
32+
33+
impl PyObjectPayload2 for PyBytes {
34+
fn required_type(ctx: &PyContext) -> PyObjectRef {
35+
ctx.bytes_type()
36+
}
37+
}
38+
1439
// Binary data support
1540

1641
// Fill bytes class methods:
@@ -71,8 +96,8 @@ fn bytes_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
7196
};
7297

7398
Ok(PyObject::new(
74-
PyObjectPayload::Bytes {
75-
value: RefCell::new(value),
99+
PyObjectPayload::AnyRustValue {
100+
value: Box::new(PyBytes::new(value)),
76101
},
77102
cls.clone(),
78103
))
@@ -170,19 +195,7 @@ fn bytes_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
170195
}
171196

172197
pub fn get_value<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<u8>> + 'a {
173-
if let PyObjectPayload::Bytes { ref value } = obj.payload {
174-
value.borrow()
175-
} else {
176-
panic!("Inner error getting bytearray {:?}", obj);
177-
}
178-
}
179-
180-
pub fn get_mut_value<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<u8>> + 'a {
181-
if let PyObjectPayload::Bytes { ref value } = obj.payload {
182-
value.borrow_mut()
183-
} else {
184-
panic!("Inner error getting bytearray {:?}", obj);
185-
}
198+
&obj.payload::<PyBytes>().unwrap().value
186199
}
187200

188201
fn bytes_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {

vm/src/obj/objiter.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use crate::pyobject::{
88
use crate::vm::VirtualMachine;
99

1010
use super::objbool;
11+
use super::objbytearray::PyByteArray;
12+
use super::objbytes::PyBytes;
1113
use super::objrange::PyRange;
1214
use super::objtype;
1315

@@ -137,6 +139,22 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
137139
} else {
138140
Err(new_stop_iteration(vm))
139141
}
142+
} else if let Some(bytes) = iterated_obj_ref.payload::<PyBytes>() {
143+
if position.get() < bytes.len() {
144+
let obj_ref = vm.ctx.new_int(bytes[position.get()]);
145+
position.set(position.get() + 1);
146+
Ok(obj_ref)
147+
} else {
148+
Err(new_stop_iteration(vm))
149+
}
150+
} else if let Some(bytes) = iterated_obj_ref.payload::<PyByteArray>() {
151+
if position.get() < bytes.value.borrow().len() {
152+
let obj_ref = vm.ctx.new_int(bytes.value.borrow()[position.get()]);
153+
position.set(position.get() + 1);
154+
Ok(obj_ref)
155+
} else {
156+
Err(new_stop_iteration(vm))
157+
}
140158
} else {
141159
match iterated_obj_ref.payload {
142160
PyObjectPayload::Sequence { ref elements } => {
@@ -148,16 +166,6 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
148166
Err(new_stop_iteration(vm))
149167
}
150168
}
151-
PyObjectPayload::Bytes { ref value } => {
152-
if position.get() < value.borrow().len() {
153-
let obj_ref = vm.ctx.new_int(value.borrow()[position.get()]);
154-
position.set(position.get() + 1);
155-
Ok(obj_ref)
156-
} else {
157-
Err(new_stop_iteration(vm))
158-
}
159-
}
160-
161169
_ => {
162170
panic!("NOT IMPL");
163171
}

vm/src/pyobject.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -483,17 +483,17 @@ impl PyContext {
483483

484484
pub fn new_bytes(&self, data: Vec<u8>) -> PyObjectRef {
485485
PyObject::new(
486-
PyObjectPayload::Bytes {
487-
value: RefCell::new(data),
486+
PyObjectPayload::AnyRustValue {
487+
value: Box::new(objbytes::PyBytes::new(data)),
488488
},
489489
self.bytes_type(),
490490
)
491491
}
492492

493493
pub fn new_bytearray(&self, data: Vec<u8>) -> PyObjectRef {
494494
PyObject::new(
495-
PyObjectPayload::Bytes {
496-
value: RefCell::new(data),
495+
PyObjectPayload::AnyRustValue {
496+
value: Box::new(objbytearray::PyByteArray::new(data)),
497497
},
498498
self.bytearray_type(),
499499
)
@@ -1253,9 +1253,6 @@ pub enum PyObjectPayload {
12531253
Complex {
12541254
value: Complex64,
12551255
},
1256-
Bytes {
1257-
value: RefCell<Vec<u8>>,
1258-
},
12591256
Sequence {
12601257
elements: RefCell<Vec<PyObjectRef>>,
12611258
},
@@ -1340,7 +1337,6 @@ impl fmt::Debug for PyObjectPayload {
13401337
match self {
13411338
PyObjectPayload::Integer { ref value } => write!(f, "int {}", value),
13421339
PyObjectPayload::Complex { ref value } => write!(f, "complex {}", value),
1343-
PyObjectPayload::Bytes { ref value } => write!(f, "bytes/bytearray {:?}", value),
13441340
PyObjectPayload::MemoryView { ref obj } => write!(f, "bytes/bytearray {:?}", obj),
13451341
PyObjectPayload::Sequence { .. } => write!(f, "list or tuple"),
13461342
PyObjectPayload::Dict { .. } => write!(f, "dict"),

vm/src/stdlib/io.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ use num_traits::ToPrimitive;
1515

1616
//custom imports
1717
use super::os;
18+
use crate::obj::objbytearray::PyByteArray;
1819
use crate::obj::objbytes;
1920
use crate::obj::objint;
2021
use crate::obj::objstr;
2122

2223
use crate::pyobject::{
23-
AttributeProtocol, BufferProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef,
24-
PyResult, TypeProtocol,
24+
AttributeProtocol, BufferProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol,
2525
};
2626

2727
use crate::import;
@@ -86,8 +86,8 @@ fn buffered_reader_read(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
8686
.map_err(|_| vm.new_value_error("IO Error".to_string()))?;
8787

8888
//Copy bytes from the buffer vector into the results vector
89-
if let PyObjectPayload::Bytes { ref value } = buffer.payload {
90-
result.extend(value.borrow().iter().cloned());
89+
if let Some(bytes) = buffer.payload::<PyByteArray>() {
90+
result.extend_from_slice(&bytes.value.borrow());
9191
};
9292

9393
let len = vm.get_method(buffer.clone(), &"__len__".to_string());
@@ -169,10 +169,10 @@ fn file_io_readinto(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
169169
let handle = os::rust_file(raw_fd);
170170

171171
let mut f = handle.take(length);
172-
if let PyObjectPayload::Bytes { ref value } = obj.payload {
172+
if let Some(bytes) = obj.payload::<PyByteArray>() {
173173
//TODO: Implement for MemoryView
174174

175-
let mut value_mut = value.borrow_mut();
175+
let mut value_mut = bytes.value.borrow_mut();
176176
value_mut.clear();
177177
match f.read_to_end(&mut value_mut) {
178178
Ok(_) => {}
@@ -200,9 +200,9 @@ fn file_io_write(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
200200
//to support windows - i.e. raw file_handles
201201
let mut handle = os::rust_file(raw_fd);
202202

203-
match obj.payload {
204-
PyObjectPayload::Bytes { ref value } => {
205-
let value_mut = value.borrow();
203+
match obj.payload::<PyByteArray>() {
204+
Some(bytes) => {
205+
let value_mut = bytes.value.borrow();
206206
match handle.write(&value_mut[..]) {
207207
Ok(len) => {
208208
//reset raw fd on the FileIO object
@@ -215,7 +215,7 @@ fn file_io_write(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
215215
Err(_) => Err(vm.new_value_error("Error Writing Bytes to Handle".to_string())),
216216
}
217217
}
218-
_ => Err(vm.new_value_error("Expected Bytes Object".to_string())),
218+
None => Err(vm.new_value_error("Expected Bytes Object".to_string())),
219219
}
220220
}
221221

0 commit comments

Comments
 (0)