Add a lazily calculated hash field to PyString

This commit is contained in:
Noah
2019-09-19 15:58:15 +00:00
parent 59d4e4e7c1
commit 54cfb71d74
3 changed files with 23 additions and 14 deletions

View File

@@ -250,12 +250,9 @@ fn builtin_format(
format_spec: OptionalArg<PyStringRef>,
vm: &VirtualMachine,
) -> PyResult<PyStringRef> {
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()

View File

@@ -54,6 +54,7 @@ use unicode_categories::UnicodeCategories;
pub struct PyString {
// TODO: shouldn't be public
pub value: String,
hash: Cell<Option<pyhash::PyHash>>,
}
impl PyString {
@@ -64,8 +65,15 @@ impl PyString {
impl From<&str> for PyString {
fn from(s: &str) -> PyString {
s.to_string().into()
}
}
impl From<String> 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<PyString> for String {
fn try_into_ref(self, vm: &VirtualMachine) -> PyResult<PyRef<PyString>> {
Ok(PyString { value: self }.into_ref(vm))
Ok(PyString::from(self).into_ref(vm))
}
}
impl TryIntoRef<PyString> for &str {
fn try_into_ref(self, vm: &VirtualMachine) -> PyResult<PyRef<PyString>> {
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__")]

View File

@@ -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<u8>) -> PyObjectRef {