From 54cfb71d7460f5038bf109bf223348e70752a15c Mon Sep 17 00:00:00 2001 From: Noah <33094578+coolreader18@users.noreply.github.com> Date: Thu, 19 Sep 2019 15:58:15 +0000 Subject: [PATCH 1/3] Add a lazily calculated hash field to PyString --- vm/src/builtins.rs | 9 +++------ vm/src/obj/objstr.rs | 26 +++++++++++++++++++------- vm/src/pyobject.rs | 2 +- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 16a701359..59a216b7b 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -250,12 +250,9 @@ fn builtin_format( format_spec: OptionalArg, vm: &VirtualMachine, ) -> PyResult { - let format_spec = format_spec.into_option().unwrap_or_else(|| { - PyString { - value: "".to_string(), - } - .into_ref(vm) - }); + let format_spec = format_spec + .into_option() + .unwrap_or_else(|| PyString::from("").into_ref(vm)); vm.call_method(&value, "__format__", vec![format_spec.into_object()])? .downcast() diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index c7a3fcbb0..f9e0d35d8 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -54,6 +54,7 @@ use unicode_categories::UnicodeCategories; pub struct PyString { // TODO: shouldn't be public pub value: String, + hash: Cell>, } impl PyString { @@ -64,8 +65,15 @@ impl PyString { impl From<&str> for PyString { fn from(s: &str) -> PyString { + s.to_string().into() + } +} + +impl From for PyString { + fn from(s: String) -> PyString { PyString { - value: s.to_string(), + value: s, + hash: Cell::default(), } } } @@ -80,16 +88,13 @@ impl fmt::Display for PyString { impl TryIntoRef for String { fn try_into_ref(self, vm: &VirtualMachine) -> PyResult> { - Ok(PyString { value: self }.into_ref(vm)) + Ok(PyString::from(self).into_ref(vm)) } } impl TryIntoRef for &str { fn try_into_ref(self, vm: &VirtualMachine) -> PyResult> { - Ok(PyString { - value: self.to_string(), - } - .into_ref(vm)) + Ok(PyString::from(self).into_ref(vm)) } } @@ -259,7 +264,14 @@ impl PyString { #[pymethod(name = "__hash__")] fn hash(&self, _vm: &VirtualMachine) -> pyhash::PyHash { - pyhash::hash_value(&self.value) + match self.hash.get() { + Some(hash) => hash, + None => { + let hash = pyhash::hash_value(&self.value); + self.hash.set(Some(hash)); + hash + } + } } #[pymethod(name = "__len__")] diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 3d9297dd4..56a9ad112 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -380,7 +380,7 @@ impl PyContext { } pub fn new_str(&self, s: String) -> PyObjectRef { - PyObject::new(objstr::PyString { value: s }, self.str_type(), None) + PyObject::new(objstr::PyString::from(s), self.str_type(), None) } pub fn new_bytes(&self, data: Vec) -> PyObjectRef { From 0def37d78e85bb1ae2ab60c0785552a8ac9933f5 Mon Sep 17 00:00:00 2001 From: Noah <33094578+coolreader18@users.noreply.github.com> Date: Thu, 19 Sep 2019 16:32:23 +0000 Subject: [PATCH 2/3] Make PyString.value private --- vm/src/builtins.rs | 20 ++++++++-------- vm/src/dictdatatype.rs | 4 ++-- vm/src/exceptions.rs | 43 +++++++++++++++++----------------- vm/src/frame.rs | 2 +- vm/src/obj/objbool.rs | 2 +- vm/src/obj/objbyteinner.rs | 2 +- vm/src/obj/objdict.rs | 2 +- vm/src/obj/objfloat.rs | 2 +- vm/src/obj/objint.rs | 29 +++++++++++------------ vm/src/obj/objlist.rs | 12 +++++----- vm/src/obj/objnone.rs | 6 ++--- vm/src/obj/objobject.rs | 14 +++++------ vm/src/obj/objset.rs | 4 ++-- vm/src/obj/objstr.rs | 4 ++-- vm/src/obj/objtuple.rs | 4 ++-- vm/src/obj/objtype.rs | 6 ++--- vm/src/stdlib/ast.rs | 2 +- vm/src/stdlib/hashlib.rs | 2 +- vm/src/stdlib/io.rs | 10 ++++---- vm/src/stdlib/os.rs | 28 +++++++++++----------- vm/src/stdlib/pwd.rs | 2 +- vm/src/stdlib/re.rs | 10 ++++---- vm/src/stdlib/socket.rs | 6 ++--- vm/src/stdlib/symtable.rs | 4 ++-- vm/src/stdlib/time_module.rs | 10 ++++---- vm/src/stdlib/unicodedata.rs | 10 ++++---- vm/src/vm.rs | 6 ++--- wasm/lib/src/browser_module.rs | 6 ++--- 28 files changed, 125 insertions(+), 127 deletions(-) diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 59a216b7b..b1a2edbba 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -60,7 +60,7 @@ fn builtin_any(iterable: PyIterable, vm: &VirtualMachine) -> PyResul fn builtin_ascii(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { let repr = vm.to_repr(&obj)?; - let ascii = to_ascii(&repr.value); + let ascii = to_ascii(repr.as_str()); Ok(ascii) } @@ -126,9 +126,9 @@ struct CompileArgs { #[cfg(feature = "rustpython-compiler")] fn builtin_compile(args: CompileArgs, vm: &VirtualMachine) -> PyResult { // TODO: compile::compile should probably get bytes - let source = match args.source { - Either::A(string) => string.value.to_string(), - Either::B(bytes) => str::from_utf8(&bytes).unwrap().to_string(), + let source = match &args.source { + Either::A(string) => string.as_str(), + Either::B(bytes) => str::from_utf8(bytes).unwrap(), }; let mode = args @@ -137,7 +137,7 @@ fn builtin_compile(args: CompileArgs, vm: &VirtualMachine) -> PyResult() .map_err(|err| vm.new_value_error(err.to_string()))?; - vm.compile(&source, mode, args.filename.value.to_string()) + vm.compile(source, mode, args.filename.as_str().to_string()) .map_err(|err| vm.new_syntax_error(&err)) } @@ -595,8 +595,8 @@ impl Printer for &'_ PyObjectRef { impl Printer for std::io::StdoutLock<'_> { fn write(&mut self, vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<()> { - let s = &vm.to_str(&obj)?.value; - write!(self, "{}", s).unwrap(); + let s = vm.to_str(&obj)?; + write!(self, "{}", s.as_str()).unwrap(); Ok(()) } @@ -628,7 +628,7 @@ pub fn builtin_print(objects: Args, options: PrintOptions, vm: &VirtualMachine) let sep = options .sep .as_ref() - .map_or(" ", |sep| &sep.value) + .map_or(" ", |sep| sep.as_str()) .into_pyobject(vm) .unwrap(); @@ -646,7 +646,7 @@ pub fn builtin_print(objects: Args, options: PrintOptions, vm: &VirtualMachine) let end = options .end .as_ref() - .map_or("\n", |end| &end.value) + .map_or("\n", |end| end.as_str()) .into_pyobject(vm) .unwrap(); printer.write(vm, end)?; @@ -899,7 +899,7 @@ pub fn builtin_build_class_( mut kwargs: KwArgs, vm: &VirtualMachine, ) -> PyResult { - let name = qualified_name.value.split('.').next_back().unwrap(); + let name = qualified_name.as_str().split('.').next_back().unwrap(); let name_obj = vm.new_str(name.to_string()); let mut metaclass = if let Some(metaclass) = kwargs.pop_kwarg("metaclass") { diff --git a/vm/src/dictdatatype.rs b/vm/src/dictdatatype.rs index 5f086c2dc..222e364a1 100644 --- a/vm/src/dictdatatype.rs +++ b/vm/src/dictdatatype.rs @@ -330,7 +330,7 @@ impl DictKey for &str { fn do_eq(self, vm: &VirtualMachine, other_key: &PyObjectRef) -> PyResult { if let Some(py_str_value) = other_key.payload::() { - Ok(py_str_value.value == self) + Ok(py_str_value.as_str() == self) } else { // Fall back to PyString implementation. let s = vm.new_str(self.to_string()); @@ -357,7 +357,7 @@ impl DictKey for &String { fn do_eq(self, vm: &VirtualMachine, other_key: &PyObjectRef) -> PyResult { if let Some(py_str_value) = other_key.payload::() { - Ok(&py_str_value.value == self) + Ok(py_str_value.as_str() == self) } else { // Fall back to PyString implementation. let s = vm.new_str(self.to_string()); diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index 38b6e501e..8d15b6ede 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -44,7 +44,7 @@ pub fn print_exception(vm: &VirtualMachine, exc: &PyObjectRef) { print_exception_inner(vm, exc) } -fn print_source_line(filename: String, lineno: usize) { +fn print_source_line(filename: &str, lineno: usize) { // TODO: use io.open() method instead, when available, according to https://github.com/python/cpython/blob/master/Python/traceback.c#L393 // TODO: support different encodings let file = match File::open(filename) { @@ -70,22 +70,26 @@ fn print_source_line(filename: String, lineno: usize) { fn print_traceback_entry(vm: &VirtualMachine, tb_entry: &PyObjectRef) { if objtype::isinstance(&tb_entry, &vm.ctx.tuple_type()) { let location_attrs = objsequence::get_elements_tuple(&tb_entry); - let filename = if let Ok(x) = vm.to_str(&location_attrs[0]) { - x.value.clone() + + let filename = vm.to_str(&location_attrs[0]); + let filename = if let Ok(ref x) = filename { + x.as_str() } else { - "".to_string() + "" }; - let lineno = if let Ok(x) = vm.to_str(&location_attrs[1]) { - x.value.clone() + let lineno = vm.to_str(&location_attrs[1]); + let lineno = if let Ok(ref x) = lineno { + x.as_str() } else { - "".to_string() + "" }; - let obj_name = if let Ok(x) = vm.to_str(&location_attrs[2]) { - x.value.clone() + let obj_name = vm.to_str(&location_attrs[2]); + let obj_name = if let Ok(ref x) = obj_name { + x.as_str() } else { - "".to_string() + "" }; println!( @@ -149,17 +153,14 @@ fn exception_args_as_string( }; vec![args0_repr] } - _ => { - let mut args_vec = Vec::with_capacity(varargs.elements.len()); - for vararg in &varargs.elements { - let arg_repr = match vm.to_repr(vararg) { - Ok(arg_repr) => arg_repr.value.clone(), - Err(_) => "".to_string(), - }; - args_vec.push(arg_repr); - } - args_vec - } + _ => varargs + .elements + .iter() + .map(|vararg| match vm.to_repr(vararg) { + Ok(arg_repr) => arg_repr.as_str().to_string(), + Err(_) => "".to_string(), + }) + .collect(), } } diff --git a/vm/src/frame.rs b/vm/src/frame.rs index ec5bcf658..844b0849f 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -1058,7 +1058,7 @@ impl Frame { .ctx .new_function(code_obj, scope, defaults, kw_only_defaults); - let name = qualified_name.value.split('.').next_back().unwrap(); + let name = qualified_name.as_str().split('.').next_back().unwrap(); vm.set_attr(&func_obj, "__name__", vm.new_str(name.to_string()))?; vm.set_attr(&func_obj, "__qualname__", qualified_name)?; let module = self diff --git a/vm/src/obj/objbool.rs b/vm/src/obj/objbool.rs index 4bd83a6f4..039b4688d 100644 --- a/vm/src/obj/objbool.rs +++ b/vm/src/obj/objbool.rs @@ -121,7 +121,7 @@ fn bool_format( format_spec: PyStringRef, vm: &VirtualMachine, ) -> PyResult { - if format_spec.value.is_empty() { + if format_spec.as_str().is_empty() { vm.to_str(&obj) } else { Err(vm.new_type_error("unsupported format string passed to bool.__format__".to_string())) diff --git a/vm/src/obj/objbyteinner.rs b/vm/src/obj/objbyteinner.rs index 2fa5920df..b6b73bc84 100644 --- a/vm/src/obj/objbyteinner.rs +++ b/vm/src/obj/objbyteinner.rs @@ -99,7 +99,7 @@ impl ByteInnerNewOptions { if let OptionalArg::Present(enc) = self.encoding { if let OptionalArg::Present(eval) = self.val_option { if let Ok(input) = eval.downcast::() { - let inner = PyByteInner::from_string(&input.value, enc.as_str(), vm)?; + let inner = PyByteInner::from_string(input.as_str(), enc.as_str(), vm)?; Ok(inner) } else { Err(vm.new_type_error("encoding without a string argument".to_string())) diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index f645902d6..4576d71ed 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -156,7 +156,7 @@ impl PyDictRef { for (key, value) in self { let key_repr = vm.to_repr(&key)?; let value_repr = vm.to_repr(&value)?; - str_parts.push(format!("{}: {}", key_repr.value, value_repr.value)); + str_parts.push(format!("{}: {}", key_repr.as_str(), value_repr.as_str())); } format!("{{{}}}", str_parts.join(", ")) diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index 8945840bb..6afc8a2b3 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -560,7 +560,7 @@ impl PyFloat { #[pymethod] fn fromhex(repr: PyStringRef, vm: &VirtualMachine) -> PyResult { - hexf_parse::parse_hexf64(&repr.value, false).or_else(|_| match repr.value.as_ref() { + hexf_parse::parse_hexf64(repr.as_str(), false).or_else(|_| match repr.as_str() { "nan" => Ok(std::f64::NAN), "inf" => Ok(std::f64::INFINITY), "-inf" => Ok(std::f64::NEG_INFINITY), diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index 7a478fae9..fd14f01c5 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -554,7 +554,7 @@ impl PyInt { #[pymethod(name = "__format__")] fn format(&self, spec: PyStringRef, vm: &VirtualMachine) -> PyResult { - let format_spec = FormatSpec::parse(&spec.value); + let format_spec = FormatSpec::parse(spec.as_str()); match format_spec.format_int(&self.value) { Ok(string) => Ok(string), Err(err) => Err(vm.new_value_error(err.to_string())), @@ -594,22 +594,21 @@ impl PyInt { ); } } - let x; - if byteorder.value == "big" { - x = match signed { + let x = match byteorder.as_str() { + "big" => match signed { true => BigInt::from_signed_bytes_be(&bytes.elements), false => BigInt::from_bytes_be(Sign::Plus, &bytes.elements), - } - } else if byteorder.value == "little" { - x = match signed { + }, + "little" => match signed { true => BigInt::from_signed_bytes_le(&bytes.elements), false => BigInt::from_bytes_le(Sign::Plus, &bytes.elements), + }, + _ => { + return Err( + vm.new_value_error("byteorder must be either 'little' or 'big'".to_string()) + ) } - } else { - return Err( - vm.new_value_error("byteorder must be either 'little' or 'big'".to_string()) - ); - } + }; Ok(x) } #[pymethod] @@ -642,7 +641,7 @@ impl PyInt { return Err(vm.new_value_error("length parameter is illegal".to_string())); } - let mut origin_bytes = match byteorder.value.as_str() { + let mut origin_bytes = match byteorder.as_str() { "big" => match signed { true => value.to_signed_bytes_be(), false => value.to_bytes_be().1, @@ -667,7 +666,7 @@ impl PyInt { _ => vec![0u8; byte_len - origin_len], }; let mut bytes = vec![]; - match byteorder.value.as_str() { + match byteorder.as_str() { "big" => { bytes = append_bytes; bytes.append(&mut origin_bytes); @@ -746,7 +745,7 @@ pub fn to_int(vm: &VirtualMachine, obj: &PyObjectRef, base: u32) -> PyResult { - let s = string.value.as_str().trim(); + let s = string.as_str().trim(); str_to_int(vm, s, base) }, bytes @ PyBytes => { diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index 1f3b1c953..caf174e46 100644 --- a/vm/src/obj/objlist.rs +++ b/vm/src/obj/objlist.rs @@ -388,10 +388,10 @@ impl PyListRef { fn repr(self, vm: &VirtualMachine) -> PyResult { let s = if let Some(_guard) = ReprGuard::enter(self.as_object()) { - let mut str_parts = vec![]; + let mut str_parts = Vec::with_capacity(self.elements.borrow().len()); for elem in self.elements.borrow().iter() { let s = vm.to_repr(elem)?; - str_parts.push(s.value.clone()); + str_parts.push(s.as_str().to_string()); } format!("[{}]", str_parts.join(", ")) } else { @@ -462,8 +462,8 @@ impl PyListRef { return Ok(index); } } - let needle_str = &vm.to_str(&needle)?.value; - Err(vm.new_value_error(format!("'{}' is not in list", needle_str))) + let needle_str = vm.to_str(&needle)?; + Err(vm.new_value_error(format!("'{}' is not in list", needle_str.as_str()))) } fn pop(self, i: OptionalArg, vm: &VirtualMachine) -> PyResult { @@ -499,8 +499,8 @@ impl PyListRef { self.elements.borrow_mut().remove(index); Ok(()) } else { - let needle_str = &vm.to_str(&needle)?.value; - Err(vm.new_value_error(format!("'{}' is not in list", needle_str))) + let needle_str = vm.to_str(&needle)?; + Err(vm.new_value_error(format!("'{}' is not in list", needle_str.as_str()))) } } diff --git a/vm/src/obj/objnone.rs b/vm/src/obj/objnone.rs index cf1b4d3a5..3ccb6581f 100644 --- a/vm/src/obj/objnone.rs +++ b/vm/src/obj/objnone.rs @@ -68,7 +68,7 @@ impl PyNoneRef { } } - if let Some(attr) = class_get_attr(&cls, &name.value) { + if let Some(attr) = class_get_attr(&cls, name.as_str()) { let attr_class = attr.class(); if class_has_attr(&attr_class, "__set__") { if let Some(get_func) = class_get_attr(&attr_class, "__get__") { @@ -84,10 +84,10 @@ impl PyNoneRef { } // None has no attributes and cannot have attributes set on it. - // if let Some(obj_attr) = self.as_object().get_attr(&name.value) { + // if let Some(obj_attr) = self.as_object().get_attr(name.as_str()) { // Ok(obj_attr) // } else - if let Some(attr) = class_get_attr(&cls, &name.value) { + if let Some(attr) = class_get_attr(&cls, name.as_str()) { let attr_class = attr.class(); if let Some(get_func) = class_get_attr(&attr_class, "__get__") { call_descriptor(attr, get_func, self.into_object(), cls.into_object(), vm) diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index 70e9b5fd3..dbd5498c4 100644 --- a/vm/src/obj/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -69,7 +69,7 @@ fn object_setattr( vm_trace!("object.__setattr__({:?}, {}, {:?})", obj, attr_name, value); let cls = obj.class(); - if let Some(attr) = objtype::class_get_attr(&cls, &attr_name.value) { + if let Some(attr) = objtype::class_get_attr(&cls, attr_name.as_str()) { if let Some(descriptor) = objtype::class_get_attr(&attr.class(), "__set__") { return vm .invoke(&descriptor, vec![attr, obj.clone(), value]) @@ -78,13 +78,13 @@ fn object_setattr( } if let Some(ref dict) = obj.clone().dict { - dict.set_item(&attr_name.value, value, vm)?; + dict.set_item(attr_name.as_str(), value, vm)?; Ok(()) } else { Err(vm.new_attribute_error(format!( "'{}' object has no attribute '{}'", obj.class().name, - &attr_name.value + attr_name.as_str() ))) } } @@ -92,20 +92,20 @@ fn object_setattr( fn object_delattr(obj: PyObjectRef, attr_name: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { let cls = obj.class(); - if let Some(attr) = objtype::class_get_attr(&cls, &attr_name.value) { + if let Some(attr) = objtype::class_get_attr(&cls, attr_name.as_str()) { if let Some(descriptor) = objtype::class_get_attr(&attr.class(), "__delete__") { return vm.invoke(&descriptor, vec![attr, obj.clone()]).map(|_| ()); } } if let Some(ref dict) = obj.dict { - dict.del_item(&attr_name.value, vm)?; + dict.del_item(attr_name.as_str(), vm)?; Ok(()) } else { Err(vm.new_attribute_error(format!( "'{}' object has no attribute '{}'", obj.class().name, - &attr_name.value + attr_name.as_str() ))) } } @@ -145,7 +145,7 @@ fn object_format( format_spec: PyStringRef, vm: &VirtualMachine, ) -> PyResult { - if format_spec.value.is_empty() { + if format_spec.as_str().is_empty() { vm.to_str(&obj) } else { Err(vm.new_type_error("unsupported format string passed to object.__format__".to_string())) diff --git a/vm/src/obj/objset.rs b/vm/src/obj/objset.rs index dc4a3ca95..243b0dfdd 100644 --- a/vm/src/obj/objset.rs +++ b/vm/src/obj/objset.rs @@ -240,10 +240,10 @@ impl PySetInner { } fn repr(&self, vm: &VirtualMachine) -> PyResult { - let mut str_parts = vec![]; + let mut str_parts = Vec::with_capacity(self.content.len()); for key in self.content.keys() { let part = vm.to_repr(&key)?; - str_parts.push(part.value.clone()); + str_parts.push(part.as_str().to_owned()); } Ok(format!("{{{}}}", str_parts.join(", "))) diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index f9e0d35d8..4c42de58c 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -52,12 +52,12 @@ use unicode_categories::UnicodeCategories; #[pyclass(name = "str")] #[derive(Clone, Debug)] pub struct PyString { - // TODO: shouldn't be public - pub value: String, + value: String, hash: Cell>, } impl PyString { + #[inline] pub fn as_str(&self) -> &str { &self.value } diff --git a/vm/src/obj/objtuple.rs b/vm/src/obj/objtuple.rs index 459f0e9bc..9ce483fc0 100644 --- a/vm/src/obj/objtuple.rs +++ b/vm/src/obj/objtuple.rs @@ -169,10 +169,10 @@ impl PyTupleRef { fn repr(self, vm: &VirtualMachine) -> PyResult { let s = if let Some(_guard) = ReprGuard::enter(self.as_object()) { - let mut str_parts = vec![]; + let mut str_parts = Vec::with_capacity(self.elements.len()); for elem in self.elements.iter() { let s = vm.to_repr(elem)?; - str_parts.push(s.value.clone()); + str_parts.push(s.as_str().to_owned()); } if str_parts.len() == 1 { diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index b88fccb00..48e50bcc9 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -130,7 +130,7 @@ impl PyClassRef { } fn getattribute(self, name_ref: PyStringRef, vm: &VirtualMachine) -> PyResult { - let name = &name_ref.value; + let name = name_ref.as_str(); vm_trace!("type.__getattribute__({:?}, {:?})", self, name); let mcl = self.class(); @@ -171,7 +171,7 @@ impl PyClassRef { value: PyObjectRef, vm: &VirtualMachine, ) -> PyResult<()> { - if let Some(attr) = class_get_attr(&self.class(), &attr_name.value) { + if let Some(attr) = class_get_attr(&self.class(), attr_name.as_str()) { if let Some(ref descriptor) = class_get_attr(&attr.class(), "__set__") { vm.invoke(descriptor, vec![attr, self.into_object(), value])?; return Ok(()); @@ -281,7 +281,7 @@ pub fn type_new_class( ) -> PyResult { let mut bases: Vec = bases.iter(vm)?.collect::, _>>()?; bases.push(vm.ctx.object()); - new(typ.clone(), &name.value, bases, dict.to_attributes()) + new(typ.clone(), name.as_str(), bases, dict.to_attributes()) } pub fn type_call(class: PyClassRef, args: Args, kwargs: KwArgs, vm: &VirtualMachine) -> PyResult { diff --git a/vm/src/stdlib/ast.rs b/vm/src/stdlib/ast.rs index a9d7b44c2..cea1674c4 100644 --- a/vm/src/stdlib/ast.rs +++ b/vm/src/stdlib/ast.rs @@ -635,7 +635,7 @@ fn string_to_ast(vm: &VirtualMachine, string: &ast::StringGroup) -> PyResult PyResult { - let internal_ast = parser::parse_program(&source.value) + let internal_ast = parser::parse_program(source.as_str()) .map_err(|err| vm.new_value_error(format!("{}", err)))?; // source.clone(); program_to_ast(&vm, &internal_ast) diff --git a/vm/src/stdlib/hashlib.rs b/vm/src/stdlib/hashlib.rs index ca74f35f8..396d0ba49 100644 --- a/vm/src/stdlib/hashlib.rs +++ b/vm/src/stdlib/hashlib.rs @@ -86,7 +86,7 @@ fn hashlib_new( data: OptionalArg, vm: &VirtualMachine, ) -> PyResult { - let hasher = match name.value.as_ref() { + let hasher = match name.as_str() { "md5" => Ok(PyHasher::new("md5", HashWrapper::md5())), "sha1" => Ok(PyHasher::new("sha1", HashWrapper::sha1())), "sha224" => Ok(PyHasher::new("sha224", HashWrapper::sha224())), diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index 7d4151dbf..74974614a 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -38,10 +38,10 @@ impl BufferedIO { BufferedIO { cursor } } - fn write(&mut self, data: Vec) -> Option { + fn write(&mut self, data: &[u8]) -> Option { let length = data.len(); - match self.cursor.write_all(&data) { + match self.cursor.write_all(data) { Ok(_) => Some(length as u64), Err(_) => None, } @@ -102,9 +102,9 @@ impl PyValue for PyStringIO { impl PyStringIORef { //write string to underlying vector fn write(self, data: PyStringRef, vm: &VirtualMachine) -> PyResult { - let bytes = &data.value.clone().into_bytes(); + let bytes = data.as_str().as_bytes(); - match self.buffer.borrow_mut().write(bytes.to_vec()) { + match self.buffer.borrow_mut().write(bytes) { Some(value) => Ok(vm.ctx.new_int(value)), None => Err(vm.new_type_error("Error Writing String".to_string())), } @@ -180,7 +180,7 @@ impl PyBytesIORef { fn write(self, data: objbytes::PyBytesRef, vm: &VirtualMachine) -> PyResult { let bytes = data.get_value(); - match self.buffer.borrow_mut().write(bytes.to_vec()) { + match self.buffer.borrow_mut().write(bytes) { Some(value) => Ok(vm.ctx.new_int(value)), None => Err(vm.new_type_error("Error Writing Bytes".to_string())), } diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 69c177dc4..8c3e53bd0 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -377,25 +377,25 @@ fn os_write(fd: PyIntRef, data: PyBytesRef, vm: &VirtualMachine) -> PyResult { fn os_remove(path: PyStringRef, dir_fd: DirFd, vm: &VirtualMachine) -> PyResult<()> { let path = make_path(vm, path, &dir_fd); - fs::remove_file(&path.value).map_err(|err| convert_io_error(vm, err)) + fs::remove_file(path.as_str()).map_err(|err| convert_io_error(vm, err)) } fn os_mkdir(path: PyStringRef, dir_fd: DirFd, vm: &VirtualMachine) -> PyResult<()> { let path = make_path(vm, path, &dir_fd); - fs::create_dir(&path.value).map_err(|err| convert_io_error(vm, err)) + fs::create_dir(path.as_str()).map_err(|err| convert_io_error(vm, err)) } fn os_mkdirs(path: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { - fs::create_dir_all(&path.value).map_err(|err| convert_io_error(vm, err)) + fs::create_dir_all(path.as_str()).map_err(|err| convert_io_error(vm, err)) } fn os_rmdir(path: PyStringRef, dir_fd: DirFd, vm: &VirtualMachine) -> PyResult<()> { let path = make_path(vm, path, &dir_fd); - fs::remove_dir(&path.value).map_err(|err| convert_io_error(vm, err)) + fs::remove_dir(path.as_str()).map_err(|err| convert_io_error(vm, err)) } fn os_listdir(path: PyStringRef, vm: &VirtualMachine) -> PyResult { - match fs::read_dir(&path.value) { + match fs::read_dir(path.as_str()) { Ok(iter) => { let res: PyResult> = iter .map(|entry| match entry { @@ -583,7 +583,7 @@ impl ScandirIterator { } fn os_scandir(path: PyStringRef, vm: &VirtualMachine) -> PyResult { - match fs::read_dir(&path.value) { + match fs::read_dir(path.as_str()) { Ok(iter) => Ok(ScandirIterator { entries: RefCell::new(iter), } @@ -699,7 +699,7 @@ macro_rules! os_unix_stat_inner { }) } - get_stats(&$path.value, $follow_symlinks.follow_symlinks) + get_stats($path.as_str(), $follow_symlinks.follow_symlinks) .map_err(|err| convert_io_error($vm, err)) }}; } @@ -802,7 +802,7 @@ fn os_stat( }) } - get_stats(&path.value, follow_symlinks.follow_symlinks) + get_stats(path.as_str(), follow_symlinks.follow_symlinks) .map_err(|s| vm.new_os_error(s.to_string())) } @@ -842,7 +842,7 @@ fn os_symlink( ) -> PyResult<()> { use std::os::unix::fs as unix_fs; let dst = make_path(vm, dst, &dir_fd); - unix_fs::symlink(&src.value, &dst.value).map_err(|err| convert_io_error(vm, err)) + unix_fs::symlink(src.as_str(), dst.as_str()).map_err(|err| convert_io_error(vm, err)) } #[cfg(windows)] @@ -888,7 +888,7 @@ fn os_getcwd(vm: &VirtualMachine) -> PyResult { } fn os_chdir(path: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { - env::set_current_dir(&path.value).map_err(|err| convert_io_error(vm, err)) + env::set_current_dir(path.as_str()).map_err(|err| convert_io_error(vm, err)) } #[cfg(unix)] @@ -902,14 +902,14 @@ fn os_chmod( use std::os::unix::fs::PermissionsExt; let path = make_path(vm, path, &dir_fd); let metadata = if follow_symlinks.follow_symlinks { - fs::metadata(&path.value) + fs::metadata(path.as_str()) } else { - fs::symlink_metadata(&path.value) + fs::symlink_metadata(path.as_str()) }; let meta = metadata.map_err(|err| convert_io_error(vm, err))?; let mut permissions = meta.permissions(); permissions.set_mode(mode); - fs::set_permissions(&path.value, permissions).map_err(|err| convert_io_error(vm, err))?; + fs::set_permissions(path.as_str(), permissions).map_err(|err| convert_io_error(vm, err))?; Ok(()) } @@ -927,7 +927,7 @@ fn os_fspath(path: PyObjectRef, vm: &VirtualMachine) -> PyResult { } fn os_rename(src: PyStringRef, dst: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { - fs::rename(&src.value, &dst.value).map_err(|err| convert_io_error(vm, err)) + fs::rename(src.as_str(), dst.as_str()).map_err(|err| convert_io_error(vm, err)) } fn os_getpid(vm: &VirtualMachine) -> PyObjectRef { diff --git a/vm/src/stdlib/pwd.rs b/vm/src/stdlib/pwd.rs index 85cb2d3eb..2c687ee54 100644 --- a/vm/src/stdlib/pwd.rs +++ b/vm/src/stdlib/pwd.rs @@ -44,7 +44,7 @@ impl PasswdRef { } fn pwd_getpwnam(name: PyStringRef, vm: &VirtualMachine) -> PyResult { - match Passwd::from_name(&name.value) { + match Passwd::from_name(name.as_str()) { Ok(Some(passwd)) => Ok(passwd), _ => { let name_repr = vm.to_repr(name.as_object())?; diff --git a/vm/src/stdlib/re.rs b/vm/src/stdlib/re.rs index 49fba3185..97bcbeda1 100644 --- a/vm/src/stdlib/re.rs +++ b/vm/src/stdlib/re.rs @@ -97,7 +97,7 @@ fn re_match( vm: &VirtualMachine, ) -> PyResult { let flags = extract_flags(flags); - let regex = make_regex(vm, &pattern.value, flags)?; + let regex = make_regex(vm, pattern.as_str(), flags)?; do_match(vm, ®ex, string) } @@ -108,7 +108,7 @@ fn re_search( vm: &VirtualMachine, ) -> PyResult { let flags = extract_flags(flags); - let regex = make_regex(vm, &pattern.value, flags)?; + let regex = make_regex(vm, pattern.as_str(), flags)?; do_search(vm, ®ex, string) } @@ -311,11 +311,11 @@ fn re_compile( vm: &VirtualMachine, ) -> PyResult { let flags = extract_flags(flags); - make_regex(vm, &pattern.value, flags) + make_regex(vm, pattern.as_str(), flags) } fn re_escape(pattern: PyStringRef, _vm: &VirtualMachine) -> String { - regex::escape(&pattern.value) + regex::escape(pattern.as_str()) } fn re_purge(_vm: &VirtualMachine) {} @@ -336,7 +336,7 @@ impl PyPattern { fn sub(&self, repl: PyStringRef, text: PyStringRef, vm: &VirtualMachine) -> PyResult { let replaced_text = self .regex - .replace_all(text.value.as_bytes(), repl.as_str().as_bytes()); + .replace_all(text.as_str().as_bytes(), repl.as_str().as_bytes()); let replaced_text = String::from_utf8_lossy(&replaced_text).into_owned(); Ok(vm.ctx.new_str(replaced_text)) } diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 0a9814f9e..92fcc3db0 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -502,9 +502,7 @@ impl TryFromObject for Address { Err(vm.new_type_error("Address tuple should have only 2 values".to_string())) } else { Ok(Address { - host: PyStringRef::try_from_object(vm, tuple.elements[0].clone())? - .value - .to_string(), + host: vm.to_pystr(&tuple.elements[0])?, port: PyIntRef::try_from_object(vm, tuple.elements[1].clone())? .as_bigint() .to_usize() @@ -530,7 +528,7 @@ fn socket_gethostname(vm: &VirtualMachine) -> PyResult { #[cfg(all(unix, not(target_os = "redox")))] fn socket_sethostname(hostname: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { - sethostname(hostname.value.as_str()).map_err(|err| convert_nix_error(vm, err)) + sethostname(hostname.as_str()).map_err(|err| convert_nix_error(vm, err)) } fn socket_inet_aton(ip_string: PyStringRef, vm: &VirtualMachine) -> PyResult { diff --git a/vm/src/stdlib/symtable.rs b/vm/src/stdlib/symtable.rs index 0c4042891..e6359157d 100644 --- a/vm/src/stdlib/symtable.rs +++ b/vm/src/stdlib/symtable.rs @@ -32,7 +32,7 @@ fn symtable_symtable( .parse::() .map_err(|err| vm.new_value_error(err.to_string()))?; let symtable = - source_to_symtable(&source.value, mode).map_err(|err| vm.new_syntax_error(&err))?; + source_to_symtable(source.as_str(), mode).map_err(|err| vm.new_syntax_error(&err))?; let py_symbol_table = to_py_symbol_table(symtable); Ok(py_symbol_table.into_ref(vm)) @@ -99,7 +99,7 @@ impl PySymbolTable { #[pymethod(name = "lookup")] fn lookup(&self, name: PyStringRef, vm: &VirtualMachine) -> PyResult { - let name = &name.value; + let name = name.as_str(); if let Some(symbol) = self.symtable.symbols.get(name) { Ok(PySymbol { symbol: symbol.clone(), diff --git a/vm/src/stdlib/time_module.rs b/vm/src/stdlib/time_module.rs index f5d196b84..71063abc2 100644 --- a/vm/src/stdlib/time_module.rs +++ b/vm/src/stdlib/time_module.rs @@ -175,7 +175,7 @@ fn time_strftime( OptionalArg::Present(t) => t.get_date_time(), OptionalArg::Missing => default, }; - let formatted_time = instant.format(&format.value).to_string(); + let formatted_time = instant.format(format.as_str()).to_string(); Ok(vm.ctx.new_str(formatted_time)) } @@ -184,11 +184,11 @@ fn time_strptime( format: OptionalArg, vm: &VirtualMachine, ) -> PyResult { - let format: String = match format { - OptionalArg::Present(format) => format.value.clone(), - OptionalArg::Missing => "%a %b %H:%M:%S %Y".to_string(), + let format = match format { + OptionalArg::Present(ref format) => format.as_str(), + OptionalArg::Missing => "%a %b %H:%M:%S %Y", }; - let instant = NaiveDateTime::parse_from_str(&string.value, &format) + let instant = NaiveDateTime::parse_from_str(string.as_str(), format) .map_err(|e| vm.new_value_error(format!("Parse error: {:?}", e)))?; let struct_time = PyStructTime::new(instant, -1); Ok(struct_time) diff --git a/vm/src/stdlib/unicodedata.rs b/vm/src/stdlib/unicodedata.rs index 7c9c865da..b1e75730b 100644 --- a/vm/src/stdlib/unicodedata.rs +++ b/vm/src/stdlib/unicodedata.rs @@ -35,7 +35,7 @@ fn category(character: PyStringRef, vm: &VirtualMachine) -> PyResult { fn lookup(name: PyStringRef, vm: &VirtualMachine) -> PyResult { // TODO: we might want to use unic_ucd instead of unicode_names2 for this too, if possible: - if let Some(character) = unicode_names2::character(&name.value) { + if let Some(character) = unicode_names2::character(name.as_str()) { Ok(vm.new_str(character.to_string())) } else { Err(vm.new_key_error(vm.new_str(format!("undefined character name '{}'", name)))) @@ -70,8 +70,8 @@ fn bidirectional(character: PyStringRef, vm: &VirtualMachine) -> PyResult { fn normalize(form: PyStringRef, unistr: PyStringRef, vm: &VirtualMachine) -> PyResult { use unic::normal::StrNormalForm; - let text = &unistr.value; - let normalized_text = match form.value.as_ref() { + let text = unistr.as_str(); + let normalized_text = match form.as_str() { "NFC" => text.nfc().collect::(), "NFKC" => text.nfkc().collect::(), "NFD" => text.nfd().collect::(), @@ -85,10 +85,10 @@ fn normalize(form: PyStringRef, unistr: PyStringRef, vm: &VirtualMachine) -> PyR } fn extract_char(character: PyStringRef, vm: &VirtualMachine) -> PyResult { - if character.value.len() != 1 { + if character.as_str().len() != 1 { return Err(vm.new_type_error("argument must be an unicode character, not str".to_string())); } - let my_char: char = character.value.chars().next().unwrap(); + let my_char: char = character.as_str().chars().next().unwrap(); Ok(my_char) } diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 0494eadd7..191ac684f 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -446,7 +446,7 @@ impl VirtualMachine { pub fn to_pystr<'a, T: Into<&'a PyObjectRef>>(&'a self, obj: T) -> Result { let py_str_obj = self.to_str(obj.into())?; - Ok(py_str_obj.value.clone()) + Ok(py_str_obj.as_str().to_owned()) } pub fn to_repr(&self, obj: &PyObjectRef) -> PyResult { @@ -457,7 +457,7 @@ impl VirtualMachine { pub fn to_ascii(&self, obj: &PyObjectRef) -> PyResult { let repr = self.call_method(obj, "__repr__", vec![])?; let repr: PyStringRef = TryFromObject::try_from_object(self, repr)?; - let ascii = to_ascii(&repr.value); + let ascii = to_ascii(repr.as_str()); Ok(self.new_str(ascii)) } @@ -956,7 +956,7 @@ impl VirtualMachine { } let attr = if let Some(ref dict) = obj.dict { - dict.get_item_option(&name_str.value, self)? + dict.get_item_option(name_str.as_str(), self)? } else { None }; diff --git a/wasm/lib/src/browser_module.rs b/wasm/lib/src/browser_module.rs index abfdc2b53..f5878d7fb 100644 --- a/wasm/lib/src/browser_module.rs +++ b/wasm/lib/src/browser_module.rs @@ -267,7 +267,7 @@ impl Document { fn query(&self, query: PyStringRef, vm: &VirtualMachine) -> PyResult { let elem = self .doc - .query_selector(&query.value) + .query_selector(query.as_str()) .map_err(|err| convert::js_py_typeerror(vm, err))?; let elem = match elem { Some(elem) => Element { elem }.into_ref(vm).into_object(), @@ -298,7 +298,7 @@ impl Element { default: OptionalArg, vm: &VirtualMachine, ) -> PyObjectRef { - match self.elem.get_attribute(&attr.value) { + match self.elem.get_attribute(attr.as_str()) { Some(s) => vm.new_str(s), None => default.into_option().unwrap_or_else(|| vm.get_none()), } @@ -307,7 +307,7 @@ impl Element { #[pymethod] fn set_attr(&self, attr: PyStringRef, value: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { self.elem - .set_attribute(&attr.value, &value.value) + .set_attribute(attr.as_str(), value.as_str()) .map_err(|err| convert::js_to_py(vm, err)) } } From f846cd73278145ac67f21bc9d867e9343212b59c Mon Sep 17 00:00:00 2001 From: Noah <33094578+coolreader18@users.noreply.github.com> Date: Sat, 21 Sep 2019 15:33:52 -0500 Subject: [PATCH 3/3] Fix failing socket test --- vm/src/stdlib/socket.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 92fcc3db0..5f4079cd8 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -502,7 +502,9 @@ impl TryFromObject for Address { Err(vm.new_type_error("Address tuple should have only 2 values".to_string())) } else { Ok(Address { - host: vm.to_pystr(&tuple.elements[0])?, + host: PyStringRef::try_from_object(vm, tuple.elements[0].clone())? + .as_str() + .to_owned(), port: PyIntRef::try_from_object(vm, tuple.elements[1].clone())? .as_bigint() .to_usize()