diff --git a/src/shell.rs b/src/shell.rs index c8ca36122..88f84de0c 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -6,7 +6,7 @@ use rustpython_vm::readline::{Readline, ReadlineResult}; use rustpython_vm::{ exceptions::{print_exception, PyBaseExceptionRef}, obj::objtype, - pyobject::PyResult, + pyobject::{BorrowValue, PyResult}, scope::Scope, VirtualMachine, }; @@ -61,7 +61,7 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> { .get_attribute(vm.sys_module.clone(), prompt_name) .and_then(|prompt| vm.to_str(&prompt)); let prompt = match prompt { - Ok(ref s) => s.as_str(), + Ok(ref s) => s.borrow_value(), Err(_) => "", }; let result = match repl.readline(prompt) { diff --git a/src/shell/helper.rs b/src/shell/helper.rs index 30900d1da..c1888bb44 100644 --- a/src/shell/helper.rs +++ b/src/shell/helper.rs @@ -1,5 +1,5 @@ use rustpython_vm::obj::objstr::PyStringRef; -use rustpython_vm::pyobject::{PyIterable, PyResult, TryFromObject}; +use rustpython_vm::pyobject::{BorrowValue, PyIterable, PyResult, TryFromObject}; use rustpython_vm::scope::{NameProtocol, Scope}; use rustpython_vm::VirtualMachine; @@ -104,7 +104,7 @@ impl<'vm> ShellHelper<'vm> { .filter(|res| { res.as_ref() .ok() - .map_or(true, |s| s.as_str().starts_with(word_start)) + .map_or(true, |s| s.borrow_value().starts_with(word_start)) }) .collect::, _>>() .ok()?; @@ -117,7 +117,7 @@ impl<'vm> ShellHelper<'vm> { let no_underscore = all_completions .iter() .cloned() - .filter(|s| !s.as_str().starts_with('_')) + .filter(|s| !s.borrow_value().starts_with('_')) .collect::>(); // if there are only completions that start with a '_', give them all of the @@ -130,13 +130,13 @@ impl<'vm> ShellHelper<'vm> { }; // sort the completions alphabetically - completions.sort_by(|a, b| std::cmp::Ord::cmp(a.as_str(), b.as_str())); + completions.sort_by(|a, b| std::cmp::Ord::cmp(a.borrow_value(), b.borrow_value())); Some(( startpos, completions .into_iter() - .map(|s| s.as_str().to_owned()) + .map(|s| s.borrow_value().to_owned()) .collect(), )) } diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index eeb6a5b6d..03fe54469 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -70,7 +70,7 @@ mod decl { #[pyfunction] fn ascii(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { let repr = vm.to_repr(&obj)?; - let ascii = to_ascii(repr.as_str()); + let ascii = to_ascii(repr.borrow_value()); Ok(ascii) } @@ -121,11 +121,11 @@ mod decl { fn compile(args: CompileArgs, vm: &VirtualMachine) -> PyResult { // TODO: compile::compile should probably get bytes let source = match &args.source { - Either::A(string) => string.as_str(), + Either::A(string) => string.borrow_value(), Either::B(bytes) => std::str::from_utf8(bytes).unwrap(), }; - let mode_str = args.mode.as_str(); + let mode_str = args.mode.borrow_value(); let flags = args .flags @@ -138,7 +138,7 @@ mod decl { .parse::() .map_err(|err| vm.new_value_error(err.to_string()))?; - vm.compile(&source, mode, args.filename.as_str().to_owned()) + vm.compile(&source, mode, args.filename.borrow_value().to_owned()) .map(|o| o.into_object()) .map_err(|err| vm.new_syntax_error(&err)) } else { @@ -230,7 +230,7 @@ mod decl { // Determine code object: let code_obj = match source { Either::A(string) => vm - .compile(string.as_str(), mode, "".to_owned()) + .compile(string.borrow_value(), mode, "".to_owned()) .map_err(|err| vm.new_syntax_error(&err))?, Either::B(code_obj) => code_obj, }; @@ -355,7 +355,7 @@ mod decl { #[pyfunction] fn input(prompt: OptionalArg, vm: &VirtualMachine) -> PyResult { - let prompt = prompt.as_ref().map_or("", |s| s.as_str()); + let prompt = prompt.as_ref().map_or("", |s| s.borrow_value()); let mut readline = Readline::new(()); match readline.readline(prompt) { ReadlineResult::Line(s) => Ok(s), @@ -568,7 +568,7 @@ mod decl { Ok(u32::from(bytes[0])) }), Either::B(string) => { - let string = string.as_str(); + let string = string.borrow_value(); let string_len = string.chars().count(); if string_len != 1 { return Err(vm.new_type_error(format!( @@ -779,7 +779,11 @@ mod decl { mut kwargs: KwArgs, vm: &VirtualMachine, ) -> PyResult { - let name = qualified_name.as_str().split('.').next_back().unwrap(); + let name = qualified_name + .borrow_value() + .split('.') + .next_back() + .unwrap(); let name_obj = vm.new_str(name.to_owned()); let mut metaclass = if let Some(metaclass) = kwargs.pop_kwarg("metaclass") { diff --git a/vm/src/cformat.rs b/vm/src/cformat.rs index a04160248..71ca8c66d 100644 --- a/vm/src/cformat.rs +++ b/vm/src/cformat.rs @@ -2,7 +2,9 @@ /// [https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting] use crate::format::get_num_digits; use crate::obj::{objfloat, objint, objstr, objtuple, objtype}; -use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult, TryFromObject, TypeProtocol}; +use crate::pyobject::{ + BorrowValue, ItemProtocol, PyObjectRef, PyResult, TryFromObject, TypeProtocol, +}; use crate::vm::VirtualMachine; use num_bigint::{BigInt, Sign}; use num_traits::cast::ToPrimitive; @@ -295,7 +297,7 @@ impl CFormatSpec { vm.call_method(&obj.clone(), "decode", vec![])?, )?, }; - Ok(self.format_string(result.as_str().to_owned())) + Ok(self.format_string(result.borrow_value().to_owned())) } CFormatType::Number(number_type) => { if !objtype::isinstance(&obj, &vm.ctx.types.int_type) { diff --git a/vm/src/dictdatatype.rs b/vm/src/dictdatatype.rs index 5a64c875f..1a4102488 100644 --- a/vm/src/dictdatatype.rs +++ b/vm/src/dictdatatype.rs @@ -4,7 +4,7 @@ /// And: http://code.activestate.com/recipes/578375/ use crate::common::cell::{PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard}; use crate::obj::objstr::{PyString, PyStringRef}; -use crate::pyobject::{IdProtocol, IntoPyObject, PyObjectRef, PyResult}; +use crate::pyobject::{BorrowValue, IdProtocol, IntoPyObject, PyObjectRef, PyResult}; use crate::vm::VirtualMachine; use rustpython_common::hash; use std::collections::HashMap; @@ -447,7 +447,7 @@ impl DictKey for PyStringRef { if self.is(other_key) { Ok(true) } else if let Some(py_str_value) = other_key.payload::() { - Ok(py_str_value.as_str() == self.as_str()) + Ok(py_str_value.borrow_value() == self.borrow_value()) } else { vm.bool_eq(self.clone().into_object(), other_key.clone()) } @@ -472,7 +472,7 @@ impl DictKey for &str { fn key_eq(&self, vm: &VirtualMachine, other_key: &PyObjectRef) -> PyResult { if let Some(py_str_value) = other_key.payload::() { - Ok(py_str_value.as_str() == *self) + Ok(py_str_value.borrow_value() == *self) } else { // Fall back to PyObjectRef implementation. let s = vm.ctx.new_str(*self); diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 38606b3fb..0dd5481e9 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -24,7 +24,8 @@ use crate::obj::objtraceback::PyTraceback; use crate::obj::objtuple::PyTuple; use crate::obj::objtype::{self, PyClassRef}; use crate::pyobject::{ - IdProtocol, ItemProtocol, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol, + BorrowValue, IdProtocol, ItemProtocol, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, + TypeProtocol, }; use crate::scope::{NameProtocol, Scope}; use crate::vm::VirtualMachine; @@ -795,7 +796,7 @@ impl ExecutingFrame<'_> { if let Some(dict) = module.dict() { for (k, v) in &dict { let k = vm.to_str(&k)?; - let k = k.as_str(); + let k = k.borrow_value(); if !k.starts_with('_') { self.scope.store_name(&vm, k, v); } @@ -991,7 +992,7 @@ impl ExecutingFrame<'_> { let key_repr = vm.to_repr(&key)?; let msg = format!( "got multiple values for keyword argument {}", - key_repr.as_str() + key_repr.borrow_value() ); return Err(vm.new_type_error(msg)); } @@ -1066,7 +1067,7 @@ impl ExecutingFrame<'_> { let mut kwargs = IndexMap::new(); for (key, value) in kw_dict.into_iter() { if let Some(key) = key.payload_if_subclass::(vm) { - kwargs.insert(key.as_str().to_owned(), value); + kwargs.insert(key.borrow_value().to_owned(), value); } else { return Err(vm.new_type_error("keywords must be strings".to_owned())); } @@ -1285,7 +1286,11 @@ impl ExecutingFrame<'_> { .ctx .new_pyfunction(code_obj, scope, defaults, kw_only_defaults); - let name = qualified_name.as_str().split('.').next_back().unwrap(); + let name = qualified_name + .borrow_value() + .split('.') + .next_back() + .unwrap(); vm.set_attr(&func_obj, "__name__", vm.new_str(name.to_owned()))?; 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 e97e8eee3..b57b1c2bb 100644 --- a/vm/src/obj/objbool.rs +++ b/vm/src/obj/objbool.rs @@ -103,7 +103,7 @@ impl PyBool { format_spec: PyStringRef, vm: &VirtualMachine, ) -> PyResult { - if format_spec.as_str().is_empty() { + if format_spec.borrow_value().is_empty() { vm.to_str(&obj) } else { Err(vm.new_type_error("unsupported format string passed to bool.__format__".to_owned())) diff --git a/vm/src/obj/objbytearray.rs b/vm/src/obj/objbytearray.rs index b0d29d0ac..5e071f891 100644 --- a/vm/src/obj/objbytearray.rs +++ b/vm/src/obj/objbytearray.rs @@ -256,7 +256,7 @@ impl PyByteArray { #[pymethod] fn fromhex(string: PyStringRef, vm: &VirtualMachine) -> PyResult { - Ok(PyBytesInner::fromhex(string.as_str(), vm)?.into()) + Ok(PyBytesInner::fromhex(string.borrow_value(), vm)?.into()) } #[pymethod(name = "center")] @@ -590,7 +590,7 @@ impl PyByteArray { vm.new_type_error(format!( "'{}' decoder returned '{}' instead of 'str'; use codecs.encode() to \ encode arbitrary types", - encoding.as_ref().map_or("utf-8", |s| s.as_str()), + encoding.as_ref().map_or("utf-8", |s| s.borrow_value()), obj.lease_class().name, )) }) diff --git a/vm/src/obj/objbytes.rs b/vm/src/obj/objbytes.rs index 5cd8a023e..7b9660ecc 100644 --- a/vm/src/obj/objbytes.rs +++ b/vm/src/obj/objbytes.rs @@ -238,7 +238,7 @@ impl PyBytes { #[pymethod] fn fromhex(string: PyStringRef, vm: &VirtualMachine) -> PyResult { - Ok(PyBytesInner::fromhex(string.as_str(), vm)?.into()) + Ok(PyBytesInner::fromhex(string.borrow_value(), vm)?.into()) } #[pymethod(name = "center")] @@ -481,7 +481,7 @@ impl PyBytes { vm.new_type_error(format!( "'{}' decoder returned '{}' instead of 'str'; use codecs.encode() to \ encode arbitrary types", - encoding.as_ref().map_or("utf-8", |s| s.as_str()), + encoding.as_ref().map_or("utf-8", |s| s.borrow_value()), obj.lease_class().name, )) }) diff --git a/vm/src/obj/objcomplex.rs b/vm/src/obj/objcomplex.rs index 577447de8..7da74eb42 100644 --- a/vm/src/obj/objcomplex.rs +++ b/vm/src/obj/objcomplex.rs @@ -245,7 +245,7 @@ impl PyComplex { "complex() can't take second arg if first is a string".to_owned(), )); } - let value = Complex64::from_str(s.as_str()) + let value = Complex64::from_str(s.borrow_value()) .map_err(|err| vm.new_value_error(err.to_string()))?; return PyComplex { value }.into_ref_with_type(vm, cls); } diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index 90b522485..94e13e21f 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -9,8 +9,8 @@ use crate::dictdatatype::{self, DictKey}; use crate::exceptions::PyBaseExceptionRef; use crate::function::{KwArgs, OptionalArg, PyFuncArgs}; use crate::pyobject::{ - IdProtocol, IntoPyObject, ItemProtocol, PyAttributes, PyClassImpl, PyContext, PyIterable, - PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol, + BorrowValue, IdProtocol, IntoPyObject, ItemProtocol, PyAttributes, PyClassImpl, PyContext, + PyIterable, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol, }; use crate::vm::{ReprGuard, VirtualMachine}; @@ -199,7 +199,11 @@ 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.as_str(), value_repr.as_str())); + str_parts.push(format!( + "{}: {}", + key_repr.borrow_value(), + value_repr.borrow_value() + )); } format!("{{{}}}", str_parts.join(", ")) @@ -571,7 +575,7 @@ macro_rules! dict_iterator { let mut str_parts = vec![]; for (key, value) in zelf.dict.clone() { let s = vm.to_repr(&$result_fn(vm, key, value))?; - str_parts.push(s.as_str().to_owned()); + str_parts.push(s.borrow_value().to_owned()); } format!("{}([{}])", $class_name, str_parts.join(", ")) } else { diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index 802a16994..a8a0c0baa 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -187,7 +187,7 @@ impl PyFloat { #[pymethod(name = "__format__")] fn format(&self, spec: PyStringRef, vm: &VirtualMachine) -> PyResult { - match FormatSpec::parse(spec.as_str()) + match FormatSpec::parse(spec.borrow_value()) .and_then(|format_spec| format_spec.format_float(self.value)) { Ok(string) => Ok(string), @@ -508,7 +508,7 @@ impl PyFloat { #[pymethod] fn fromhex(repr: PyStringRef, vm: &VirtualMachine) -> PyResult { - float_ops::from_hex(repr.as_str().trim()).ok_or_else(|| { + float_ops::from_hex(repr.borrow_value().trim()).ok_or_else(|| { vm.new_value_error("invalid hexadecimal floating-point string".to_owned()) }) } @@ -525,7 +525,7 @@ fn to_float(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult { } else if let Some(int) = obj.payload_if_subclass::(vm) { objint::try_float(int.borrow_value(), vm)? } else if let Some(s) = obj.payload_if_subclass::(vm) { - float_ops::parse_str(s.as_str().trim()).ok_or_else(|| { + float_ops::parse_str(s.borrow_value().trim()).ok_or_else(|| { vm.new_value_error(format!("could not convert string to float: '{}'", s)) })? } else if let Some(bytes) = obj.payload_if_subclass::(vm) { diff --git a/vm/src/obj/objfunction.rs b/vm/src/obj/objfunction.rs index e17f20b7f..3aabaf570 100644 --- a/vm/src/obj/objfunction.rs +++ b/vm/src/obj/objfunction.rs @@ -10,8 +10,8 @@ use crate::obj::objasyncgenerator::PyAsyncGen; use crate::obj::objcoroutine::PyCoroutine; use crate::obj::objgenerator::PyGenerator; use crate::pyobject::{ - IdProtocol, ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, - TypeProtocol, + BorrowValue, IdProtocol, ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, + PyValue, TypeProtocol, }; use crate::scope::Scope; use crate::slots::{SlotCall, SlotDescriptor}; @@ -314,7 +314,7 @@ impl PyBoundMethod { fn repr(&self, vm: &VirtualMachine) -> PyResult { Ok(format!( "", - vm.to_repr(&self.object)?.as_str() + vm.to_repr(&self.object)?.borrow_value() )) } @@ -325,7 +325,7 @@ impl PyBoundMethod { #[pymethod(magic)] fn getattribute(zelf: PyRef, name: PyStringRef, vm: &VirtualMachine) -> PyResult { - if let Some(obj) = zelf.get_class_attr(name.as_str()) { + if let Some(obj) = zelf.get_class_attr(name.borrow_value()) { return vm.call_if_get_descriptor(obj, zelf.into_object()); } vm.get_attribute(zelf.function.clone(), name) diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index 2eeb7b6f7..8af718f5f 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -18,8 +18,9 @@ use crate::bytesinner::PyBytesInner; use crate::format::FormatSpec; use crate::function::{OptionalArg, PyFuncArgs}; use crate::pyobject::{ - IdProtocol, IntoPyObject, IntoPyResult, PyArithmaticValue, PyClassImpl, PyComparisonValue, - PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol, BorrowValue + BorrowValue, IdProtocol, IntoPyObject, IntoPyResult, PyArithmaticValue, PyClassImpl, + PyComparisonValue, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, + TypeProtocol, }; use crate::stdlib::array::PyArray; use crate::vm::VirtualMachine; @@ -567,7 +568,7 @@ impl PyInt { #[pymethod(name = "__format__")] fn format(&self, spec: PyStringRef, vm: &VirtualMachine) -> PyResult { - match FormatSpec::parse(spec.as_str()) + match FormatSpec::parse(spec.borrow_value()) .and_then(|format_spec| format_spec.format_int(&self.value)) { Ok(string) => Ok(string), @@ -615,7 +616,7 @@ impl PyInt { false }; - let value = match (args.byteorder.as_str(), signed) { + let value = match (args.byteorder.borrow_value(), signed) { ("big", true) => BigInt::from_signed_bytes_be(&args.bytes.elements), ("big", false) => BigInt::from_bytes_be(Sign::Plus, &args.bytes.elements), ("little", true) => BigInt::from_signed_bytes_le(&args.bytes.elements), @@ -650,7 +651,7 @@ impl PyInt { ); }; - let mut origin_bytes = match args.byteorder.as_str() { + let mut origin_bytes = match args.byteorder.borrow_value() { "big" => match signed { true => value.to_signed_bytes_be(), false => value.to_bytes_be().1, @@ -677,7 +678,7 @@ impl PyInt { }; let mut bytes = vec![]; - match args.byteorder.as_str() { + match args.byteorder.borrow_value() { "big" => { bytes = append_bytes; bytes.append(&mut origin_bytes); @@ -757,7 +758,7 @@ pub(crate) fn to_int(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult let base = 10; let opt = match_class!(match obj.clone() { string @ PyString => { - let s = string.as_str(); + let s = string.borrow_value(); bytes_to_int(s.as_bytes(), base) } bytes @ PyBytes => { @@ -810,7 +811,7 @@ fn to_int_radix(vm: &VirtualMachine, obj: &PyObjectRef, base: u32) -> PyResult { - let s = string.as_str(); + let s = string.borrow_value(); bytes_to_int(s.as_bytes(), base) } bytes @ PyBytes => { diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index cbd3987ca..b35f53179 100644 --- a/vm/src/obj/objlist.rs +++ b/vm/src/obj/objlist.rs @@ -425,7 +425,7 @@ impl PyList { let mut str_parts = Vec::with_capacity(elements.len()); for elem in elements.iter() { let s = vm.to_repr(elem)?; - str_parts.push(s.as_str().to_owned()); + str_parts.push(s.borrow_value().to_owned()); } format!("[{}]", str_parts.join(", ")) } else { @@ -491,7 +491,7 @@ impl PyList { } } let needle_str = vm.to_str(&needle)?; - Err(vm.new_value_error(format!("'{}' is not in list", needle_str.as_str()))) + Err(vm.new_value_error(format!("'{}' is not in list", needle_str.borrow_value()))) } #[pymethod] @@ -526,7 +526,7 @@ impl PyList { Ok(()) } else { let needle_str = vm.to_str(&needle)?; - Err(vm.new_value_error(format!("'{}' is not in list", needle_str.as_str()))) + Err(vm.new_value_error(format!("'{}' is not in list", needle_str.borrow_value()))) } } diff --git a/vm/src/obj/objmappingproxy.rs b/vm/src/obj/objmappingproxy.rs index 67256eca0..ed819b0a8 100644 --- a/vm/src/obj/objmappingproxy.rs +++ b/vm/src/obj/objmappingproxy.rs @@ -4,7 +4,8 @@ use super::objstr::PyStringRef; use super::objtype::PyClassRef; use crate::function::OptionalArg; use crate::pyobject::{ - ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, + BorrowValue, ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, + TryFromObject, }; use crate::vm::VirtualMachine; @@ -48,7 +49,7 @@ impl PyMappingProxy { let opt = match &self.mapping { MappingProxyInner::Class(class) => { let key = PyStringRef::try_from_object(vm, key)?; - class.get_attr(key.as_str()) + class.get_attr(key.borrow_value()) } MappingProxyInner::Dict(obj) => obj.get_item(key, vm).ok(), }; @@ -75,7 +76,7 @@ impl PyMappingProxy { match &self.mapping { MappingProxyInner::Class(class) => { let key = PyStringRef::try_from_object(vm, key)?; - Ok(vm.new_bool(class.has_attr(key.as_str()))) + Ok(vm.new_bool(class.has_attr(key.borrow_value()))) } MappingProxyInner::Dict(obj) => vm._membership(obj.clone(), key), } diff --git a/vm/src/obj/objmodule.rs b/vm/src/obj/objmodule.rs index abed0794f..9db052148 100644 --- a/vm/src/obj/objmodule.rs +++ b/vm/src/obj/objmodule.rs @@ -3,7 +3,7 @@ use super::objstr::{PyString, PyStringRef}; use super::objtype::PyClassRef; use crate::function::OptionalOption; use crate::pyobject::{ - ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, + BorrowValue, ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, }; use crate::vm::VirtualMachine; @@ -70,7 +70,10 @@ impl PyModuleRef { None, ) .unwrap_or(None) - .and_then(|obj| obj.payload::().map(|s| s.as_str().to_owned())) + .and_then(|obj| { + obj.payload::() + .map(|s| s.borrow_value().to_owned()) + }) } #[pymethod(magic)] diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index 8428fa116..b4ce1d1d6 100644 --- a/vm/src/obj/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -6,8 +6,9 @@ use super::objtype::PyClassRef; use crate::function::{OptionalArg, PyFuncArgs}; use crate::obj::objtype::PyClass; use crate::pyobject::{ - IdProtocol, ItemProtocol, PyArithmaticValue::*, PyAttributes, PyClassImpl, PyComparisonValue, - PyContext, PyObject, PyObjectRef, PyResult, PyValue, TryFromObject, TypeProtocol, + BorrowValue, IdProtocol, ItemProtocol, PyArithmaticValue::*, PyAttributes, PyClassImpl, + PyComparisonValue, PyContext, PyObject, PyObjectRef, PyResult, PyValue, TryFromObject, + TypeProtocol, }; use crate::vm::VirtualMachine; @@ -100,20 +101,20 @@ impl PyBaseObject { #[pymethod(magic)] fn delattr(obj: PyObjectRef, attr_name: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { - if let Some(attr) = obj.get_class_attr(attr_name.as_str()) { + if let Some(attr) = obj.get_class_attr(attr_name.borrow_value()) { if let Some(descriptor) = attr.get_class_attr("__delete__") { return vm.invoke(&descriptor, vec![attr, obj.clone()]).map(|_| ()); } } if let Some(dict) = obj.dict() { - dict.del_item(attr_name.as_str(), vm)?; + dict.del_item(attr_name.borrow_value(), vm)?; Ok(()) } else { Err(vm.new_attribute_error(format!( "'{}' object has no attribute '{}'", obj.lease_class().name, - attr_name.as_str() + attr_name.borrow_value() ))) } } @@ -167,7 +168,7 @@ impl PyBaseObject { format_spec: PyStringRef, vm: &VirtualMachine, ) -> PyResult { - if format_spec.as_str().is_empty() { + if format_spec.borrow_value().is_empty() { vm.to_str(&obj) } else { Err(vm.new_type_error( @@ -262,7 +263,7 @@ pub(crate) fn setattr( ) -> PyResult<()> { vm_trace!("object.__setattr__({:?}, {}, {:?})", obj, attr_name, value); - if let Some(attr) = obj.get_class_attr(attr_name.as_str()) { + if let Some(attr) = obj.get_class_attr(attr_name.borrow_value()) { if let Some(descriptor) = attr.get_class_attr("__set__") { return vm .invoke(&descriptor, vec![attr, obj.clone(), value]) @@ -271,13 +272,13 @@ pub(crate) fn setattr( } if let Some(dict) = obj.dict() { - dict.set_item(attr_name.as_str(), value, vm)?; + dict.set_item(attr_name.borrow_value(), value, vm)?; Ok(()) } else { Err(vm.new_attribute_error(format!( "'{}' object has no attribute '{}'", obj.lease_class().name, - attr_name.as_str() + attr_name.borrow_value() ))) } } diff --git a/vm/src/obj/objset.rs b/vm/src/obj/objset.rs index b68373d5c..c43cf25e1 100644 --- a/vm/src/obj/objset.rs +++ b/vm/src/obj/objset.rs @@ -8,8 +8,8 @@ use super::objtype::{self, PyClassRef}; use crate::dictdatatype; use crate::function::{Args, OptionalArg}; use crate::pyobject::{ - self, PyClassImpl, PyContext, PyIterable, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, - TypeProtocol, + self, BorrowValue, PyClassImpl, PyContext, PyIterable, PyObjectRef, PyRef, PyResult, PyValue, + TryFromObject, TypeProtocol, }; use crate::vm::{ReprGuard, VirtualMachine}; use rustpython_common::hash::PyHash; @@ -250,7 +250,7 @@ impl PySetInner { 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.as_str().to_owned()); + str_parts.push(part.borrow_value().to_owned()); } Ok(format!("{{{}}}", str_parts.join(", "))) diff --git a/vm/src/obj/objslice.rs b/vm/src/obj/objslice.rs index 473132fb3..3d066b7dc 100644 --- a/vm/src/obj/objslice.rs +++ b/vm/src/obj/objslice.rs @@ -62,9 +62,9 @@ impl PySlice { Ok(format!( "slice({}, {}, {})", - start_repr.as_str(), - stop_repr.as_str(), - step_repr.as_str() + start_repr.borrow_value(), + stop_repr.borrow_value(), + step_repr.borrow_value() )) } diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index bb81415c9..fe880f875 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -50,9 +50,16 @@ pub struct PyString { len: AtomicCell>, } -impl PyString { - #[inline] - pub fn as_str(&self) -> &str { +impl<'a> BorrowValue<'a> for PyString { + type Borrowed = &'a str; + + fn borrow_value(&'a self) -> Self::Borrowed { + &self.value + } +} + +impl AsRef for PyString { + fn as_ref(&self) -> &str { &self.value } } @@ -196,7 +203,7 @@ impl PyString { if string.class().is(&cls) { Ok(string) } else { - PyString::from(string.as_str()).into_ref_with_type(vm, cls) + PyString::from(string.borrow_value()).into_ref_with_type(vm, cls) } } @@ -502,7 +509,7 @@ impl PyString { args, "endswith", "str", - |s, x: &PyStringRef| s.ends_with(x.as_str()), + |s, x: &PyStringRef| s.ends_with(x.borrow_value()), vm, ) } @@ -513,7 +520,7 @@ impl PyString { args, "startswith", "str", - |s, x: &PyStringRef| s.starts_with(x.as_str()), + |s, x: &PyStringRef| s.starts_with(x.borrow_value()), vm, ) } @@ -609,7 +616,7 @@ impl PyString { #[pymethod(name = "__format__")] fn format_str(&self, spec: PyStringRef, vm: &VirtualMachine) -> PyResult { - match FormatSpec::parse(spec.as_str()) + match FormatSpec::parse(spec.borrow_value()) .and_then(|format_spec| format_spec.format_string(&self.value)) { Ok(string) => Ok(string), @@ -1088,7 +1095,7 @@ pub(crate) fn encode_string( vm.new_type_error(format!( "'{}' encoder returned '{}' instead of 'bytes'; use codecs.encode() to \ encode arbitrary types", - encoding.as_ref().map_or("utf-8", |s| s.as_str()), + encoding.as_ref().map_or("utf-8", |s| s.borrow_value()), obj.lease_class().name, )) }) @@ -1121,7 +1128,7 @@ impl IntoPyObject for &String { impl TryFromObject for std::ffi::CString { fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { let s = PyStringRef::try_from_object(vm, obj)?; - Self::new(s.as_str().to_owned()) + Self::new(s.borrow_value().to_owned()) .map_err(|_| vm.new_value_error("embedded null character".to_owned())) } } diff --git a/vm/src/obj/objsuper.rs b/vm/src/obj/objsuper.rs index 8f57f6362..64ebfd1ce 100644 --- a/vm/src/obj/objsuper.rs +++ b/vm/src/obj/objsuper.rs @@ -10,8 +10,8 @@ use super::objstr::PyStringRef; use super::objtype::{self, PyClass, PyClassRef}; use crate::function::OptionalArg; use crate::pyobject::{ - IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, - TypeProtocol, + BorrowValue, IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, + TryFromObject, TypeProtocol, }; use crate::scope::NameProtocol; use crate::slots::SlotDescriptor; @@ -65,7 +65,7 @@ impl PySuper { let mut it = obj_type.iter_mro().peekable(); for _ in it.peeking_take_while(|cls| !cls.is(&zelf.typ)) {} for cls in it.skip(1) { - if let Some(descr) = cls.get_attr(name.as_str()) { + if let Some(descr) = cls.get_attr(name.borrow_value()) { return vm .call_get_descriptor_specific( descr.clone(), diff --git a/vm/src/obj/objtuple.rs b/vm/src/obj/objtuple.rs index 6fca5bb9c..0df5e7540 100644 --- a/vm/src/obj/objtuple.rs +++ b/vm/src/obj/objtuple.rs @@ -6,7 +6,7 @@ use super::objsequence::get_item; use super::objtype::PyClassRef; use crate::function::OptionalArg; use crate::pyobject::{ - self, IntoPyObject, + self, BorrowValue, IntoPyObject, PyArithmaticValue::{self, *}, PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue, }; @@ -179,7 +179,7 @@ impl PyTuple { let mut str_parts = Vec::with_capacity(zelf.elements.len()); for elem in zelf.elements.iter() { let s = vm.to_repr(elem)?; - str_parts.push(s.as_str().to_owned()); + str_parts.push(s.borrow_value().to_owned()); } if str_parts.len() == 1 { diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 1de26d7f2..aefee81ea 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -12,8 +12,8 @@ use super::objtuple::PyTuple; use super::objweakref::PyWeak; use crate::function::{KwArgs, OptionalArg, PyFuncArgs}; use crate::pyobject::{ - IdProtocol, PyAttributes, PyClassImpl, PyContext, PyIterable, PyLease, PyObject, PyObjectRef, - PyRef, PyResult, PyValue, TypeProtocol, + BorrowValue, IdProtocol, PyAttributes, PyClassImpl, PyContext, PyIterable, PyLease, PyObject, + PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, }; use crate::slots::{PyClassSlots, PyTpFlags}; use crate::vm::VirtualMachine; @@ -129,7 +129,7 @@ impl PyClassRef { #[pymethod(magic)] fn getattribute(self, name_ref: PyStringRef, vm: &VirtualMachine) -> PyResult { - let name = name_ref.as_str(); + let name = name_ref.borrow_value(); vm_trace!("type.__getattribute__({:?}, {:?})", self, name); let mcl = self.lease_class(); @@ -182,7 +182,7 @@ impl PyClassRef { value: PyObjectRef, vm: &VirtualMachine, ) -> PyResult<()> { - if let Some(attr) = self.get_class_attr(attr_name.as_str()) { + if let Some(attr) = self.get_class_attr(attr_name.borrow_value()) { if let Some(ref descriptor) = attr.get_class_attr("__set__") { vm.invoke(descriptor, vec![attr, self.into_object(), value])?; return Ok(()); @@ -195,7 +195,7 @@ impl PyClassRef { #[pymethod(magic)] fn delattr(self, attr_name: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { - if let Some(attr) = self.get_class_attr(attr_name.as_str()) { + if let Some(attr) = self.get_class_attr(attr_name.borrow_value()) { if let Some(ref descriptor) = attr.get_class_attr("__delete__") { return vm .invoke(descriptor, vec![attr, self.into_object()]) @@ -203,11 +203,11 @@ impl PyClassRef { } } - if self.get_attr(attr_name.as_str()).is_some() { - self.attributes.write().remove(attr_name.as_str()); + if self.get_attr(attr_name.borrow_value()).is_some() { + self.attributes.write().remove(attr_name.borrow_value()); Ok(()) } else { - Err(vm.new_attribute_error(attr_name.as_str().to_owned())) + Err(vm.new_attribute_error(attr_name.borrow_value().to_owned())) } } @@ -308,8 +308,14 @@ impl PyClassRef { } } - let typ = new(metatype, name.as_str(), base.clone(), bases, attributes) - .map_err(|e| vm.new_type_error(e))?; + let typ = new( + metatype, + name.borrow_value(), + base.clone(), + bases, + attributes, + ) + .map_err(|e| vm.new_type_error(e))?; typ.slots.write().flags = base.slots.read().flags; vm.ctx.add_tp_new_wrapper(&typ); diff --git a/vm/src/stdlib/array.rs b/vm/src/stdlib/array.rs index 42aa8f6fa..555058ea4 100644 --- a/vm/src/stdlib/array.rs +++ b/vm/src/stdlib/array.rs @@ -284,8 +284,8 @@ impl PyArray { init: OptionalArg, vm: &VirtualMachine, ) -> PyResult { - let spec = match spec.as_str().len() { - 1 => spec.as_str().chars().next().unwrap(), + let spec = match spec.borrow_value().len() { + 1 => spec.borrow_value().chars().next().unwrap(), _ => { return Err(vm.new_type_error( "array() argument 1 must be a unicode character, not str".to_owned(), diff --git a/vm/src/stdlib/binascii.rs b/vm/src/stdlib/binascii.rs index 859c9f703..a76e0e590 100644 --- a/vm/src/stdlib/binascii.rs +++ b/vm/src/stdlib/binascii.rs @@ -24,7 +24,7 @@ mod decl { b @ PyBytes => Ok(SerializedData::Bytes(b)), b @ PyByteArray => Ok(SerializedData::Buffer(b)), a @ PyString => { - if a.as_str().is_ascii() { + if a.borrow_value().is_ascii() { Ok(SerializedData::Ascii(a)) } else { Err(vm.new_value_error( @@ -46,7 +46,7 @@ mod decl { match self { SerializedData::Bytes(b) => f(b.borrow_value()), SerializedData::Buffer(b) => f(&b.borrow_value().elements), - SerializedData::Ascii(a) => f(a.as_str().as_bytes()), + SerializedData::Ascii(a) => f(a.borrow_value().as_bytes()), } } } diff --git a/vm/src/stdlib/csv.rs b/vm/src/stdlib/csv.rs index 7db15d984..585da018f 100644 --- a/vm/src/stdlib/csv.rs +++ b/vm/src/stdlib/csv.rs @@ -8,8 +8,10 @@ use crate::function::PyFuncArgs; use crate::obj::objiter; use crate::obj::objstr::{self, PyString}; use crate::obj::objtype::PyClassRef; -use crate::pyobject::{IntoPyObject, TryFromObject, TypeProtocol}; -use crate::pyobject::{PyClassImpl, PyIterable, PyObjectRef, PyRef, PyResult, PyValue}; +use crate::pyobject::{ + BorrowValue, IntoPyObject, PyClassImpl, PyIterable, PyObjectRef, PyRef, PyResult, PyValue, + TryFromObject, TypeProtocol, +}; use crate::types::create_type; use crate::VirtualMachine; @@ -76,7 +78,7 @@ fn into_strings(iterable: &PyIterable, vm: &VirtualMachine) -> PyRe .iter(vm)? .map(|py_obj_ref| { match_class!(match py_obj_ref? { - py_str @ PyString => Ok(py_str.as_str().trim().to_owned()), + py_str @ PyString => Ok(py_str.borrow_value().trim().to_owned()), obj => { let msg = format!( "iterator should return strings, not {} (did you open the file in text mode?)", diff --git a/vm/src/stdlib/dis.rs b/vm/src/stdlib/dis.rs index 26fe0a1fe..2f591f855 100644 --- a/vm/src/stdlib/dis.rs +++ b/vm/src/stdlib/dis.rs @@ -1,7 +1,7 @@ use crate::bytecode::CodeFlags; use crate::obj::objcode::PyCodeRef; use crate::obj::objstr::PyStringRef; -use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult, TryFromObject}; +use crate::pyobject::{BorrowValue, ItemProtocol, PyObjectRef, PyResult, TryFromObject}; use crate::vm::VirtualMachine; use rustpython_compiler::compile; @@ -14,7 +14,11 @@ fn dis_dis(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { // String: if let Ok(co_str) = PyStringRef::try_from_object(vm, obj.clone()) { let code = vm - .compile(co_str.as_str(), compile::Mode::Exec, "".to_owned()) + .compile( + co_str.borrow_value(), + compile::Mode::Exec, + "".to_owned(), + ) .map_err(|err| vm.new_syntax_error(&err))? .into_object(); return dis_disassemble(code, vm); diff --git a/vm/src/stdlib/hashlib.rs b/vm/src/stdlib/hashlib.rs index 7b4a53a11..6c465c95f 100644 --- a/vm/src/stdlib/hashlib.rs +++ b/vm/src/stdlib/hashlib.rs @@ -93,7 +93,7 @@ fn hashlib_new( data: OptionalArg, vm: &VirtualMachine, ) -> PyResult { - match name.as_str() { + match name.borrow_value() { "md5" => md5(data, vm), "sha1" => sha1(data, vm), "sha224" => sha224(data, vm), diff --git a/vm/src/stdlib/imp.rs b/vm/src/stdlib/imp.rs index c11b27431..d718403ec 100644 --- a/vm/src/stdlib/imp.rs +++ b/vm/src/stdlib/imp.rs @@ -4,7 +4,7 @@ use crate::obj::objcode::PyCode; use crate::obj::objmodule::PyModuleRef; use crate::obj::objstr; use crate::obj::objstr::PyStringRef; -use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult}; +use crate::pyobject::{BorrowValue, ItemProtocol, PyObjectRef, PyResult}; #[cfg(not(target_arch = "wasm32"))] use crate::stdlib::thread::RawRMutex; use crate::vm::VirtualMachine; @@ -48,11 +48,11 @@ fn imp_lock_held(_vm: &VirtualMachine) -> bool { } fn imp_is_builtin(name: PyStringRef, vm: &VirtualMachine) -> bool { - vm.state.stdlib_inits.contains_key(name.as_str()) + vm.state.stdlib_inits.contains_key(name.borrow_value()) } fn imp_is_frozen(name: PyStringRef, vm: &VirtualMachine) -> bool { - vm.state.frozen.contains_key(name.as_str()) + vm.state.frozen.contains_key(name.borrow_value()) } fn imp_create_builtin(spec: PyObjectRef, vm: &VirtualMachine) -> PyResult { @@ -75,37 +75,29 @@ fn imp_exec_builtin(_mod: PyModuleRef) -> i32 { } fn imp_get_frozen_object(name: PyStringRef, vm: &VirtualMachine) -> PyResult { + let name = name.borrow_value(); vm.state .frozen - .get(name.as_str()) + .get(name) .map(|frozen| { let mut frozen = frozen.code.clone(); - frozen.source_path = format!("frozen {}", name.as_str()); + frozen.source_path = format!("frozen {}", name); PyCode::new(frozen) }) - .ok_or_else(|| { - vm.new_import_error( - format!("No such frozen object named {}", name.as_str()), - name.as_str(), - ) - }) + .ok_or_else(|| vm.new_import_error(format!("No such frozen object named {}", name), name)) } fn imp_init_frozen(name: PyStringRef, vm: &VirtualMachine) -> PyResult { - import::import_frozen(vm, name.as_str()) + import::import_frozen(vm, name.borrow_value()) } fn imp_is_frozen_package(name: PyStringRef, vm: &VirtualMachine) -> PyResult { + let name = name.borrow_value(); vm.state .frozen - .get(name.as_str()) + .get(name) .map(|frozen| frozen.package) - .ok_or_else(|| { - vm.new_import_error( - format!("No such frozen object named {}", name.as_str()), - name.as_str(), - ) - }) + .ok_or_else(|| vm.new_import_error(format!("No such frozen object named {}", name), name)) } fn imp_fix_co_filename(_code: PyObjectRef, _path: PyStringRef) { diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index 2f4a9248e..4e2701b19 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -203,7 +203,7 @@ impl PyStringIORef { //write string to underlying vector fn write(self, data: PyStringRef, vm: &VirtualMachine) -> PyResult { - let bytes = data.as_str().as_bytes(); + let bytes = data.borrow_value().as_bytes(); match self.buffer(vm)?.write(bytes) { Some(value) => Ok(vm.ctx.new_int(value)), @@ -656,7 +656,7 @@ mod fileio { fn file_io_init(file_io: PyObjectRef, args: FileIOArgs, vm: &VirtualMachine) -> PyResult { let mode = args .mode - .map(|mode| mode.as_str().to_owned()) + .map(|mode| mode.borrow_value().to_owned()) .unwrap_or_else(|| "r".to_owned()); let (name, file_no) = match args.name { Either::A(name) => { @@ -679,7 +679,7 @@ mod fileio { fd } else { os::open( - os::PyPathLike::new_str(name.as_str().to_owned()), + os::PyPathLike::new_str(name.borrow_value().to_owned()), mode as _, OptionalArg::Missing, OptionalArg::Missing, @@ -887,7 +887,7 @@ struct TextIOWrapperArgs { impl TextIOWrapperArgs { fn validate_newline(&self, vm: &VirtualMachine) -> PyResult<()> { if let Some(pystr) = &self.newline { - match pystr.as_str() { + match pystr.borrow_value() { "" | "\n" | "\r" | "\r\n" => Ok(()), _ => { Err(vm.new_value_error(format!("illegal newline value: '{}'", pystr.repr(vm)?))) @@ -915,7 +915,7 @@ fn text_io_wrapper_init( if let Some(self_encoding) = self_encoding { encoding = Some(PyString::from(self_encoding).into_ref(vm)); } else if let Some(ref encoding) = encoding { - self_encoding = Some(encoding.as_str()) + self_encoding = Some(encoding.borrow_value()) } else { return Err(vm.new_os_error("could not determine default encoding".to_owned())); } @@ -925,7 +925,7 @@ fn text_io_wrapper_init( .errors .map_or_else(|| vm.ctx.new_str("strict"), |o| o.into_object()); - // let readuniversal = args.newline.map_or_else(true, |s| s.as_str().is_empty()); + // let readuniversal = args.newline.map_or_else(true, |s| s.borrow_value().is_empty()); vm.set_attr( &instance, @@ -1017,7 +1017,7 @@ fn text_io_wrapper_write( return Err(vm.new_value_error("not writable".to_owned())); } - let bytes = obj.as_str().to_owned().into_bytes(); + let bytes = obj.borrow_value().to_owned().into_bytes(); let len = vm.call_method(&raw, "write", vec![vm.ctx.new_bytes(bytes.clone())])?; let len = objint::get_value(&len) @@ -1126,7 +1126,7 @@ fn io_open_wrapper( ) -> PyResult { io_open( file, - mode.as_ref().into_option().map(|s| s.as_str()), + mode.as_ref().into_option().map(|s| s.borrow_value()), opts, vm, ) diff --git a/vm/src/stdlib/json.rs b/vm/src/stdlib/json.rs index 57f6f6b38..deaa14287 100644 --- a/vm/src/stdlib/json.rs +++ b/vm/src/stdlib/json.rs @@ -1,7 +1,9 @@ use crate::obj::objiter; use crate::obj::objstr::PyStringRef; use crate::obj::{objbool, objtype::PyClassRef}; -use crate::pyobject::{IdProtocol, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue}; +use crate::pyobject::{ + BorrowValue, IdProtocol, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, +}; use crate::VirtualMachine; use num_bigint::BigInt; @@ -195,7 +197,7 @@ impl JsonScanner { return Err(vm.new_value_error("idx cannot be negative".to_owned())); } let idx = idx as usize; - let mut chars = pystr.as_str().chars(); + let mut chars = pystr.borrow_value().chars(); if idx > 0 { chars .nth(idx - 1) @@ -221,11 +223,11 @@ fn encode_string(s: &str, ascii_only: bool) -> String { } fn _json_encode_basestring(s: PyStringRef) -> String { - encode_string(s.as_str(), false) + encode_string(s.borrow_value(), false) } fn _json_encode_basestring_ascii(s: PyStringRef) -> String { - encode_string(s.as_str(), true) + encode_string(s.borrow_value(), true) } pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { diff --git a/vm/src/stdlib/keyword.rs b/vm/src/stdlib/keyword.rs index e22590ab4..1e3d49434 100644 --- a/vm/src/stdlib/keyword.rs +++ b/vm/src/stdlib/keyword.rs @@ -5,12 +5,12 @@ use rustpython_parser::lexer; use crate::obj::objstr::PyStringRef; -use crate::pyobject::{PyObjectRef, PyResult}; +use crate::pyobject::{BorrowValue, PyObjectRef, PyResult}; use crate::vm::VirtualMachine; fn keyword_iskeyword(s: PyStringRef, vm: &VirtualMachine) -> PyResult { let keywords = lexer::get_keywords(); - let value = keywords.contains_key(s.as_str()); + let value = keywords.contains_key(s.borrow_value()); let value = vm.ctx.new_bool(value); Ok(value) } diff --git a/vm/src/stdlib/msvcrt.rs b/vm/src/stdlib/msvcrt.rs index 563af38b5..fcd3aa064 100644 --- a/vm/src/stdlib/msvcrt.rs +++ b/vm/src/stdlib/msvcrt.rs @@ -1,103 +1,103 @@ -use super::os::errno_err; -use crate::obj::objbytes::PyBytesRef; -use crate::obj::objstr::PyStringRef; -use crate::pyobject::{PyObjectRef, PyResult}; -use crate::VirtualMachine; - -use itertools::Itertools; -use winapi::shared::minwindef::UINT; -use winapi::um::errhandlingapi::SetErrorMode; - -extern "C" { - fn _getch() -> i32; - fn _getwch() -> u32; - fn _getche() -> i32; - fn _getwche() -> u32; - fn _putch(c: u32) -> i32; - fn _putwch(c: u16) -> u32; -} - -fn msvcrt_getch() -> Vec { - let c = unsafe { _getch() }; - vec![c as u8] -} -fn msvcrt_getwch() -> String { - let c = unsafe { _getwch() }; - std::char::from_u32(c).unwrap().to_string() -} -fn msvcrt_getche() -> Vec { - let c = unsafe { _getche() }; - vec![c as u8] -} -fn msvcrt_getwche() -> String { - let c = unsafe { _getwche() }; - std::char::from_u32(c).unwrap().to_string() -} -fn msvcrt_putch(b: PyBytesRef, vm: &VirtualMachine) -> PyResult<()> { - let &c = b.borrow_value().iter().exactly_one().map_err(|_| { - vm.new_type_error("putch() argument must be a byte string of length 1".to_owned()) - })?; - unsafe { suppress_iph!(_putch(c.into())) }; - Ok(()) -} -fn msvcrt_putwch(s: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { - let c = s.as_str().chars().exactly_one().map_err(|_| { - vm.new_type_error("putch() argument must be a string of length 1".to_owned()) - })?; - unsafe { suppress_iph!(_putwch(c as u16)) }; - Ok(()) -} - -extern "C" { - fn _setmode(fd: i32, flags: i32) -> i32; -} - -fn msvcrt_setmode(fd: i32, flags: i32, vm: &VirtualMachine) -> PyResult { - let flags = unsafe { suppress_iph!(_setmode(fd, flags)) }; - if flags == -1 { - Err(errno_err(vm)) - } else { - Ok(flags) - } -} - -extern "C" { - fn _open_osfhandle(osfhandle: isize, flags: i32) -> i32; -} - -fn msvcrt_open_osfhandle(handle: isize, flags: i32, vm: &VirtualMachine) -> PyResult { - let ret = unsafe { suppress_iph!(_open_osfhandle(handle, flags)) }; - if ret == -1 { - Err(errno_err(vm)) - } else { - Ok(ret) - } -} - -fn msvcrt_seterrormode(mode: UINT, _: &VirtualMachine) -> UINT { - unsafe { suppress_iph!(SetErrorMode(mode)) } -} - -pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { - use winapi::um::winbase::{ - SEM_FAILCRITICALERRORS, SEM_NOALIGNMENTFAULTEXCEPT, SEM_NOGPFAULTERRORBOX, - SEM_NOOPENFILEERRORBOX, - }; - - let ctx = &vm.ctx; - py_module!(vm, "msvcrt", { - "getch" => ctx.new_function(msvcrt_getch), - "getwch" => ctx.new_function(msvcrt_getwch), - "getche" => ctx.new_function(msvcrt_getche), - "getwche" => ctx.new_function(msvcrt_getwche), - "putch" => ctx.new_function(msvcrt_putch), - "putwch" => ctx.new_function(msvcrt_putwch), - "setmode" => ctx.new_function(msvcrt_setmode), - "open_osfhandle" => ctx.new_function(msvcrt_open_osfhandle), - "SetErrorMode" => ctx.new_function(msvcrt_seterrormode), - "SEM_FAILCRITICALERRORS" => ctx.new_int(SEM_FAILCRITICALERRORS), - "SEM_NOALIGNMENTFAULTEXCEPT" => ctx.new_int(SEM_NOALIGNMENTFAULTEXCEPT), - "SEM_NOGPFAULTERRORBOX" => ctx.new_int(SEM_NOGPFAULTERRORBOX), - "SEM_NOOPENFILEERRORBOX" => ctx.new_int(SEM_NOOPENFILEERRORBOX), - }) -} +use super::os::errno_err; +use crate::obj::objbytes::PyBytesRef; +use crate::obj::objstr::PyStringRef; +use crate::pyobject::{BorrowValue, PyObjectRef, PyResult}; +use crate::VirtualMachine; + +use itertools::Itertools; +use winapi::shared::minwindef::UINT; +use winapi::um::errhandlingapi::SetErrorMode; + +extern "C" { + fn _getch() -> i32; + fn _getwch() -> u32; + fn _getche() -> i32; + fn _getwche() -> u32; + fn _putch(c: u32) -> i32; + fn _putwch(c: u16) -> u32; +} + +fn msvcrt_getch() -> Vec { + let c = unsafe { _getch() }; + vec![c as u8] +} +fn msvcrt_getwch() -> String { + let c = unsafe { _getwch() }; + std::char::from_u32(c).unwrap().to_string() +} +fn msvcrt_getche() -> Vec { + let c = unsafe { _getche() }; + vec![c as u8] +} +fn msvcrt_getwche() -> String { + let c = unsafe { _getwche() }; + std::char::from_u32(c).unwrap().to_string() +} +fn msvcrt_putch(b: PyBytesRef, vm: &VirtualMachine) -> PyResult<()> { + let &c = b.borrow_value().iter().exactly_one().map_err(|_| { + vm.new_type_error("putch() argument must be a byte string of length 1".to_owned()) + })?; + unsafe { suppress_iph!(_putch(c.into())) }; + Ok(()) +} +fn msvcrt_putwch(s: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { + let c = s.borrow_value().chars().exactly_one().map_err(|_| { + vm.new_type_error("putch() argument must be a string of length 1".to_owned()) + })?; + unsafe { suppress_iph!(_putwch(c as u16)) }; + Ok(()) +} + +extern "C" { + fn _setmode(fd: i32, flags: i32) -> i32; +} + +fn msvcrt_setmode(fd: i32, flags: i32, vm: &VirtualMachine) -> PyResult { + let flags = unsafe { suppress_iph!(_setmode(fd, flags)) }; + if flags == -1 { + Err(errno_err(vm)) + } else { + Ok(flags) + } +} + +extern "C" { + fn _open_osfhandle(osfhandle: isize, flags: i32) -> i32; +} + +fn msvcrt_open_osfhandle(handle: isize, flags: i32, vm: &VirtualMachine) -> PyResult { + let ret = unsafe { suppress_iph!(_open_osfhandle(handle, flags)) }; + if ret == -1 { + Err(errno_err(vm)) + } else { + Ok(ret) + } +} + +fn msvcrt_seterrormode(mode: UINT, _: &VirtualMachine) -> UINT { + unsafe { suppress_iph!(SetErrorMode(mode)) } +} + +pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { + use winapi::um::winbase::{ + SEM_FAILCRITICALERRORS, SEM_NOALIGNMENTFAULTEXCEPT, SEM_NOGPFAULTERRORBOX, + SEM_NOOPENFILEERRORBOX, + }; + + let ctx = &vm.ctx; + py_module!(vm, "msvcrt", { + "getch" => ctx.new_function(msvcrt_getch), + "getwch" => ctx.new_function(msvcrt_getwch), + "getche" => ctx.new_function(msvcrt_getche), + "getwche" => ctx.new_function(msvcrt_getwche), + "putch" => ctx.new_function(msvcrt_putch), + "putwch" => ctx.new_function(msvcrt_putwch), + "setmode" => ctx.new_function(msvcrt_setmode), + "open_osfhandle" => ctx.new_function(msvcrt_open_osfhandle), + "SetErrorMode" => ctx.new_function(msvcrt_seterrormode), + "SEM_FAILCRITICALERRORS" => ctx.new_int(SEM_FAILCRITICALERRORS), + "SEM_NOALIGNMENTFAULTEXCEPT" => ctx.new_int(SEM_NOALIGNMENTFAULTEXCEPT), + "SEM_NOGPFAULTERRORBOX" => ctx.new_int(SEM_NOGPFAULTERRORBOX), + "SEM_NOOPENFILEERRORBOX" => ctx.new_int(SEM_NOOPENFILEERRORBOX), + }) +} diff --git a/vm/src/stdlib/operator.rs b/vm/src/stdlib/operator.rs index b386892bf..72f04f665 100644 --- a/vm/src/stdlib/operator.rs +++ b/vm/src/stdlib/operator.rs @@ -2,7 +2,7 @@ use crate::byteslike::PyBytesLike; use crate::function::OptionalArg; use crate::obj::objstr::PyStringRef; use crate::obj::{objiter, objtype}; -use crate::pyobject::{Either, PyObjectRef, PyResult, TypeProtocol}; +use crate::pyobject::{BorrowValue, Either, PyObjectRef, PyResult, TypeProtocol}; use crate::VirtualMachine; use volatile::Volatile; @@ -76,12 +76,12 @@ fn operator_compare_digest( ) -> PyResult { let res = match (a, b) { (Either::A(a), Either::A(b)) => { - if !a.as_str().is_ascii() || !b.as_str().is_ascii() { + if !a.borrow_value().is_ascii() || !b.borrow_value().is_ascii() { return Err(vm.new_type_error( "comparing strings with non-ASCII characters is not supported".to_owned(), )); } - timing_safe_cmp(a.as_str().as_bytes(), b.as_str().as_bytes()) + timing_safe_cmp(a.borrow_value().as_bytes(), b.borrow_value().as_bytes()) } (Either::B(a), Either::B(b)) => a.with_ref(|a| b.with_ref(|b| timing_safe_cmp(a, b))), _ => { diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 954b0e77a..0ca4414a1 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -95,7 +95,7 @@ impl TryFromObject for PyPathLike { let match1 = |obj: &PyObjectRef| { let pathlike = match_class!(match obj { ref l @ PyString => PyPathLike { - path: l.as_str().into(), + path: l.borrow_value().into(), mode: OutputMode::String, }, ref i @ PyBytes => PyPathLike { @@ -320,7 +320,7 @@ mod _os { #[pyfunction] fn error(message: OptionalArg, vm: &VirtualMachine) -> PyResult { - let msg = message.map_or("".to_owned(), |msg| msg.as_str().to_owned()); + let msg = message.map_or("".to_owned(), |msg| msg.borrow_value().to_owned()); Err(vm.new_os_error(msg)) } @@ -379,7 +379,7 @@ mod _os { #[pyfunction] fn mkdirs(path: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { - fs::create_dir_all(path.as_str()).map_err(|err| err.into_pyexception(vm)) + fs::create_dir_all(path.borrow_value()).map_err(|err| err.into_pyexception(vm)) } #[pyfunction] @@ -407,11 +407,11 @@ mod _os { vm: &VirtualMachine, ) -> PyResult<()> { let key: &ffi::OsStr = match key { - Either::A(ref s) => s.as_str().as_ref(), + Either::A(ref s) => s.borrow_value().as_ref(), Either::B(ref b) => bytes_as_osstr(b.borrow_value(), vm)?, }; let value: &ffi::OsStr = match value { - Either::A(ref s) => s.as_str().as_ref(), + Either::A(ref s) => s.borrow_value().as_ref(), Either::B(ref b) => bytes_as_osstr(b.borrow_value(), vm)?, }; env::set_var(key, value); @@ -421,7 +421,7 @@ mod _os { #[pyfunction] fn unsetenv(key: Either, vm: &VirtualMachine) -> PyResult<()> { let key: &ffi::OsStr = match key { - Either::A(ref s) => s.as_str().as_ref(), + Either::A(ref s) => s.borrow_value().as_ref(), Either::B(ref b) => bytes_as_osstr(b.borrow_value(), vm)?, }; env::remove_var(key); @@ -1385,7 +1385,7 @@ mod posix { fn system(command: PyStringRef) -> PyResult { use std::ffi::CString; - let rstr = command.as_str(); + let rstr = command.borrow_value(); let cstr = CString::new(rstr).unwrap(); let x = unsafe { libc::system(cstr.as_ptr()) }; Ok(x) @@ -1416,7 +1416,7 @@ mod posix { argv_list: Either, vm: &VirtualMachine, ) -> PyResult<()> { - let path = ffi::CString::new(path.as_str()) + let path = ffi::CString::new(path.borrow_value()) .map_err(|_| vm.new_value_error("embedded null character".to_owned()))?; let argv: Vec = match argv_list { @@ -1716,7 +1716,7 @@ mod posix { ))] #[pyfunction] fn initgroups(user_name: PyStringRef, gid: u32, vm: &VirtualMachine) -> PyResult<()> { - let user = ffi::CString::new(user_name.as_str()).unwrap(); + let user = ffi::CString::new(user_name.borrow_value()).unwrap(); let gid = Gid::from_raw(gid); unistd::initgroups(&user, gid).map_err(|err| err.into_pyexception(vm)) } diff --git a/vm/src/stdlib/pwd.rs b/vm/src/stdlib/pwd.rs index f07b9fee4..891ff4b3a 100644 --- a/vm/src/stdlib/pwd.rs +++ b/vm/src/stdlib/pwd.rs @@ -44,7 +44,7 @@ impl From for Passwd { } fn pwd_getpwnam(name: PyStringRef, vm: &VirtualMachine) -> PyResult { - match User::from_name(name.as_str()).map_err(|err| err.into_pyexception(vm))? { + match User::from_name(name.borrow_value()).map_err(|err| err.into_pyexception(vm))? { Some(user) => Ok(Passwd::from(user) .into_struct_sequence(vm, vm.try_class("pwd", "struct_passwd")?)? .into_object()), diff --git a/vm/src/stdlib/pystruct.rs b/vm/src/stdlib/pystruct.rs index 48bf7e557..080f602e0 100644 --- a/vm/src/stdlib/pystruct.rs +++ b/vm/src/stdlib/pystruct.rs @@ -92,7 +92,7 @@ mod _struct { fmt: &Either, ) -> PyResult { let decoded_fmt = match fmt { - Either::A(string) => string.as_str(), + Either::A(string) => string.borrow_value(), Either::B(bytes) if bytes.is_ascii() => std::str::from_utf8(&bytes).unwrap(), _ => { return Err(vm.new_unicode_decode_error( diff --git a/vm/src/stdlib/re.rs b/vm/src/stdlib/re.rs index 2eabd8cac..76401c0c6 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.as_str(), flags)?; + let regex = make_regex(vm, pattern.borrow_value(), 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.as_str(), flags)?; + let regex = make_regex(vm, pattern.borrow_value(), flags)?; do_search(vm, ®ex, string) } @@ -121,7 +121,7 @@ fn re_sub( vm: &VirtualMachine, ) -> PyResult { let flags = extract_flags(flags); - let regex = make_regex(vm, pattern.as_str(), flags)?; + let regex = make_regex(vm, pattern.borrow_value(), flags)?; let limit = count.unwrap_or(0); do_sub(vm, ®ex, repl, string, limit) } @@ -133,7 +133,7 @@ fn re_findall( vm: &VirtualMachine, ) -> PyResult { let flags = extract_flags(flags); - let regex = make_regex(vm, pattern.as_str(), flags)?; + let regex = make_regex(vm, pattern.borrow_value(), flags)?; do_findall(vm, ®ex, string) } @@ -145,7 +145,7 @@ fn re_split( vm: &VirtualMachine, ) -> PyResult { let flags = extract_flags(flags); - let regex = make_regex(vm, pattern.as_str(), flags)?; + let regex = make_regex(vm, pattern.borrow_value(), flags)?; do_split(vm, ®ex, string, maxsplit.into_option()) } @@ -157,9 +157,9 @@ fn do_sub( limit: usize, ) -> PyResult { let out = pattern.regex.replacen( - search_text.as_str().as_bytes(), + search_text.borrow_value().as_bytes(), limit, - repl.as_str().as_bytes(), + repl.borrow_value().as_bytes(), ); let out = String::from_utf8_lossy(&out).into_owned(); Ok(vm.new_str(out)) @@ -171,14 +171,14 @@ fn do_match(vm: &VirtualMachine, pattern: &PyPattern, search_text: PyStringRef) regex.push_str(pattern.regex.as_str()); let regex = Regex::new(®ex).unwrap(); - match regex.captures(search_text.as_str().as_bytes()) { + match regex.captures(search_text.borrow_value().as_bytes()) { None => Ok(vm.get_none()), Some(captures) => Ok(create_match(vm, search_text.clone(), captures)), } } fn do_search(vm: &VirtualMachine, regex: &PyPattern, search_text: PyStringRef) -> PyResult { - match regex.regex.captures(search_text.as_str().as_bytes()) { + match regex.regex.captures(search_text.borrow_value().as_bytes()) { None => Ok(vm.get_none()), Some(captures) => Ok(create_match(vm, search_text.clone(), captures)), } @@ -187,7 +187,7 @@ fn do_search(vm: &VirtualMachine, regex: &PyPattern, search_text: PyStringRef) - fn do_findall(vm: &VirtualMachine, pattern: &PyPattern, search_text: PyStringRef) -> PyResult { let out = pattern .regex - .captures_iter(search_text.as_str().as_bytes()) + .captures_iter(search_text.borrow_value().as_bytes()) .map(|captures| match captures.len() { 1 => { let full = captures.get(0).unwrap().as_bytes(); @@ -233,7 +233,7 @@ fn do_split( .map(|i| usize::try_from_object(vm, i.into_object())) .transpose()? .unwrap_or(0); - let text = search_text.as_str().as_bytes(); + let text = search_text.borrow_value().as_bytes(); // essentially Regex::split, but it outputs captures as well let mut output = Vec::new(); let mut last = 0; @@ -309,11 +309,11 @@ fn re_compile( vm: &VirtualMachine, ) -> PyResult { let flags = extract_flags(flags); - make_regex(vm, pattern.as_str(), flags) + make_regex(vm, pattern.borrow_value(), flags) } fn re_escape(pattern: PyStringRef) -> String { - regex::escape(pattern.as_str()) + regex::escape(pattern.borrow_value()) } fn re_purge(_vm: &VirtualMachine) {} @@ -332,9 +332,10 @@ impl PyPattern { #[pymethod(name = "sub")] fn sub(&self, repl: PyStringRef, text: PyStringRef, vm: &VirtualMachine) -> PyResult { - let replaced_text = self - .regex - .replace_all(text.as_str().as_bytes(), repl.as_str().as_bytes()); + let replaced_text = self.regex.replace_all( + text.borrow_value().as_bytes(), + repl.borrow_value().as_bytes(), + ); let replaced_text = String::from_utf8_lossy(&replaced_text).into_owned(); Ok(vm.ctx.new_str(replaced_text)) } @@ -386,7 +387,7 @@ impl PyMatch { } fn subgroup(&self, bounds: (usize, usize), vm: &VirtualMachine) -> PyObjectRef { - vm.new_str(self.haystack.as_str()[bounds.0..bounds.1].to_owned()) + vm.new_str(self.haystack.borrow_value()[bounds.0..bounds.1].to_owned()) } fn get_bounds(&self, id: PyObjectRef, vm: &VirtualMachine) -> PyResult> { diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 4c2fa8cec..a18b22c9a 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -19,7 +19,8 @@ use crate::obj::objstr::{PyString, PyStringRef}; use crate::obj::objtuple::PyTupleRef; use crate::obj::objtype::PyClassRef; use crate::pyobject::{ - Either, IntoPyObject, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, + BorrowValue, Either, IntoPyObject, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, + TryFromObject, }; use crate::vm::VirtualMachine; @@ -434,7 +435,7 @@ struct Address { impl ToSocketAddrs for Address { type Iter = std::vec::IntoIter; fn to_socket_addrs(&self) -> io::Result { - (self.host.as_str(), self.port).to_socket_addrs() + (self.host.borrow_value(), self.port).to_socket_addrs() } } @@ -445,7 +446,7 @@ impl TryFromObject for Address { Err(vm.new_type_error("Address tuple should have only 2 values".to_owned())) } else { let host = PyStringRef::try_from_object(vm, tuple.as_slice()[0].clone())?; - let host = if host.as_str().is_empty() { + let host = if host.borrow_value().is_empty() { PyString::from("0.0.0.0").into_ref(vm) } else { host @@ -478,12 +479,12 @@ fn socket_gethostname(vm: &VirtualMachine) -> PyResult { #[cfg(all(unix, not(target_os = "redox")))] fn socket_sethostname(hostname: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { - sethostname(hostname.as_str()).map_err(|err| err.into_pyexception(vm)) + sethostname(hostname.borrow_value()).map_err(|err| err.into_pyexception(vm)) } fn socket_inet_aton(ip_string: PyStringRef, vm: &VirtualMachine) -> PyResult { ip_string - .as_str() + .borrow_value() .parse::() .map(|ip_addr| vm.ctx.new_bytes(ip_addr.octets().to_vec())) .map_err(|_| vm.new_os_error("illegal IP address string passed to inet_aton".to_owned())) @@ -523,10 +524,10 @@ fn socket_getaddrinfo(opts: GAIOptions, vm: &VirtualMachine) -> PyResult { flags: opts.flags, }; - let host = opts.host.as_ref().map(|s| s.as_str()); + let host = opts.host.as_ref().map(|s| s.borrow_value()); let port = opts.port.as_ref().map(|p| -> std::borrow::Cow { match p { - Either::A(ref s) => s.as_str().into(), + Either::A(ref s) => s.borrow_value().into(), Either::B(i) => i.to_string().into(), } }); @@ -563,7 +564,7 @@ fn socket_gethostbyaddr( vm: &VirtualMachine, ) -> PyResult<(String, PyObjectRef, PyObjectRef)> { // TODO: figure out how to do this properly - let ai = dns_lookup::getaddrinfo(Some(addr.as_str()), None, None) + let ai = dns_lookup::getaddrinfo(Some(addr.borrow_value()), None, None) .map_err(|e| convert_sock_error(vm, e.into()))? .next() .unwrap() diff --git a/vm/src/stdlib/ssl.rs b/vm/src/stdlib/ssl.rs index a86506102..c977e5865 100644 --- a/vm/src/stdlib/ssl.rs +++ b/vm/src/stdlib/ssl.rs @@ -7,7 +7,8 @@ use crate::obj::objbytearray::PyByteArrayRef; use crate::obj::objstr::PyStringRef; use crate::obj::{objtype::PyClassRef, objweakref::PyWeak}; use crate::pyobject::{ - Either, IntoPyObject, ItemProtocol, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, + BorrowValue, Either, IntoPyObject, ItemProtocol, PyClassImpl, PyObjectRef, PyRef, PyResult, + PyValue, }; use crate::types::create_type; use crate::VirtualMachine; @@ -120,7 +121,7 @@ fn ssl_enum_certificates(store_name: PyStringRef, vm: &VirtualMachine) -> PyResu let open_fns = [CertStore::open_current_user, CertStore::open_local_machine]; let stores = open_fns .iter() - .filter_map(|open| open(store_name.as_str()).ok()) + .filter_map(|open| open(store_name.borrow_value()).ok()) .collect::>(); let certs = stores.iter().map(|s| s.certs()).flatten().map(|c| { let cert = vm.ctx.new_bytes(c.to_der().to_owned()); @@ -200,7 +201,7 @@ fn ssl_rand_add(string: Either, entropy: f64) { } }; match string { - Either::A(s) => f(s.as_str().as_bytes()), + Either::A(s) => f(s.borrow_value().as_bytes()), Either::B(b) => b.with_ref(f), } } @@ -315,7 +316,7 @@ impl PySslContext { #[pymethod] fn set_ciphers(&self, cipherlist: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { - let ciphers = cipherlist.as_str(); + let ciphers = cipherlist.borrow_value(); if ciphers.contains('\0') { return Err(vm.new_value_error("embedded null character".to_owned())); } @@ -378,10 +379,10 @@ impl PySslContext { if let Some(cadata) = args.cadata { let cert = match cadata { Either::A(s) => { - if !s.as_str().is_ascii() { + if !s.borrow_value().is_ascii() { return Err(vm.new_type_error("Must be an ascii string".to_owned())); } - X509::from_pem(s.as_str().as_bytes()) + X509::from_pem(s.borrow_value().as_bytes()) } Either::B(b) => b.with_ref(X509::from_der), }; diff --git a/vm/src/stdlib/string.rs b/vm/src/stdlib/string.rs index 6b9314c38..688851202 100644 --- a/vm/src/stdlib/string.rs +++ b/vm/src/stdlib/string.rs @@ -13,7 +13,7 @@ mod _string { }; use crate::obj::objlist::PyList; use crate::obj::objstr::PyStringRef; - use crate::pyobject::{IntoPyObject, PyObjectRef, PyResult}; + use crate::pyobject::{BorrowValue, IntoPyObject, PyObjectRef, PyResult}; use crate::vm::VirtualMachine; fn create_format_part( @@ -35,7 +35,7 @@ mod _string { #[pyfunction] fn formatter_parser(text: PyStringRef, vm: &VirtualMachine) -> PyResult { let format_string = - FormatString::from_str(text.as_str()).map_err(|e| e.into_pyexception(vm))?; + FormatString::from_str(text.borrow_value()).map_err(|e| e.into_pyexception(vm))?; let mut result = Vec::new(); let mut literal = String::new(); @@ -74,7 +74,8 @@ mod _string { text: PyStringRef, vm: &VirtualMachine, ) -> PyResult<(PyObjectRef, PyList)> { - let field_name = FieldName::parse(text.as_str()).map_err(|e| e.into_pyexception(vm))?; + let field_name = + FieldName::parse(text.borrow_value()).map_err(|e| e.into_pyexception(vm))?; let first = match field_name.field_type { FieldType::Auto => vm.new_str("".to_owned()), diff --git a/vm/src/stdlib/symtable.rs b/vm/src/stdlib/symtable.rs index 2172f974c..6001a775d 100644 --- a/vm/src/stdlib/symtable.rs +++ b/vm/src/stdlib/symtable.rs @@ -5,7 +5,7 @@ use rustpython_parser::parser; use crate::obj::objstr::PyStringRef; use crate::obj::objtype::PyClassRef; -use crate::pyobject::{PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue}; +use crate::pyobject::{BorrowValue, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { @@ -30,11 +30,11 @@ fn symtable_symtable( vm: &VirtualMachine, ) -> PyResult { let mode = mode - .as_str() + .borrow_value() .parse::() .map_err(|err| vm.new_value_error(err.to_string()))?; - let symtable = source_to_symtable(source.as_str(), mode, filename.as_str()) + let symtable = source_to_symtable(source.borrow_value(), mode, filename.borrow_value()) .map_err(|err| vm.new_syntax_error(&err))?; let py_symbol_table = to_py_symbol_table(symtable); @@ -105,7 +105,7 @@ impl PySymbolTable { #[pymethod(name = "lookup")] fn lookup(&self, name: PyStringRef, vm: &VirtualMachine) -> PyResult { - let name = name.as_str(); + let name = name.borrow_value(); if let Some(symbol) = self.symtable.symbols.get(name) { Ok(PySymbol { symbol: symbol.clone(), diff --git a/vm/src/stdlib/thread.rs b/vm/src/stdlib/thread.rs index 7d21b7e4f..93b0db7b5 100644 --- a/vm/src/stdlib/thread.rs +++ b/vm/src/stdlib/thread.rs @@ -6,8 +6,8 @@ use crate::obj::objstr::PyStringRef; use crate::obj::objtuple::PyTupleRef; use crate::obj::objtype::PyClassRef; use crate::pyobject::{ - Either, IdProtocol, ItemProtocol, PyCallable, PyClassImpl, PyObjectRef, PyRef, PyResult, - PyValue, TypeProtocol, + BorrowValue, Either, IdProtocol, ItemProtocol, PyCallable, PyClassImpl, PyObjectRef, PyRef, + PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -238,7 +238,7 @@ fn thread_start_new_thread( let repr = vm.to_repr(&func.into_object()).ok(); let repr = repr .as_ref() - .map_or("", |s| s.as_str()); + .map_or("", |s| s.borrow_value()); writeln!(stderr, "Exception ignored in thread started by: {}", repr) .and_then(|()| exceptions::write_exception(&mut stderr, vm, &exc)) .ok(); @@ -306,7 +306,7 @@ impl PyLocal { #[pymethod(magic)] fn getattribute(zelf: PyRef, attr: PyStringRef, vm: &VirtualMachine) -> PyResult { let ldict = zelf.ldict(vm); - if attr.as_str() == "__dict__" { + if attr.borrow_value() == "__dict__" { Ok(ldict.into_object()) } else { let zelf = zelf.into_object(); @@ -324,7 +324,7 @@ impl PyLocal { value: PyObjectRef, vm: &VirtualMachine, ) -> PyResult<()> { - if attr.as_str() == "__dict__" { + if attr.borrow_value() == "__dict__" { Err(vm.new_attribute_error(format!( "{} attribute '__dict__' is read-only", zelf.as_object() @@ -337,7 +337,7 @@ impl PyLocal { #[pymethod(magic)] fn delattr(zelf: PyRef, attr: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { - if attr.as_str() == "__dict__" { + if attr.borrow_value() == "__dict__" { Err(vm.new_attribute_error(format!( "{} attribute '__dict__' is read-only", zelf.as_object() diff --git a/vm/src/stdlib/time_module.rs b/vm/src/stdlib/time_module.rs index 41bc17b91..936be534e 100644 --- a/vm/src/stdlib/time_module.rs +++ b/vm/src/stdlib/time_module.rs @@ -11,7 +11,7 @@ use crate::function::OptionalArg; use crate::obj::objstr::PyStringRef; use crate::obj::objtuple::PyTupleRef; use crate::obj::objtype::PyClassRef; -use crate::pyobject::{Either, PyClassImpl, PyObjectRef, PyResult, TryFromObject}; +use crate::pyobject::{BorrowValue, Either, PyClassImpl, PyObjectRef, PyResult, TryFromObject}; use crate::vm::VirtualMachine; #[cfg(unix)] @@ -152,7 +152,7 @@ fn time_strftime( OptionalArg::Present(t) => t.to_date_time(vm)?, OptionalArg::Missing => default, }; - let formatted_time = instant.format(format.as_str()).to_string(); + let formatted_time = instant.format(format.borrow_value()).to_string(); Ok(vm.ctx.new_str(formatted_time)) } @@ -162,10 +162,10 @@ fn time_strptime( vm: &VirtualMachine, ) -> PyResult { let format = match format { - OptionalArg::Present(ref format) => format.as_str(), + OptionalArg::Present(ref format) => format.borrow_value(), OptionalArg::Missing => "%a %b %H:%M:%S %Y", }; - let instant = NaiveDateTime::parse_from_str(string.as_str(), format) + let instant = NaiveDateTime::parse_from_str(string.borrow_value(), format) .map_err(|e| vm.new_value_error(format!("Parse error: {:?}", e)))?; Ok(PyStructTime::new(vm, instant, -1).into_obj(vm)) } diff --git a/vm/src/stdlib/tokenize.rs b/vm/src/stdlib/tokenize.rs index 0440d32b4..a6f255b58 100644 --- a/vm/src/stdlib/tokenize.rs +++ b/vm/src/stdlib/tokenize.rs @@ -4,14 +4,13 @@ use std::iter::FromIterator; +use crate::obj::objstr::PyStringRef; +use crate::pyobject::{BorrowValue, PyObjectRef, PyResult}; +use crate::vm::VirtualMachine; use rustpython_parser::lexer; -use crate::obj::objstr::PyStringRef; -use crate::pyobject::{PyObjectRef, PyResult}; -use crate::vm::VirtualMachine; - fn tokenize_tokenize(s: PyStringRef, vm: &VirtualMachine) -> PyResult { - let source = s.as_str(); + let source = s.borrow_value(); // TODO: implement generator when the time has come. let lexer1 = lexer::make_tokenizer(source); diff --git a/vm/src/stdlib/unicodedata.rs b/vm/src/stdlib/unicodedata.rs index 84d60663f..a7dcba9d2 100644 --- a/vm/src/stdlib/unicodedata.rs +++ b/vm/src/stdlib/unicodedata.rs @@ -5,7 +5,7 @@ use crate::function::OptionalArg; use crate::obj::objstr::PyStringRef; use crate::obj::objtype::PyClassRef; -use crate::pyobject::{PyClassImpl, PyObject, PyObjectRef, PyResult, PyValue}; +use crate::pyobject::{BorrowValue, PyClassImpl, PyObject, PyObjectRef, PyResult, PyValue}; use crate::vm::VirtualMachine; use itertools::Itertools; @@ -82,9 +82,13 @@ impl PyUCD { } fn extract_char(&self, character: PyStringRef, vm: &VirtualMachine) -> PyResult> { - let c = character.as_str().chars().exactly_one().map_err(|_| { - vm.new_type_error("argument must be an unicode character, not str".to_owned()) - })?; + let c = character + .borrow_value() + .chars() + .exactly_one() + .map_err(|_| { + vm.new_type_error("argument must be an unicode character, not str".to_owned()) + })?; if self.check_age(c) { Ok(Some(c)) @@ -104,7 +108,7 @@ impl PyUCD { #[pymethod] fn lookup(&self, name: PyStringRef, vm: &VirtualMachine) -> PyResult { - if let Some(character) = unicode_names2::character(name.as_str()) { + if let Some(character) = unicode_names2::character(name.borrow_value()) { if self.check_age(character) { return Ok(character.to_string()); } @@ -150,8 +154,8 @@ impl PyUCD { unistr: PyStringRef, vm: &VirtualMachine, ) -> PyResult { - let text = unistr.as_str(); - let normalized_text = match form.as_str() { + let text = unistr.borrow_value(); + let normalized_text = match form.borrow_value() { "NFC" => text.nfc().collect::(), "NFKC" => text.nfkc().collect::(), "NFD" => text.nfd().collect::(), diff --git a/vm/src/stdlib/winapi.rs b/vm/src/stdlib/winapi.rs index 4ba177654..76918d237 100644 --- a/vm/src/stdlib/winapi.rs +++ b/vm/src/stdlib/winapi.rs @@ -13,7 +13,7 @@ use super::os::errno_err; use crate::function::OptionalArg; use crate::obj::objdict::{PyDictRef, PyMapping}; use crate::obj::objstr::PyStringRef; -use crate::pyobject::{PyObjectRef, PyResult, PySequence, TryFromObject}; +use crate::pyobject::{BorrowValue, PyObjectRef, PyResult, PySequence, TryFromObject}; use crate::VirtualMachine; fn GetLastError() -> u32 { @@ -170,10 +170,10 @@ fn _winapi_CreateProcess( .map_or_else(null_mut, |l| l.attrlist.as_mut_ptr() as _); let wstr = |s: PyStringRef| { - if s.as_str().contains('\0') { + if s.borrow_value().contains('\0') { Err(vm.new_value_error("embedded null character".to_owned())) } else { - Ok(s.as_str() + Ok(s.borrow_value() .encode_utf16() .chain(std::iter::once(0)) .collect::>()) @@ -227,9 +227,9 @@ fn getenvironment(env: PyDictRef, vm: &VirtualMachine) -> PyResult> { let mut out = vec![]; for (k, v) in env { let k = PyStringRef::try_from_object(vm, k)?; - let k = k.as_str(); + let k = k.borrow_value(); let v = PyStringRef::try_from_object(vm, v)?; - let v = v.as_str(); + let v = v.borrow_value(); if k.contains('\0') || v.contains('\0') { return Err(vm.new_value_error("embedded null character".to_owned())); } diff --git a/vm/src/stdlib/winreg.rs b/vm/src/stdlib/winreg.rs index 79c3098ea..619b5e938 100644 --- a/vm/src/stdlib/winreg.rs +++ b/vm/src/stdlib/winreg.rs @@ -4,7 +4,9 @@ use crate::exceptions::IntoPyException; use crate::function::OptionalArg; use crate::obj::objstr::PyStringRef; use crate::obj::objtype::PyClassRef; -use crate::pyobject::{PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject}; +use crate::pyobject::{ + BorrowValue, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, +}; use crate::VirtualMachine; use std::convert::TryInto; @@ -112,7 +114,7 @@ fn winreg_OpenKey( return Err(vm.new_value_error("reserved param must be 0".to_owned())); } - let subkey = subkey.as_ref().map_or("", |s| s.as_str()); + let subkey = subkey.as_ref().map_or("", |s| s.borrow_value()); let key = key .with_key(|k| k.open_subkey_with_flags(subkey, access)) .map_err(|e| e.into_pyexception(vm))?; @@ -125,7 +127,7 @@ fn winreg_QueryValue( subkey: Option, vm: &VirtualMachine, ) -> PyResult { - let subkey = subkey.as_ref().map_or("", |s| s.as_str()); + let subkey = subkey.as_ref().map_or("", |s| s.borrow_value()); key.with_key(|k| k.get_value(subkey)) .map_err(|e| e.into_pyexception(vm)) } @@ -135,7 +137,7 @@ fn winreg_QueryValueEx( subkey: Option, vm: &VirtualMachine, ) -> PyResult<(PyObjectRef, usize)> { - let subkey = subkey.as_ref().map_or("", |s| s.as_str()); + let subkey = subkey.as_ref().map_or("", |s| s.borrow_value()); key.with_key(|k| k.get_raw_value(subkey)) .map_err(|e| e.into_pyexception(vm)) .and_then(|regval| { diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 11a681922..d3e9b5ae6 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -40,8 +40,8 @@ use crate::obj::objstr::{PyString, PyStringRef}; use crate::obj::objtuple::PyTuple; use crate::obj::objtype::{self, PyClassRef}; use crate::pyobject::{ - IdProtocol, ItemProtocol, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, - TryFromObject, TryIntoRef, TypeProtocol, BorrowValue + BorrowValue, IdProtocol, ItemProtocol, PyContext, PyObject, PyObjectRef, PyRef, PyResult, + PyValue, TryFromObject, TryIntoRef, TypeProtocol, }; use crate::scope::Scope; use crate::stdlib; @@ -655,7 +655,7 @@ impl VirtualMachine { pub fn to_pystr<'a, T: Into<&'a PyObjectRef>>(&'a self, obj: T) -> PyResult { let py_str_obj = self.to_str(obj.into())?; - Ok(py_str_obj.as_str().to_owned()) + Ok(py_str_obj.borrow_value().to_owned()) } pub fn to_repr(&self, obj: &PyObjectRef) -> PyResult { @@ -666,7 +666,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.as_str()); + let ascii = to_ascii(repr.borrow_value()); Ok(self.new_str(ascii)) } @@ -1023,7 +1023,7 @@ impl VirtualMachine { name_str: PyStringRef, dict: Option, ) -> PyResult> { - let name = name_str.as_str(); + let name = name_str.borrow_value(); let cls = obj.class(); if let Some(attr) = cls.get_attr(&name) { @@ -1037,7 +1037,7 @@ impl VirtualMachine { let dict = dict.or_else(|| obj.dict()); let attr = if let Some(dict) = dict { - dict.get_item_option(name_str.as_str(), self)? + dict.get_item_option(name, self)? } else { None }; diff --git a/wasm/lib/src/browser_module.rs b/wasm/lib/src/browser_module.rs index d3b14fa20..2ace9387b 100644 --- a/wasm/lib/src/browser_module.rs +++ b/wasm/lib/src/browser_module.rs @@ -9,7 +9,7 @@ use rustpython_vm::function::{OptionalArg, PyFuncArgs}; use rustpython_vm::import::import_file; use rustpython_vm::obj::{objdict::PyDictRef, objstr::PyStringRef, objtype::PyClassRef}; use rustpython_vm::pyobject::{ - PyCallable, PyClassImpl, PyObject, PyObjectRef, PyRef, PyResult, PyValue, + BorrowValue, PyCallable, PyClassImpl, PyObject, PyObjectRef, PyRef, PyResult, PyValue, }; use rustpython_vm::VirtualMachine; @@ -71,14 +71,14 @@ fn browser_fetch(url: PyStringRef, args: FetchArgs, vm: &VirtualMachine) -> PyRe } = args; let response_format = match response_format { - Some(s) => FetchResponseFormat::from_str(vm, s.as_str())?, + Some(s) => FetchResponseFormat::from_str(vm, s.borrow_value())?, None => FetchResponseFormat::Text, }; let mut opts = web_sys::RequestInit::new(); match method { - Some(s) => opts.method(s.as_str()), + Some(s) => opts.method(s.borrow_value()), None => opts.method("GET"), }; @@ -86,7 +86,7 @@ fn browser_fetch(url: PyStringRef, args: FetchArgs, vm: &VirtualMachine) -> PyRe opts.body(Some(&convert::py_to_js(vm, body))); } - let request = web_sys::Request::new_with_str_and_init(url.as_str(), &opts) + let request = web_sys::Request::new_with_str_and_init(url.borrow_value(), &opts) .map_err(|err| convert::js_py_typeerror(vm, err))?; if let Some(headers) = headers { @@ -94,7 +94,7 @@ fn browser_fetch(url: PyStringRef, args: FetchArgs, vm: &VirtualMachine) -> PyRe for (key, value) in headers { let key = vm.to_str(&key)?; let value = vm.to_str(&value)?; - h.set(key.as_str(), value.as_str()) + h.set(key.borrow_value(), value.borrow_value()) .map_err(|err| convert::js_py_typeerror(vm, err))?; } } @@ -102,7 +102,7 @@ fn browser_fetch(url: PyStringRef, args: FetchArgs, vm: &VirtualMachine) -> PyRe if let Some(content_type) = content_type { request .headers() - .set("Content-Type", content_type.as_str()) + .set("Content-Type", content_type.borrow_value()) .map_err(|err| convert::js_py_typeerror(vm, err))?; } @@ -266,7 +266,7 @@ impl Document { fn query(&self, query: PyStringRef, vm: &VirtualMachine) -> PyResult { let elem = self .doc - .query_selector(query.as_str()) + .query_selector(query.borrow_value()) .map_err(|err| convert::js_py_typeerror(vm, err))?; let elem = match elem { Some(elem) => Element { elem }.into_ref(vm).into_object(), @@ -297,7 +297,7 @@ impl Element { default: OptionalArg, vm: &VirtualMachine, ) -> PyObjectRef { - match self.elem.get_attribute(attr.as_str()) { + match self.elem.get_attribute(attr.borrow_value()) { Some(s) => vm.new_str(s), None => default.into_option().unwrap_or_else(|| vm.get_none()), } @@ -306,7 +306,7 @@ impl Element { #[pymethod] fn set_attr(&self, attr: PyStringRef, value: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { self.elem - .set_attribute(attr.as_str(), value.as_str()) + .set_attribute(attr.borrow_value(), value.borrow_value()) .map_err(|err| convert::js_py_typeerror(vm, err)) } } @@ -317,7 +317,7 @@ fn browser_load_module(module: PyStringRef, path: PyStringRef, vm: &VirtualMachi let mut opts = web_sys::RequestInit::new(); opts.method("GET"); - let request = web_sys::Request::new_with_str_and_init(path.as_str(), &opts) + let request = web_sys::Request::new_with_str_and_init(path.borrow_value(), &opts) .map_err(|err| convert::js_py_typeerror(vm, err))?; let window = window(); @@ -337,7 +337,7 @@ fn browser_load_module(module: PyStringRef, path: PyStringRef, vm: &VirtualMachi .expect("that the vm is valid when the promise resolves"); let vm = &stored_vm.vm; let resp_text = text.as_string().unwrap(); - let res = import_file(vm, module.as_str(), "WEB".to_owned(), resp_text); + let res = import_file(vm, module.borrow_value(), "WEB".to_owned(), resp_text); match res { Ok(_) => Ok(JsValue::null()), Err(err) => Err(convert::py_err_to_js_err(vm, &err)), diff --git a/wasm/lib/src/js_module.rs b/wasm/lib/src/js_module.rs index d84a8cadd..9651296f3 100644 --- a/wasm/lib/src/js_module.rs +++ b/wasm/lib/src/js_module.rs @@ -3,7 +3,9 @@ use rustpython_vm::common::rc::PyRc; use rustpython_vm::exceptions::PyBaseExceptionRef; use rustpython_vm::function::Args; use rustpython_vm::obj::{objfloat::PyFloatRef, objstr::PyStringRef, objtype::PyClassRef}; -use rustpython_vm::pyobject::{PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject}; +use rustpython_vm::pyobject::{ + BorrowValue, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, +}; use rustpython_vm::types::create_type; use rustpython_vm::VirtualMachine; use wasm_bindgen::{prelude::*, JsCast}; @@ -61,7 +63,7 @@ impl TryFromObject for JsProperty { impl JsProperty { fn into_jsvalue(self) -> JsValue { match self { - JsProperty::Str(s) => s.as_str().into(), + JsProperty::Str(s) => s.borrow_value().into(), JsProperty::Js(value) => value.value.clone(), } } @@ -88,7 +90,7 @@ impl PyJsValue { #[pymethod] fn new_from_str(&self, s: PyStringRef) -> PyJsValue { - PyJsValue::new(s.as_str()) + PyJsValue::new(s.borrow_value()) } #[pymethod] diff --git a/wasm/lib/src/wasm_builtins.rs b/wasm/lib/src/wasm_builtins.rs index 5b0b9fd6e..fd565d0df 100644 --- a/wasm/lib/src/wasm_builtins.rs +++ b/wasm/lib/src/wasm_builtins.rs @@ -7,7 +7,7 @@ use web_sys::{self, console}; use rustpython_vm::obj::objstr::PyStringRef; -use rustpython_vm::pyobject::{PyObjectRef, PyResult}; +use rustpython_vm::pyobject::{BorrowValue, PyObjectRef, PyResult}; use rustpython_vm::VirtualMachine; pub(crate) fn window() -> web_sys::Window { @@ -26,7 +26,7 @@ pub fn make_stdout_object( let ctx = &vm.ctx; let write_method = ctx.new_method( move |_self: PyObjectRef, data: PyStringRef, vm: &VirtualMachine| -> PyResult<()> { - write_f(data.as_str(), vm) + write_f(data.borrow_value(), vm) }, ); let flush_method = ctx.new_method(|_self: PyObjectRef| {});