pyo3io_macros/
utils.rs

1// Code is copied and modified from the original source code: https://github.com/apache/incubator-opendal/blob/main/bindings/python/src/utils.rs
2//
3// Licensed to the Apache Software Foundation (ASF) under one
4// or more contributor license agreements.  See the NOTICE file
5// distributed with this work for additional information
6// regarding copyright ownership.  The ASF licenses this file
7// to you under the Apache License, Version 2.0 (the
8// "License"); you may not use this file except in compliance
9// with the License.  You may obtain a copy of the License at
10//
11//   http://www.apache.org/licenses/LICENSE-2.0
12//
13// Unless required by applicable law or agreed to in writing,
14// software distributed under the License is distributed on an
15// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16// KIND, either express or implied.  See the License for the
17// specific language governing permissions and limitations
18// under the License.
19
20use std::os::raw::c_int;
21
22use pyo3::ffi;
23use pyo3::prelude::*;
24
25pub(crate) const INLINED_U8: usize = 64;
26
27pub type Bytes = smallvec::SmallVec<[u8; INLINED_U8]>;
28
29/// A bytes-like object that implements buffer protocol.
30#[pyclass]
31pub struct Buffer(Bytes);
32
33impl From<Bytes> for Buffer {
34  fn from(inner: Bytes) -> Self {
35    Buffer(inner)
36  }
37}
38
39impl From<Vec<u8>> for Buffer {
40  fn from(inner: Vec<u8>) -> Self {
41    Buffer(inner.into())
42  }
43}
44
45impl From<&[u8]> for Buffer {
46  fn from(inner: &[u8]) -> Self {
47    Buffer(inner.into())
48  }
49}
50
51impl From<&str> for Buffer {
52  fn from(inner: &str) -> Self {
53    Buffer(inner.as_bytes().into())
54  }
55}
56
57impl From<String> for Buffer {
58  fn from(inner: String) -> Self {
59    Buffer(inner.into_bytes().into())
60  }
61}
62
63impl From<Buffer> for Bytes {
64  fn from(buffer: Buffer) -> Self {
65    buffer.0
66  }
67}
68
69impl Buffer {
70  pub fn new(inner: Bytes) -> Self {
71    Buffer(inner)
72  }
73
74  /// Consume self to build a memory view
75  pub fn into_memory_view(self, py: Python) -> PyResult<Py<PyAny>> {
76    let buffer = self.into_py(py);
77
78    unsafe { PyObject::from_owned_ptr_or_err(py, ffi::PyMemoryView_FromObject(buffer.as_ptr())) }
79  }
80
81  /// Consume self to build a memory view ref.
82  pub fn into_memory_view_ref(self, py: Python) -> PyResult<&PyAny> {
83    let buffer = self.into_py(py);
84    let view = unsafe { py.from_owned_ptr_or_err(ffi::PyMemoryView_FromObject(buffer.as_ptr()))? };
85
86    Ok(view)
87  }
88}
89
90#[pymethods]
91impl Buffer {
92  unsafe fn __getbuffer__(
93    slf: PyRefMut<Self>,
94    view: *mut ffi::Py_buffer,
95    flags: c_int,
96  ) -> PyResult<()> {
97    let bytes = slf.0.as_slice();
98    let ret = ffi::PyBuffer_FillInfo(
99      view,
100      slf.as_ptr() as *mut _,
101      bytes.as_ptr() as *mut _,
102      bytes.len().try_into().unwrap(),
103      1, // read only
104      flags,
105    );
106    if ret == -1 {
107      return Err(PyErr::fetch(slf.py()));
108    }
109    Ok(())
110  }
111}