Skip to content

Commit

Permalink
Provide a special purpose FromPyObject impl to efficiently and safely…
Browse files Browse the repository at this point in the history
… get a byte slice from either bytes or byte arrays.
  • Loading branch information
adamreichold committed Jan 20, 2023
1 parent 4d85374 commit 5fffb8e
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 4 deletions.
1 change: 0 additions & 1 deletion pyo3-macros-backend/src/frompyobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,6 @@ impl<'a> Container<'a> {
let self_ty = &self.path;
let struct_name = &self.name();
let field_idents: Vec<_> = (0..struct_fields.len())
.into_iter()
.map(|i| format_ident!("arg{}", i))
.collect();
let fields = struct_fields.iter().zip(&field_idents).enumerate().map(|(index, (field, ident))| {
Expand Down
2 changes: 0 additions & 2 deletions pyo3-macros-backend/src/pymethod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1109,7 +1109,6 @@ impl SlotDef {
let py = syn::Ident::new("_py", Span::call_site());
let arg_types: &Vec<_> = &arguments.iter().map(|arg| arg.ffi_type()).collect();
let arg_idents: &Vec<_> = &(0..arguments.len())
.into_iter()
.map(|i| format_ident!("arg{}", i))
.collect();
let wrapper_ident = format_ident!("__pymethod_{}__", method_name);
Expand Down Expand Up @@ -1220,7 +1219,6 @@ impl SlotFragmentDef {
let py = syn::Ident::new("_py", Span::call_site());
let arg_types: &Vec<_> = &arguments.iter().map(|arg| arg.ffi_type()).collect();
let arg_idents: &Vec<_> = &(0..arguments.len())
.into_iter()
.map(|i| format_ident!("arg{}", i))
.collect();
let body = generate_method_body(cls, spec, &py, arguments, *extract_error_mode, None)?;
Expand Down
17 changes: 16 additions & 1 deletion src/types/bytes.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use crate::{ffi, AsPyPointer, Py, PyAny, PyResult, Python};
use crate::{ffi, AsPyPointer, FromPyObject, Py, PyAny, PyResult, Python};
use std::borrow::Cow;
use std::ops::Index;
use std::os::raw::c_char;
use std::slice::SliceIndex;
use std::str;

use super::bytearray::PyByteArray;

/// Represents a Python `bytes` object.
///
/// This type is immutable.
Expand Down Expand Up @@ -121,6 +124,18 @@ impl<I: SliceIndex<[u8]>> Index<I> for PyBytes {
}
}

/// Special-purpose trait impl to efficient handle [`PyBytes`] and [`PyByteArray`]
impl<'source> FromPyObject<'source> for Cow<'source, [u8]> {
fn extract(ob: &'source PyAny) -> PyResult<Self> {
if let Ok(bytes) = ob.downcast::<PyBytes>() {
return Ok(Cow::Borrowed(bytes.as_bytes()));
}

let byte_array = ob.downcast::<PyByteArray>()?;
Ok(Cow::Owned(byte_array.to_vec()))
}
}

#[cfg(test)]
mod tests {
use super::PyBytes;
Expand Down

0 comments on commit 5fffb8e

Please sign in to comment.