From e7fb11621079b5f559c0673c9b8cf488bb214ff3 Mon Sep 17 00:00:00 2001 From: Joey Hain <jmhain@protonmail.com> Date: Thu, 28 Feb 2019 15:52:26 -0800 Subject: [PATCH 1/2] Convert more objects to `Any` payload --- vm/src/obj/objbool.rs | 5 +++- vm/src/obj/objfloat.rs | 34 ++++++++++++++++++----- vm/src/obj/objiter.rs | 62 +++++++++++++++++++++--------------------- vm/src/obj/objrange.rs | 42 ++++++++++++++++------------ vm/src/pyobject.rs | 17 +++++------- 5 files changed, 94 insertions(+), 66 deletions(-) diff --git a/vm/src/obj/objbool.rs b/vm/src/obj/objbool.rs index 3e0798ef50..84b048e3ae 100644 --- a/vm/src/obj/objbool.rs +++ b/vm/src/obj/objbool.rs @@ -1,3 +1,4 @@ +use super::objfloat::PyFloat; use super::objstr::PyString; use super::objtype; use crate::pyobject::{ @@ -16,9 +17,11 @@ pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObje if let Some(s) = obj.payload::<PyString>() { return Ok(!s.value.is_empty()); } + if let Some(value) = obj.payload::<PyFloat>() { + return Ok(*value != PyFloat::from(0.0)); + } let result = match obj.payload { PyObjectPayload::Integer { ref value } => !value.is_zero(), - PyObjectPayload::Float { value } => value != 0.0, PyObjectPayload::Sequence { ref elements } => !elements.borrow().is_empty(), PyObjectPayload::Dict { ref elements } => !elements.borrow().is_empty(), PyObjectPayload::None { .. } => false, diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index b59e893e3e..a2038bffbc 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -3,12 +3,30 @@ use super::objint; use super::objstr; use super::objtype; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, + TypeProtocol, }; use crate::vm::VirtualMachine; use num_bigint::ToBigInt; use num_traits::ToPrimitive; +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct PyFloat { + value: f64, +} + +impl PyObjectPayload2 for PyFloat { + fn required_type(ctx: &PyContext) -> PyObjectRef { + ctx.float_type() + } +} + +impl From<f64> for PyFloat { + fn from(value: f64) -> Self { + PyFloat { value } + } +} + fn float_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(float, Some(vm.ctx.float_type()))]); let v = get_value(float); @@ -50,16 +68,18 @@ fn float_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let type_name = objtype::get_type_name(&arg.typ()); return Err(vm.new_type_error(format!("can't convert {} to float", type_name))); }; - Ok(PyObject::new(PyObjectPayload::Float { value }, cls.clone())) + + Ok(PyObject::new( + PyObjectPayload::AnyRustValue { + value: Box::new(PyFloat { value }), + }, + cls.clone(), + )) } // Retrieve inner float value: pub fn get_value(obj: &PyObjectRef) -> f64 { - if let PyObjectPayload::Float { value } = &obj.payload { - *value - } else { - panic!("Inner error getting float: {}", obj); - } + obj.payload::<PyFloat>().unwrap().value } pub fn make_float(vm: &mut VirtualMachine, obj: &PyObjectRef) -> PyResult<f64> { diff --git a/vm/src/obj/objiter.rs b/vm/src/obj/objiter.rs index 2010da906d..9985553fb1 100644 --- a/vm/src/obj/objiter.rs +++ b/vm/src/obj/objiter.rs @@ -2,13 +2,14 @@ * Various types to support iteration. */ -use super::objbool; use crate::pyobject::{ PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, }; use crate::vm::VirtualMachine; -// use super::objstr; -use super::objtype; // Required for arg_check! to use isinstance + +use super::objbool; +use super::objrange::PyRange; +use super::objtype; /* * This helper function is called at multiple places. First, it is called @@ -129,38 +130,37 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { iterated_obj: ref iterated_obj_ref, } = iter.payload { - match iterated_obj_ref.payload { - PyObjectPayload::Sequence { ref elements } => { - if position.get() < elements.borrow().len() { - let obj_ref = elements.borrow()[position.get()].clone(); - position.set(position.get() + 1); - Ok(obj_ref) - } else { - Err(new_stop_iteration(vm)) - } + if let Some(range) = iterated_obj_ref.payload::<PyRange>() { + if let Some(int) = range.get(position.get()) { + position.set(position.get() + 1); + Ok(vm.ctx.new_int(int)) + } else { + Err(new_stop_iteration(vm)) } - - PyObjectPayload::Range { ref range } => { - if let Some(int) = range.get(position.get()) { - position.set(position.get() + 1); - Ok(vm.ctx.new_int(int)) - } else { - Err(new_stop_iteration(vm)) + } else { + match iterated_obj_ref.payload { + PyObjectPayload::Sequence { ref elements } => { + if position.get() < elements.borrow().len() { + let obj_ref = elements.borrow()[position.get()].clone(); + position.set(position.get() + 1); + Ok(obj_ref) + } else { + Err(new_stop_iteration(vm)) + } } - } - - PyObjectPayload::Bytes { ref value } => { - if position.get() < value.borrow().len() { - let obj_ref = vm.ctx.new_int(value.borrow()[position.get()]); - position.set(position.get() + 1); - Ok(obj_ref) - } else { - Err(new_stop_iteration(vm)) + PyObjectPayload::Bytes { ref value } => { + if position.get() < value.borrow().len() { + let obj_ref = vm.ctx.new_int(value.borrow()[position.get()]); + position.set(position.get() + 1); + Ok(obj_ref) + } else { + Err(new_stop_iteration(vm)) + } } - } - _ => { - panic!("NOT IMPL"); + _ => { + panic!("NOT IMPL"); + } } } } else { diff --git a/vm/src/obj/objrange.rs b/vm/src/obj/objrange.rs index daa5aab52f..41a4c69645 100644 --- a/vm/src/obj/objrange.rs +++ b/vm/src/obj/objrange.rs @@ -4,7 +4,8 @@ use std::ops::Mul; use super::objint; use super::objtype; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, + TypeProtocol, }; use crate::vm::VirtualMachine; use num_bigint::{BigInt, Sign}; @@ -12,7 +13,7 @@ use num_integer::Integer; use num_traits::{One, Signed, ToPrimitive, Zero}; #[derive(Debug, Clone)] -pub struct RangeType { +pub struct PyRange { // Unfortunately Rust's built in range type doesn't support things like indexing // or ranges where start > end so we need to roll our own. pub start: BigInt, @@ -20,7 +21,13 @@ pub struct RangeType { pub step: BigInt, } -impl RangeType { +impl PyObjectPayload2 for PyRange { + fn required_type(ctx: &PyContext) -> PyObjectRef { + ctx.range_type() + } +} + +impl PyRange { #[inline] pub fn try_len(&self) -> Option<usize> { match self.step.sign() { @@ -116,12 +123,12 @@ impl RangeType { }; match self.step.sign() { - Sign::Plus => RangeType { + Sign::Plus => PyRange { start, end: &self.start - 1, step: -&self.step, }, - Sign::Minus => RangeType { + Sign::Minus => PyRange { start, end: &self.start + 1, step: -&self.step, @@ -139,12 +146,8 @@ impl RangeType { } } -pub fn get_value(obj: &PyObjectRef) -> RangeType { - if let PyObjectPayload::Range { range } = &obj.payload { - range.clone() - } else { - panic!("Inner error getting range {:?}", obj); - } +pub fn get_value(obj: &PyObjectRef) -> PyRange { + obj.payload::<PyRange>().unwrap().clone() } pub fn init(context: &PyContext) { @@ -223,8 +226,8 @@ fn range_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Err(vm.new_value_error("range with 0 step size".to_string())) } else { Ok(PyObject::new( - PyObjectPayload::Range { - range: RangeType { start, end, step }, + PyObjectPayload::AnyRustValue { + value: Box::new(PyRange { start, end, step }), }, cls.clone(), )) @@ -251,7 +254,12 @@ fn range_reversed(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(PyObject::new( PyObjectPayload::Iterator { position: Cell::new(0), - iterated_obj: PyObject::new(PyObjectPayload::Range { range }, vm.ctx.range_type()), + iterated_obj: PyObject::new( + PyObjectPayload::AnyRustValue { + value: Box::new(range), + }, + vm.ctx.range_type(), + ), }, vm.ctx.iter_type(), )) @@ -316,12 +324,12 @@ fn range_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { }; Ok(PyObject::new( - PyObjectPayload::Range { - range: RangeType { + PyObjectPayload::AnyRustValue { + value: Box::new(PyRange { start: new_start, end: new_end, step: new_step, - }, + }), }, vm.ctx.range_type(), )) diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index c39aa71ae6..bfb33871e8 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -459,8 +459,13 @@ impl PyContext { ) } - pub fn new_float(&self, i: f64) -> PyObjectRef { - PyObject::new(PyObjectPayload::Float { value: i }, self.float_type()) + pub fn new_float(&self, value: f64) -> PyObjectRef { + PyObject::new( + PyObjectPayload::AnyRustValue { + value: Box::new(objfloat::PyFloat::from(value)), + }, + self.float_type(), + ) } pub fn new_complex(&self, i: Complex64) -> PyObjectRef { @@ -1245,9 +1250,6 @@ pub enum PyObjectPayload { Integer { value: BigInt, }, - Float { - value: f64, - }, Complex { value: Complex64, }, @@ -1284,9 +1286,6 @@ pub enum PyObjectPayload { stop: Option<BigInt>, step: Option<BigInt>, }, - Range { - range: objrange::RangeType, - }, MemoryView { obj: PyObjectRef, }, @@ -1340,7 +1339,6 @@ impl fmt::Debug for PyObjectPayload { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { PyObjectPayload::Integer { ref value } => write!(f, "int {}", value), - PyObjectPayload::Float { ref value } => write!(f, "float {}", value), PyObjectPayload::Complex { ref value } => write!(f, "complex {}", value), PyObjectPayload::Bytes { ref value } => write!(f, "bytes/bytearray {:?}", value), PyObjectPayload::MemoryView { ref obj } => write!(f, "bytes/bytearray {:?}", obj), @@ -1348,7 +1346,6 @@ impl fmt::Debug for PyObjectPayload { PyObjectPayload::Dict { .. } => write!(f, "dict"), PyObjectPayload::Set { .. } => write!(f, "set"), PyObjectPayload::WeakRef { .. } => write!(f, "weakref"), - PyObjectPayload::Range { .. } => write!(f, "range"), PyObjectPayload::Iterator { .. } => write!(f, "iterator"), PyObjectPayload::EnumerateIterator { .. } => write!(f, "enumerate"), PyObjectPayload::FilterIterator { .. } => write!(f, "filter"), From 2d71f6de288cd8dce359f16499c2df56e0f03bb5 Mon Sep 17 00:00:00 2001 From: Joey Hain <jmhain@protonmail.com> Date: Sun, 3 Mar 2019 20:01:07 -0800 Subject: [PATCH 2/2] bytes and bytearray --- vm/src/obj/objbytearray.rs | 49 ++++++++++++++++++++++++++++---------- vm/src/obj/objbytes.rs | 49 ++++++++++++++++++++++++-------------- vm/src/obj/objiter.rs | 28 ++++++++++++++-------- vm/src/pyobject.rs | 12 ++++------ vm/src/stdlib/io.rs | 20 ++++++++-------- 5 files changed, 100 insertions(+), 58 deletions(-) diff --git a/vm/src/obj/objbytearray.rs b/vm/src/obj/objbytearray.rs index 0cabf23fdc..7e03d34d3d 100644 --- a/vm/src/obj/objbytearray.rs +++ b/vm/src/obj/objbytearray.rs @@ -1,17 +1,47 @@ //! Implementation of the python bytearray object. use std::cell::RefCell; +use std::ops::{Deref, DerefMut}; -use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol}; +use crate::pyobject::{ + PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, + TypeProtocol, +}; use super::objint; -use super::objbytes::get_mut_value; -use super::objbytes::get_value; use super::objtype; use crate::vm::VirtualMachine; use num_traits::ToPrimitive; +#[derive(Debug)] +pub struct PyByteArray { + // TODO: shouldn't be public + pub value: RefCell<Vec<u8>>, +} + +impl PyByteArray { + pub fn new(data: Vec<u8>) -> Self { + PyByteArray { + value: RefCell::new(data), + } + } +} + +impl PyObjectPayload2 for PyByteArray { + fn required_type(ctx: &PyContext) -> PyObjectRef { + ctx.bytearray_type() + } +} + +pub fn get_value<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<u8>> + 'a { + obj.payload::<PyByteArray>().unwrap().value.borrow() +} + +pub fn get_mut_value<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<u8>> + 'a { + obj.payload::<PyByteArray>().unwrap().value.borrow_mut() +} + // Binary data support /// Fill bytearray class methods dictionary. @@ -143,8 +173,8 @@ fn bytearray_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { vec![] }; Ok(PyObject::new( - PyObjectPayload::Bytes { - value: RefCell::new(value), + PyObjectPayload::AnyRustValue { + value: Box::new(PyByteArray::new(value)), }, cls.clone(), )) @@ -290,13 +320,8 @@ fn bytearray_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn bytearray_clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(zelf, Some(vm.ctx.bytearray_type()))]); - match zelf.payload { - PyObjectPayload::Bytes { ref value } => { - value.borrow_mut().clear(); - Ok(vm.get_none()) - } - _ => panic!("Bytearray has incorrect payload."), - } + get_mut_value(zelf).clear(); + Ok(vm.get_none()) } fn bytearray_pop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { diff --git a/vm/src/obj/objbytes.rs b/vm/src/obj/objbytes.rs index 6ab2f72af2..d285b86e9a 100644 --- a/vm/src/obj/objbytes.rs +++ b/vm/src/obj/objbytes.rs @@ -1,16 +1,41 @@ -use std::cell::{Cell, RefCell}; +use std::cell::Cell; use std::hash::{Hash, Hasher}; use std::ops::Deref; -use std::ops::DerefMut; use super::objint; use super::objtype; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, + TypeProtocol, }; use crate::vm::VirtualMachine; use num_traits::ToPrimitive; +#[derive(Debug)] +pub struct PyBytes { + value: Vec<u8>, +} + +impl PyBytes { + pub fn new(data: Vec<u8>) -> Self { + PyBytes { value: data } + } +} + +impl Deref for PyBytes { + type Target = [u8]; + + fn deref(&self) -> &[u8] { + &self.value + } +} + +impl PyObjectPayload2 for PyBytes { + fn required_type(ctx: &PyContext) -> PyObjectRef { + ctx.bytes_type() + } +} + // Binary data support // Fill bytes class methods: @@ -71,8 +96,8 @@ fn bytes_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { }; Ok(PyObject::new( - PyObjectPayload::Bytes { - value: RefCell::new(value), + PyObjectPayload::AnyRustValue { + value: Box::new(PyBytes::new(value)), }, cls.clone(), )) @@ -170,19 +195,7 @@ fn bytes_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } pub fn get_value<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<u8>> + 'a { - if let PyObjectPayload::Bytes { ref value } = obj.payload { - value.borrow() - } else { - panic!("Inner error getting bytearray {:?}", obj); - } -} - -pub fn get_mut_value<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<u8>> + 'a { - if let PyObjectPayload::Bytes { ref value } = obj.payload { - value.borrow_mut() - } else { - panic!("Inner error getting bytearray {:?}", obj); - } + &obj.payload::<PyBytes>().unwrap().value } fn bytes_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { diff --git a/vm/src/obj/objiter.rs b/vm/src/obj/objiter.rs index 9985553fb1..049ea8be39 100644 --- a/vm/src/obj/objiter.rs +++ b/vm/src/obj/objiter.rs @@ -8,6 +8,8 @@ use crate::pyobject::{ use crate::vm::VirtualMachine; use super::objbool; +use super::objbytearray::PyByteArray; +use super::objbytes::PyBytes; use super::objrange::PyRange; use super::objtype; @@ -137,6 +139,22 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } else { Err(new_stop_iteration(vm)) } + } else if let Some(bytes) = iterated_obj_ref.payload::<PyBytes>() { + if position.get() < bytes.len() { + let obj_ref = vm.ctx.new_int(bytes[position.get()]); + position.set(position.get() + 1); + Ok(obj_ref) + } else { + Err(new_stop_iteration(vm)) + } + } else if let Some(bytes) = iterated_obj_ref.payload::<PyByteArray>() { + if position.get() < bytes.value.borrow().len() { + let obj_ref = vm.ctx.new_int(bytes.value.borrow()[position.get()]); + position.set(position.get() + 1); + Ok(obj_ref) + } else { + Err(new_stop_iteration(vm)) + } } else { match iterated_obj_ref.payload { PyObjectPayload::Sequence { ref elements } => { @@ -148,16 +166,6 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Err(new_stop_iteration(vm)) } } - PyObjectPayload::Bytes { ref value } => { - if position.get() < value.borrow().len() { - let obj_ref = vm.ctx.new_int(value.borrow()[position.get()]); - position.set(position.get() + 1); - Ok(obj_ref) - } else { - Err(new_stop_iteration(vm)) - } - } - _ => { panic!("NOT IMPL"); } diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index bfb33871e8..038eb1d0f8 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -483,8 +483,8 @@ impl PyContext { pub fn new_bytes(&self, data: Vec<u8>) -> PyObjectRef { PyObject::new( - PyObjectPayload::Bytes { - value: RefCell::new(data), + PyObjectPayload::AnyRustValue { + value: Box::new(objbytes::PyBytes::new(data)), }, self.bytes_type(), ) @@ -492,8 +492,8 @@ impl PyContext { pub fn new_bytearray(&self, data: Vec<u8>) -> PyObjectRef { PyObject::new( - PyObjectPayload::Bytes { - value: RefCell::new(data), + PyObjectPayload::AnyRustValue { + value: Box::new(objbytearray::PyByteArray::new(data)), }, self.bytearray_type(), ) @@ -1253,9 +1253,6 @@ pub enum PyObjectPayload { Complex { value: Complex64, }, - Bytes { - value: RefCell<Vec<u8>>, - }, Sequence { elements: RefCell<Vec<PyObjectRef>>, }, @@ -1340,7 +1337,6 @@ impl fmt::Debug for PyObjectPayload { match self { PyObjectPayload::Integer { ref value } => write!(f, "int {}", value), PyObjectPayload::Complex { ref value } => write!(f, "complex {}", value), - PyObjectPayload::Bytes { ref value } => write!(f, "bytes/bytearray {:?}", value), PyObjectPayload::MemoryView { ref obj } => write!(f, "bytes/bytearray {:?}", obj), PyObjectPayload::Sequence { .. } => write!(f, "list or tuple"), PyObjectPayload::Dict { .. } => write!(f, "dict"), diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index 077f907d89..95f6a10a9e 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -15,13 +15,13 @@ use num_traits::ToPrimitive; //custom imports use super::os; +use crate::obj::objbytearray::PyByteArray; use crate::obj::objbytes; use crate::obj::objint; use crate::obj::objstr; use crate::pyobject::{ - AttributeProtocol, BufferProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, - PyResult, TypeProtocol, + AttributeProtocol, BufferProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol, }; use crate::import; @@ -86,8 +86,8 @@ fn buffered_reader_read(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { .map_err(|_| vm.new_value_error("IO Error".to_string()))?; //Copy bytes from the buffer vector into the results vector - if let PyObjectPayload::Bytes { ref value } = buffer.payload { - result.extend(value.borrow().iter().cloned()); + if let Some(bytes) = buffer.payload::<PyByteArray>() { + result.extend_from_slice(&bytes.value.borrow()); }; let len = vm.get_method(buffer.clone(), &"__len__".to_string()); @@ -169,10 +169,10 @@ fn file_io_readinto(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let handle = os::rust_file(raw_fd); let mut f = handle.take(length); - if let PyObjectPayload::Bytes { ref value } = obj.payload { + if let Some(bytes) = obj.payload::<PyByteArray>() { //TODO: Implement for MemoryView - let mut value_mut = value.borrow_mut(); + let mut value_mut = bytes.value.borrow_mut(); value_mut.clear(); match f.read_to_end(&mut value_mut) { Ok(_) => {} @@ -200,9 +200,9 @@ fn file_io_write(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { //to support windows - i.e. raw file_handles let mut handle = os::rust_file(raw_fd); - match obj.payload { - PyObjectPayload::Bytes { ref value } => { - let value_mut = value.borrow(); + match obj.payload::<PyByteArray>() { + Some(bytes) => { + let value_mut = bytes.value.borrow(); match handle.write(&value_mut[..]) { Ok(len) => { //reset raw fd on the FileIO object @@ -215,7 +215,7 @@ fn file_io_write(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Err(_) => Err(vm.new_value_error("Error Writing Bytes to Handle".to_string())), } } - _ => Err(vm.new_value_error("Expected Bytes Object".to_string())), + None => Err(vm.new_value_error("Expected Bytes Object".to_string())), } }