@@ -1948,32 +1948,43 @@ cdef class CBufferView:
19481948 else :
19491949 return self ._iter_dispatch(offset, length)
19501950
1951+ def copy_into (self , dest , offset = 0 , length = None , dest_offset = 0 ):
1952+ if length is None :
1953+ length = self .n_elements
1954+
1955+ cdef Py_buffer buffer
1956+ PyObject_GetBuffer(dest, & buffer , PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS)
1957+
1958+ cdef int64_t c_offset = offset
1959+ cdef int64_t c_length = length
1960+ cdef int64_t c_item_size = self .item_size
1961+ cdef int64_t c_dest_offset = dest_offset
1962+ self ._check_copy_into_bounds(& buffer , c_offset, c_length, dest_offset, c_item_size)
1963+
1964+ cdef uint8_t* dest_uint8 = < uint8_t* > buffer .buf
1965+ cdef int64_t dest_offset_bytes = c_dest_offset * c_item_size
1966+ cdef int64_t src_offset_bytes = c_offset * c_item_size
1967+ cdef int64_t bytes_to_copy = c_length * c_item_size
1968+
1969+ memcpy(
1970+ & (dest_uint8[dest_offset_bytes]),
1971+ & (self ._ptr.data.as_uint8[src_offset_bytes]),
1972+ bytes_to_copy
1973+ )
1974+
1975+ PyBuffer_Release(& buffer )
1976+ return bytes_to_copy
1977+
19511978 def unpack_bits_into (self , dest , offset = 0 , length = None , dest_offset = 0 ):
19521979 if self ._data_type != NANOARROW_TYPE_BOOL:
19531980 raise ValueError (" Can't unpack non-boolean buffer" )
19541981
19551982 if length is None :
19561983 length = self .n_elements
19571984
1958- if offset < 0 or length < 0 or (offset + length) > self .n_elements:
1959- raise IndexError (
1960- f" offset {offset} and length {length} do not describe a valid slice "
1961- f" of buffer with {self.n_elements} elements"
1962- )
1963-
19641985 cdef Py_buffer buffer
19651986 PyObject_GetBuffer(dest, & buffer , PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS)
1966- if buffer .itemsize != 1 :
1967- PyBuffer_Release(& buffer )
1968- raise ValueError (" Destination buffer has itemsize != 1" )
1969-
1970- if dest_offset < 0 or buffer .len < (dest_offset + length):
1971- buffer_len = buffer .len
1972- PyBuffer_Release(& buffer )
1973- raise IndexError (
1974- f" Can't unpack {length} elements into buffer of size {buffer_len} "
1975- f" with dest_offset = {dest_offset}"
1976- )
1987+ self ._check_copy_into_bounds(& buffer , offset, length, dest_offset, 1 )
19771988
19781989 ArrowBitsUnpackInt8(
19791990 self ._ptr.data.as_uint8,
@@ -1983,6 +1994,7 @@ cdef class CBufferView:
19831994 )
19841995
19851996 PyBuffer_Release(& buffer )
1997+ return length
19861998
19871999 def unpack_bits (self , offset = 0 , length = None ):
19882000 if length is None :
@@ -1994,6 +2006,42 @@ cdef class CBufferView:
19942006 out.advance(length)
19952007 return out.finish()
19962008
2009+ def copy (self , offset = 0 , length = None ):
2010+ if length is None :
2011+ length = self .n_elements
2012+
2013+ cdef int64_t bytes_to_copy = length * self .item_size
2014+ out = CBufferBuilder().set_data_type(self .data_type_id)
2015+ out.reserve_bytes(bytes_to_copy)
2016+ self .copy_into(out, offset, length)
2017+ out.advance(bytes_to_copy)
2018+ return out.finish()
2019+
2020+ cdef _check_copy_into_bounds(self , Py_buffer* dest, int64_t offset, int64_t length,
2021+ int64_t dest_offset, int64_t dest_itemsize):
2022+ if offset < 0 or length < 0 or (offset + length) > self .n_elements:
2023+ PyBuffer_Release(dest)
2024+ raise IndexError (
2025+ f" offset {offset} and length {length} do not describe a valid slice "
2026+ f" of buffer with {self.n_elements} elements"
2027+ )
2028+
2029+ if dest.itemsize != 1 and dest.itemsize != dest_itemsize:
2030+ raise ValueError (
2031+ " Destination buffer must have itemsize == 1 or "
2032+ f" itemsize == {dest_itemsize}"
2033+ )
2034+
2035+ cdef int64_t dest_offset_bytes = dest_offset * dest_itemsize
2036+ cdef int64_t bytes_to_copy = dest_itemsize * length
2037+ if dest_offset < 0 or dest.len < (dest_offset_bytes + bytes_to_copy):
2038+ buffer_len = dest.len
2039+ PyBuffer_Release(dest)
2040+ raise IndexError (
2041+ f" Can't unpack {length} elements into buffer of size {buffer_len} "
2042+ f" with dest_offset = {dest_offset}"
2043+ )
2044+
19972045 def _iter_bitmap (self , int64_t offset , int64_t length ):
19982046 cdef uint8_t item
19992047 cdef int64_t i
0 commit comments