@@ -2,7 +2,7 @@ use crate::{
22 builtins:: { PyStr , PyTypeRef } ,
33 common:: lock:: PyRwLock ,
44 convert:: ToPyObject ,
5- AsObject , Py , PyExact , PyObject , PyObjectRef , PyRef , PyRefExact ,
5+ AsObject , Py , PyExact , PyObject , PyObjectRef , PyPayload , PyRef , PyRefExact , VirtualMachine ,
66} ;
77use std:: {
88 borrow:: { Borrow , ToOwned } ,
@@ -113,42 +113,36 @@ impl CachedPyStrRef {
113113 }
114114}
115115
116- /// The unique reference of interned PyStr
117- /// Always intended to be used as a static reference
118- pub struct PyStrInterned {
119- inner : Py < PyStr > ,
116+ pub struct PyInterned < T >
117+ where
118+ T : PyPayload ,
119+ {
120+ inner : Py < T > ,
120121}
121122
122- impl PyStrInterned {
123- /// # Safety
124- /// the given cache must be alive while returned reference is alive
123+ impl < T : PyPayload > PyInterned < T > {
125124 #[ inline]
126- unsafe fn borrow_cache ( cache : & CachedPyStrRef ) -> & ' static Self {
127- std:: mem:: transmute_copy ( cache)
125+ pub fn leak ( cache : PyRef < T > ) -> & ' static Self {
126+ unsafe { std:: mem:: transmute ( cache) }
128127 }
129128
130129 #[ inline]
131- fn as_ptr ( & self ) -> * const Py < PyStr > {
130+ fn as_ptr ( & self ) -> * const Py < T > {
132131 self as * const _ as * const _
133132 }
134133
135134 #[ inline]
136- pub fn to_owned ( & ' static self ) -> PyRefExact < PyStr > {
137- unsafe { ( * ( & self as * const _ as * const PyRefExact < PyStr > ) ) . clone ( ) }
138- }
139-
140- #[ inline]
141- pub fn to_str ( & ' static self ) -> PyRef < PyStr > {
142- self . to_owned ( ) . into_pyref ( )
135+ pub fn to_owned ( & ' static self ) -> PyRef < T > {
136+ unsafe { ( * ( & self as * const _ as * const PyRef < T > ) ) . clone ( ) }
143137 }
144138
145139 #[ inline]
146140 pub fn to_object ( & ' static self ) -> PyObjectRef {
147- self . to_str ( ) . into ( )
141+ self . to_owned ( ) . into ( )
148142 }
149143}
150144
151- impl Borrow < PyObject > for PyStrInterned {
145+ impl < T : PyPayload > Borrow < PyObject > for PyInterned < T > {
152146 #[ inline( always) ]
153147 fn borrow ( & self ) -> & PyObject {
154148 self . inner . borrow ( )
@@ -157,41 +151,58 @@ impl Borrow<PyObject> for PyStrInterned {
157151
158152// NOTE: std::hash::Hash of Self and Self::Borrowed *must* be the same
159153// This is ok only because PyObject doesn't implement Hash
160- impl std:: hash:: Hash for PyStrInterned {
154+ impl < T : PyPayload > std:: hash:: Hash for PyInterned < T > {
161155 #[ inline( always) ]
162156 fn hash < H : std:: hash:: Hasher > ( & self , state : & mut H ) {
163157 self . get_id ( ) . hash ( state)
164158 }
165159}
166160
167- impl Deref for PyStrInterned {
168- type Target = Py < PyStr > ;
161+ impl < T : PyPayload > Deref for PyInterned < T > {
162+ type Target = Py < T > ;
169163 #[ inline( always) ]
170164 fn deref ( & self ) -> & Self :: Target {
171165 & self . inner
172166 }
173167}
174168
175- impl PartialEq for PyStrInterned {
169+ impl < T : PyPayload > PartialEq for PyInterned < T > {
176170 #[ inline( always) ]
177171 fn eq ( & self , other : & Self ) -> bool {
178172 std:: ptr:: eq ( self , other)
179173 }
180174}
181175
182- impl Eq for PyStrInterned { }
176+ impl < T : PyPayload > Eq for PyInterned < T > { }
183177
184- impl AsRef < str > for PyStrInterned {
185- # [ inline ( always ) ]
186- fn as_ref ( & self ) -> & str {
187- self . as_str ( )
178+ impl < T : PyPayload + std :: fmt :: Debug > std :: fmt :: Debug for PyInterned < T > {
179+ fn fmt ( & self , f : & mut std :: fmt :: Formatter < ' _ > ) -> std :: fmt :: Result {
180+ std :: fmt :: Debug :: fmt ( & * * self , f ) ? ;
181+ write ! ( f , "@{:p}" , self . as_ptr ( ) )
188182 }
189183}
190184
191- impl std:: fmt:: Debug for PyStrInterned {
192- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
193- std:: fmt:: Debug :: fmt ( self . as_str ( ) , f) ?;
194- write ! ( f, "@{:p}" , self . as_ptr( ) )
185+ impl < T : PyPayload > ToPyObject for & ' static PyInterned < T > {
186+ fn to_pyobject ( self , _vm : & VirtualMachine ) -> PyObjectRef {
187+ self . to_owned ( ) . into ( )
188+ }
189+ }
190+
191+ /// The unique reference of interned PyStr
192+ /// Always intended to be used as a static reference
193+ pub type PyStrInterned = PyInterned < PyStr > ;
194+
195+ impl PyStrInterned {
196+ /// # Safety
197+ /// the given cache must be alive while returned reference is alive
198+ #[ inline]
199+ unsafe fn borrow_cache ( cache : & CachedPyStrRef ) -> & ' static Self {
200+ std:: mem:: transmute_copy ( cache)
201+ }
202+
203+ #[ inline]
204+ pub fn to_exact ( & ' static self ) -> PyRefExact < PyStr > {
205+ unsafe { PyRefExact :: new_unchecked ( self . to_owned ( ) ) }
195206 }
196207}
197208
@@ -201,6 +212,13 @@ impl std::fmt::Display for PyStrInterned {
201212 }
202213}
203214
215+ impl AsRef < str > for PyStrInterned {
216+ #[ inline( always) ]
217+ fn as_ref ( & self ) -> & str {
218+ self . as_str ( )
219+ }
220+ }
221+
204222mod sealed {
205223 use crate :: {
206224 builtins:: PyStr ,
0 commit comments