mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
PyInterned
This commit is contained in:
1 parent
370b2b3f99
commit
bbc31364bb
7 files changed
+93
-77
No files matched your search
+1
-1
@@ -683,7 +683,7 @@ mod array {
|
||||
fn typecode(&self, vm: &VirtualMachine) -> PyStrRef {
|
||||
vm.ctx
|
||||
.intern_str(self.read().typecode().to_string())
|
||||
.to_str()
|
||||
.to_owned()
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
|
||||
@@ -117,7 +117,6 @@ impl PyBool {
|
||||
vm.ctx.false_str
|
||||
}
|
||||
.to_owned()
|
||||
.into_pyref()
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
|
||||
@@ -104,7 +104,7 @@ impl ConstantBag for PyObjBag<'_> {
|
||||
}
|
||||
|
||||
fn make_name(&self, name: &str) -> PyStrRef {
|
||||
self.0.intern_str(name).to_str()
|
||||
self.0.intern_str(name).to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@ impl IntoPyStrRef for &str {
|
||||
impl IntoPyStrRef for &'static crate::intern::PyStrInterned {
|
||||
#[inline]
|
||||
fn into_pystr_ref(self, _vm: &VirtualMachine) -> PyRef<PyStr> {
|
||||
self.to_str()
|
||||
self.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+86
-68
@@ -2,7 +2,7 @@ use crate::{
|
||||
builtins::{PyStr, PyTypeRef},
|
||||
common::lock::PyRwLock,
|
||||
convert::ToPyObject,
|
||||
AsObject, Py, PyExact, PyObject, PyObjectRef, PyRef, PyRefExact,
|
||||
AsObject, Py, PyExact, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, VirtualMachine,
|
||||
};
|
||||
use std::{
|
||||
borrow::{Borrow, ToOwned},
|
||||
@@ -113,11 +113,84 @@ impl CachedPyStrRef {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PyInterned<T>
|
||||
where
|
||||
T: PyPayload,
|
||||
{
|
||||
inner: Py<T>,
|
||||
}
|
||||
|
||||
impl<T: PyPayload> PyInterned<T> {
|
||||
#[inline]
|
||||
pub fn leak(cache: PyRef<T>) -> &'static Self {
|
||||
unsafe { std::mem::transmute(cache) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *const Py<T> {
|
||||
self as *const _ as *const _
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_owned(&'static self) -> PyRef<T> {
|
||||
unsafe { (*(&self as *const _ as *const PyRef<T>)).clone() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_object(&'static self) -> PyObjectRef {
|
||||
self.to_owned().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyPayload> Borrow<PyObject> for PyInterned<T> {
|
||||
#[inline(always)]
|
||||
fn borrow(&self) -> &PyObject {
|
||||
self.inner.borrow()
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: std::hash::Hash of Self and Self::Borrowed *must* be the same
|
||||
// This is ok only because PyObject doesn't implement Hash
|
||||
impl<T: PyPayload> std::hash::Hash for PyInterned<T> {
|
||||
#[inline(always)]
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.get_id().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyPayload> Deref for PyInterned<T> {
|
||||
type Target = Py<T>;
|
||||
#[inline(always)]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyPayload> PartialEq for PyInterned<T> {
|
||||
#[inline(always)]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
std::ptr::eq(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyPayload> Eq for PyInterned<T> {}
|
||||
|
||||
impl<T: PyPayload + std::fmt::Debug> std::fmt::Debug for PyInterned<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
std::fmt::Debug::fmt(&**self, f)?;
|
||||
write!(f, "@{:p}", self.as_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyPayload> ToPyObject for &'static PyInterned<T> {
|
||||
fn to_pyobject(self, _vm: &VirtualMachine) -> PyObjectRef {
|
||||
self.to_owned().into()
|
||||
}
|
||||
}
|
||||
|
||||
/// The unique reference of interned PyStr
|
||||
/// Always intended to be used as a static reference
|
||||
pub struct PyStrInterned {
|
||||
inner: Py<PyStr>,
|
||||
}
|
||||
pub type PyStrInterned = PyInterned<PyStr>;
|
||||
|
||||
impl PyStrInterned {
|
||||
/// # Safety
|
||||
@@ -128,70 +201,8 @@ impl PyStrInterned {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *const Py<PyStr> {
|
||||
self as *const _ as *const _
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_owned(&'static self) -> PyRefExact<PyStr> {
|
||||
unsafe { (*(&self as *const _ as *const PyRefExact<PyStr>)).clone() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_str(&'static self) -> PyRef<PyStr> {
|
||||
self.to_owned().into_pyref()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_object(&'static self) -> PyObjectRef {
|
||||
self.to_str().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<PyObject> for PyStrInterned {
|
||||
#[inline(always)]
|
||||
fn borrow(&self) -> &PyObject {
|
||||
self.inner.borrow()
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: std::hash::Hash of Self and Self::Borrowed *must* be the same
|
||||
// This is ok only because PyObject doesn't implement Hash
|
||||
impl std::hash::Hash for PyStrInterned {
|
||||
#[inline(always)]
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.get_id().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for PyStrInterned {
|
||||
type Target = Py<PyStr>;
|
||||
#[inline(always)]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for PyStrInterned {
|
||||
#[inline(always)]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
std::ptr::eq(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for PyStrInterned {}
|
||||
|
||||
impl AsRef<str> for PyStrInterned {
|
||||
#[inline(always)]
|
||||
fn as_ref(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for PyStrInterned {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
std::fmt::Debug::fmt(self.as_str(), f)?;
|
||||
write!(f, "@{:p}", self.as_ptr())
|
||||
pub fn to_exact(&'static self) -> PyRefExact<PyStr> {
|
||||
unsafe { PyRefExact::new_unchecked(self.to_owned()) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,6 +212,13 @@ impl std::fmt::Display for PyStrInterned {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for PyStrInterned {
|
||||
#[inline(always)]
|
||||
fn as_ref(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
mod sealed {
|
||||
use crate::{
|
||||
builtins::PyStr,
|
||||
|
||||
@@ -132,7 +132,7 @@ mod sys {
|
||||
} else {
|
||||
"unknown"
|
||||
})
|
||||
.to_str()
|
||||
.to_owned()
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
@@ -513,7 +513,7 @@ mod sys {
|
||||
|
||||
#[pyfunction]
|
||||
fn intern(s: PyRefExact<PyStr>, vm: &VirtualMachine) -> PyRefExact<PyStr> {
|
||||
vm.ctx.intern_str(s).to_owned()
|
||||
vm.ctx.intern_str(s).to_exact()
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
|
||||
@@ -80,15 +80,14 @@ impl Context {
|
||||
|
||||
let new_str = unsafe { string_pool.intern("__new__", types.str_type.clone()) };
|
||||
let slot_new_wrapper = create_object(
|
||||
PyNativeFuncDef::new(PyType::__new__.into_func(), new_str.to_owned().into_pyref())
|
||||
.into_function(),
|
||||
PyNativeFuncDef::new(PyType::__new__.into_func(), new_str.to_owned()).into_function(),
|
||||
&types.builtin_function_or_method_type,
|
||||
)
|
||||
.into();
|
||||
|
||||
let true_str = unsafe { string_pool.intern("True", types.str_type.clone()) };
|
||||
let false_str = unsafe { string_pool.intern("False", types.str_type.clone()) };
|
||||
let empty_str = unsafe { string_pool.intern("", types.str_type.clone()) }.to_str();
|
||||
let empty_str = unsafe { string_pool.intern("", types.str_type.clone()) }.to_owned();
|
||||
|
||||
let context = Context {
|
||||
true_value,
|
||||
|
||||
Reference in new issue
Block a user