jorisvandenbossche commented on code in PR #378:
URL: https://github.com/apache/arrow-nanoarrow/pull/378#discussion_r1492188208


##########
python/src/nanoarrow/_lib.pyx:
##########
@@ -1177,11 +1429,395 @@ cdef class CBufferView:
         buffer.strides = &self._strides
         buffer.suboffsets = NULL
 
-    def __releasebuffer__(self, Py_buffer *buffer):
+    cdef _do_releasebuffer(self, Py_buffer* buffer):
         pass
 
     def __repr__(self):
-        return f"<nanoarrow.c_lib.CBufferView>\n  
{_lib_utils.buffer_view_repr(self)[1:]}"
+        return f"CBufferView({_lib_utils.buffer_view_repr(self)})"
+
+
+cdef class CBuffer:
+    """Wrapper around readable owned buffer content
+
+    Like the CBufferView, the CBuffer represents readable buffer content; 
however,
+    unlike the CBufferView, the CBuffer always represents a valid ArrowBuffer 
C object.
+    """
+    cdef object _base
+    cdef ArrowBuffer* _ptr
+    cdef ArrowType _data_type
+    cdef int _element_size_bits
+    cdef char _format[32]
+    cdef CDevice _device
+    cdef CBufferView _view
+    cdef int _get_buffer_count
+
+    def __cinit__(self):
+        self._base = None
+        self._ptr = NULL
+        self._data_type = NANOARROW_TYPE_BINARY
+        self._element_size_bits = 0
+        self._device = CDEVICE_CPU
+        self._format[0] = 0
+        self._get_buffer_count = 0
+        self._reset_view()
+
+    cdef _assert_valid(self):
+        if self._ptr == NULL:
+            raise RuntimeError("CBuffer is not valid")
+
+    cdef _assert_buffer_count_zero(self):
+        if self._get_buffer_count != 0:
+            raise RuntimeError(
+                f"CBuffer already open ({self._get_buffer_count} ",
+                f"references, {self._writable_get_buffer_count} writable)")
+
+    cdef _reset_view(self):
+        self._view = CBufferView(None, 0, 0, NANOARROW_TYPE_BINARY, 8, 
self._device)
+
+    cdef _populate_view(self):
+        self._assert_valid()
+        self._assert_buffer_count_zero()
+        self._view = CBufferView(
+            self._base, <uintptr_t>self._ptr.data,
+            self._ptr.size_bytes, self._data_type, self._element_size_bits,
+            self._device
+        )
+
+    cdef _refresh_view_if_needed(self):
+        if self._get_buffer_count > 0:
+            return
+
+        self._assert_valid()
+        cdef int addr_equal = self._ptr.data == self._view._ptr.data.as_uint8
+        cdef int size_equal = self._ptr.size_bytes == 
self._view._ptr.size_bytes
+        cdef int types_equal = self._data_type == self._view._data_type
+        cdef int element_size_equal = self._element_size_bits == 
self._view.element_size_bits
+        if addr_equal and size_equal and types_equal and element_size_equal:
+            return
+
+        self._populate_view()
+
+    def set_empty(self):
+        self._assert_buffer_count_zero()
+        if self._ptr == NULL:
+            self._base = alloc_c_buffer(&self._ptr)
+        ArrowBufferReset(self._ptr)
+
+        self._data_type = NANOARROW_TYPE_BINARY
+        self._element_size_bits = 0
+        self._device = CDEVICE_CPU
+        self._reset_view()
+        return self
+
+    def set_pybuffer(self, obj):
+        self._assert_buffer_count_zero()
+        if self._ptr == NULL:
+            self._base = alloc_c_buffer(&self._ptr)
+
+        self.set_format(c_buffer_set_pybuffer(obj, &self._ptr))
+        self._device = CDEVICE_CPU
+        self._reset_view()
+        return self
+
+    def set_format(self, str format):
+        self._assert_buffer_count_zero()
+        element_size_bytes, data_type = c_arrow_type_from_format(format)
+        self._data_type = data_type
+        self._element_size_bits = element_size_bytes * 8
+        format_bytes = format.encode("UTF-8")
+        snprintf(self._format, sizeof(self._format), "%s", <const 
char*>format_bytes)
+        return self
+
+    def set_data_type(self, ArrowType type_id, int element_size_bits=0):
+        self._assert_buffer_count_zero()
+        self._element_size_bits = c_format_from_arrow_type(
+            type_id,
+            element_size_bits,
+            sizeof(self._format),
+            self._format
+        )
+        self._data_type = type_id
+
+        return self
+
+    def _addr(self):
+        self._assert_valid()
+        return <uintptr_t>self._ptr.data
+
+    @property
+    def size_bytes(self):
+        self._assert_valid()
+        return self._ptr.size_bytes
+
+    @property
+    def capacity_bytes(self):
+        self._assert_valid()
+        return self._ptr.capacity_bytes
+
+    @property
+    def data_type(self):
+        return ArrowTypeString(self._data_type).decode("UTF-8")
+
+    @property
+    def data_type_id(self):
+        return self._data_type
+
+    @property
+    def element_size_bits(self):
+        return self._element_size_bits
+
+    @property
+    def item_size(self):
+        self._refresh_view_if_needed()
+        return self._view.item_size

Review Comment:
   I see. Can you add some docstrings to clarify that difference between 
"item_.." and "element_.."?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to