File tree Expand file tree Collapse file tree 2 files changed +29
-0
lines changed Expand file tree Collapse file tree 2 files changed +29
-0
lines changed Original file line number Diff line number Diff line change 1+ Add PyString::from_bytes. This saves a redundant UTF-8 validation check because Python internally validates the bytes again.
Original file line number Diff line number Diff line change @@ -168,6 +168,20 @@ impl PyString {
168168 }
169169 }
170170
171+ /// Creates a new Python string object from bytes.
172+ ///
173+ /// Returns PyMemoryError if out of memory.
174+ /// Returns [PyUnicodeDecodeError] if the slice is not a valid UTF-8 string.
175+ pub fn from_bytes < ' py > ( py : Python < ' py > , s : & [ u8 ] ) -> PyResult < Bound < ' py , PyString > > {
176+ let ptr = s. as_ptr ( ) . cast ( ) ;
177+ let len = s. len ( ) as ffi:: Py_ssize_t ;
178+ unsafe {
179+ ffi:: PyUnicode_FromStringAndSize ( ptr, len)
180+ . assume_owned_or_err ( py)
181+ . cast_into_unchecked ( )
182+ }
183+ }
184+
171185 /// Intern the given string
172186 ///
173187 /// This will return a reference to the same Python string object if called repeatedly with the same string.
@@ -828,6 +842,20 @@ mod tests {
828842 } ) ;
829843 }
830844
845+ #[ test]
846+ #[ cfg( not( any( Py_LIMITED_API , PyPy , GraalPy ) ) ) ]
847+ fn test_pystring_from_bytes ( ) {
848+ Python :: attach ( |py| {
849+ let result = PyString :: from_bytes ( py, "\u{2122} " . as_bytes ( ) ) ;
850+ assert ! ( result. is_ok( ) ) ;
851+ let result = PyString :: from_bytes ( py, b"\x80 " ) ;
852+ assert ! ( result
853+ . unwrap_err( )
854+ . get_type( py)
855+ . is( py. get_type:: <PyUnicodeDecodeError >( ) ) ) ;
856+ } ) ;
857+ }
858+
831859 #[ test]
832860 fn test_intern_string ( ) {
833861 Python :: attach ( |py| {
You can’t perform that action at this time.
0 commit comments