From 38a1f318449ce26316aad3dbfd0304a41351f907 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Wed, 11 Sep 2024 22:09:17 +0200 Subject: [PATCH] make z_bytes_writer owned and make it take possesion of bytes it writes to --- build-resources/opaque-types/src/lib.rs | 12 ++- docs/api.rst | 8 +- include/zenoh_commons.h | 50 ++++++++- include/zenoh_macros.h | 22 ++++ splitguide.yaml | 3 +- src/payload.rs | 128 +++++++++++++++++++++--- tests/z_api_payload_test.c | 41 ++++---- 7 files changed, 224 insertions(+), 40 deletions(-) diff --git a/build-resources/opaque-types/src/lib.rs b/build-resources/opaque-types/src/lib.rs index 5c2740623..cff3e0c64 100644 --- a/build-resources/opaque-types/src/lib.rs +++ b/build-resources/opaque-types/src/lib.rs @@ -93,8 +93,16 @@ get_opaque_type_data!(Sample, z_loaned_sample_t); /// A reader for serialized data. get_opaque_type_data!(ZBytesReader<'static>, z_bytes_reader_t); -/// A writer for serialized data. -get_opaque_type_data!(ZBytesWriter<'static>, z_bytes_writer_t); +#[derive(Default)] +struct DummyWriter { + _b: Box, + _w: Option>, +} + +/// An owned writer for serialized data. +get_opaque_type_data!(DummyWriter, z_owned_bytes_writer_t); +/// A loaned writer for serialized data. +get_opaque_type_data!(DummyWriter, z_loaned_bytes_writer_t); /// An iterator over multi-element serialized data. get_opaque_type_data!(ZBytesIterator<'static, ZBytes>, z_bytes_iterator_t); diff --git a/docs/api.rst b/docs/api.rst index cc175965c..031fd5d91 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -96,7 +96,8 @@ Types .. doxygenstruct:: z_loaned_bytes_t .. doxygenstruct:: z_bytes_iterator_t .. doxygenstruct:: z_bytes_reader_t -.. doxygenstruct:: z_bytes_writer_t +.. doxygenstruct:: z_owned_bytes_writer_t +.. doxygenstruct:: z_loaned_bytes_writer_t Functions ^^^^^^^^^ @@ -157,9 +158,14 @@ Functions .. doxygenfunction:: z_bytes_get_writer +.. doxygenfunction:: z_bytes_new .. doxygenfunction:: z_bytes_writer_write_all .. doxygenfunction:: z_bytes_writer_append .. doxygenfunction:: z_bytes_writer_append_bounded +.. doxygenfunction:: z_bytes_writer_get_bytes +.. doxygenfunction:: z_bytes_writer_loan +.. doxygenfunction:: z_bytes_writer_loan_mut +.. doxygenfunction:: z_bytes_writer_drop diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index e3126b15a..e6e663ff0 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -391,6 +391,9 @@ typedef struct z_moved_string_t { typedef struct ALIGN(8) z_bytes_slice_iterator_t { uint8_t _0[24]; } z_bytes_slice_iterator_t; +typedef struct z_moved_bytes_writer_t { + struct z_owned_bytes_writer_t _this; +} z_moved_bytes_writer_t; /** * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. * @brief Unique segment identifier. @@ -1603,8 +1606,12 @@ ZENOHC_API struct z_bytes_slice_iterator_t z_bytes_get_slice_iterator(const struct z_loaned_bytes_t *this_); /** * Gets writer for `this_`. + * @param this_ Data to write to. Consumed by writer. Can be extracted after all writes are done using `z_bytes_writer_get_bytes`. + * @param writer An uninitialized memory location where writer will be constructed. */ -ZENOHC_API struct z_bytes_writer_t z_bytes_get_writer(struct z_loaned_bytes_t *this_); +ZENOHC_API +void z_bytes_get_writer(struct z_moved_bytes_t *this_, + struct z_owned_bytes_writer_t *writer); /** * Returns ``true`` if `this_` is empty, ``false`` otherwise. */ @@ -1770,7 +1777,7 @@ bool z_bytes_slice_iterator_next(struct z_bytes_slice_iterator_t *this_, * @return 0 in case of success, negative error code otherwise */ ZENOHC_API -z_result_t z_bytes_writer_append(struct z_bytes_writer_t *this_, +z_result_t z_bytes_writer_append(struct z_loaned_bytes_writer_t *this_, struct z_moved_bytes_t *bytes); /** * Appends bytes, with boundaries information. It would allow to read the same piece of data using `z_bytes_reader_read_bounded()`. @@ -1778,15 +1785,42 @@ z_result_t z_bytes_writer_append(struct z_bytes_writer_t *this_, * @return 0 in case of success, negative error code otherwise */ ZENOHC_API -z_result_t z_bytes_writer_append_bounded(struct z_bytes_writer_t *this_, +z_result_t z_bytes_writer_append_bounded(struct z_loaned_bytes_writer_t *this_, struct z_moved_bytes_t *bytes); +/** + * Drops `this_`, resetting it to gravestone value. + */ +ZENOHC_API void z_bytes_writer_drop(struct z_moved_bytes_writer_t *this_); +/** + * Extracts data from writer. After the function return, writer is invalidated. + * + * @param this_ Writer to extract data from. + * @param bytes Uninitialized memory location where z_bytes оbject containing extracted data will be constructed. + */ +ZENOHC_API +void z_bytes_writer_get_bytes(struct z_moved_bytes_writer_t *this_, + struct z_owned_bytes_t *bytes); +/** + * Borrows writer. + */ +ZENOHC_API +const struct z_loaned_bytes_writer_t *z_bytes_writer_loan(const struct z_owned_bytes_writer_t *this_); +/** + * Muatably borrows writer. + */ +ZENOHC_API +struct z_loaned_bytes_writer_t *z_bytes_writer_loan_mut(struct z_owned_bytes_writer_t *this_); +/** + * Constructs a writer from empty data. + */ +ZENOHC_API void z_bytes_writer_new(struct z_owned_bytes_writer_t *this_); /** * Writes `len` bytes from `src` into underlying data. * * @return 0 in case of success, negative error code otherwise. */ ZENOHC_API -z_result_t z_bytes_writer_write_all(struct z_bytes_writer_t *this_, +z_result_t z_bytes_writer_write_all(struct z_loaned_bytes_writer_t *this_, const uint8_t *src, size_t len); /** @@ -2789,6 +2823,14 @@ ZENOHC_API bool z_internal_bytes_check(const struct z_owned_bytes_t *this_); * The gravestone value for `z_owned_bytes_t`. */ ZENOHC_API void z_internal_bytes_null(struct z_owned_bytes_t *this_); +/** + * Returns ``true`` if `this_` is in a valid state, ``false`` if it is in a gravestone state. + */ +ZENOHC_API bool z_internal_bytes_writer_check(const struct z_owned_bytes_writer_t *this_); +/** + * Constructs a serialized data writer in a gravestone state. + */ +ZENOHC_API void z_internal_bytes_writer_null(struct z_owned_bytes_writer_t *this_); /** * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. * @return ``true`` if `this` is valid. diff --git a/include/zenoh_macros.h b/include/zenoh_macros.h index f5e49c1b5..4a2c7ef35 100644 --- a/include/zenoh_macros.h +++ b/include/zenoh_macros.h @@ -5,6 +5,7 @@ #ifndef __cplusplus static inline z_moved_bytes_t* z_bytes_move(z_owned_bytes_t* x) { return (z_moved_bytes_t*)(x); } +static inline z_moved_bytes_writer_t* z_bytes_writer_move(z_owned_bytes_writer_t* x) { return (z_moved_bytes_writer_t*)(x); } static inline z_moved_closure_hello_t* z_closure_hello_move(z_owned_closure_hello_t* x) { return (z_moved_closure_hello_t*)(x); } static inline z_moved_closure_query_t* z_closure_query_move(z_owned_closure_query_t* x) { return (z_moved_closure_query_t*)(x); } static inline z_moved_closure_reply_t* z_closure_reply_move(z_owned_closure_reply_t* x) { return (z_moved_closure_reply_t*)(x); } @@ -39,6 +40,7 @@ static inline zc_moved_closure_log_t* zc_closure_log_move(zc_owned_closure_log_t #define z_loan(this_) \ _Generic((this_), \ z_owned_bytes_t : z_bytes_loan, \ + z_owned_bytes_writer_t : z_bytes_writer_loan, \ z_owned_closure_hello_t : z_closure_hello_loan, \ z_owned_closure_query_t : z_closure_query_loan, \ z_owned_closure_reply_t : z_closure_reply_loan, \ @@ -74,6 +76,7 @@ static inline zc_moved_closure_log_t* zc_closure_log_move(zc_owned_closure_log_t #define z_loan_mut(this_) \ _Generic((this_), \ z_owned_bytes_t : z_bytes_loan_mut, \ + z_owned_bytes_writer_t : z_bytes_writer_loan_mut, \ z_owned_condvar_t : z_condvar_loan_mut, \ z_owned_config_t : z_config_loan_mut, \ z_owned_encoding_t : z_encoding_loan_mut, \ @@ -85,6 +88,7 @@ static inline zc_moved_closure_log_t* zc_closure_log_move(zc_owned_closure_log_t #define z_drop(this_) \ _Generic((this_), \ z_moved_bytes_t* : z_bytes_drop, \ + z_moved_bytes_writer_t* : z_bytes_writer_drop, \ z_moved_closure_hello_t* : z_closure_hello_drop, \ z_moved_closure_query_t* : z_closure_query_drop, \ z_moved_closure_reply_t* : z_closure_reply_drop, \ @@ -119,6 +123,7 @@ static inline zc_moved_closure_log_t* zc_closure_log_move(zc_owned_closure_log_t #define z_move(this_) \ _Generic((this_), \ z_owned_bytes_t : z_bytes_move, \ + z_owned_bytes_writer_t : z_bytes_writer_move, \ z_owned_closure_hello_t : z_closure_hello_move, \ z_owned_closure_query_t : z_closure_query_move, \ z_owned_closure_reply_t : z_closure_reply_move, \ @@ -153,6 +158,7 @@ static inline zc_moved_closure_log_t* zc_closure_log_move(zc_owned_closure_log_t #define z_internal_null(this_) \ _Generic((this_), \ z_owned_bytes_t* : z_internal_bytes_null, \ + z_owned_bytes_writer_t* : z_internal_bytes_writer_null, \ z_owned_closure_hello_t* : z_internal_closure_hello_null, \ z_owned_closure_query_t* : z_internal_closure_query_null, \ z_owned_closure_reply_t* : z_internal_closure_reply_null, \ @@ -185,6 +191,7 @@ static inline zc_moved_closure_log_t* zc_closure_log_move(zc_owned_closure_log_t )(this_) static inline void z_bytes_take(z_owned_bytes_t* this_, z_moved_bytes_t* x) { *this_ = x->_this; z_internal_bytes_null(&x->_this); } +static inline void z_bytes_writer_take(z_owned_bytes_writer_t* this_, z_moved_bytes_writer_t* x) { *this_ = x->_this; z_internal_bytes_writer_null(&x->_this); } static inline void z_closure_hello_take(z_owned_closure_hello_t* this_, z_moved_closure_hello_t* x) { *this_ = x->_this; z_internal_closure_hello_null(&x->_this); } static inline void z_closure_query_take(z_owned_closure_query_t* closure_, z_moved_closure_query_t* x) { *closure_ = x->_this; z_internal_closure_query_null(&x->_this); } static inline void z_closure_reply_take(z_owned_closure_reply_t* closure_, z_moved_closure_reply_t* x) { *closure_ = x->_this; z_internal_closure_reply_null(&x->_this); } @@ -219,6 +226,7 @@ static inline void zc_closure_log_take(zc_owned_closure_log_t* closure_, zc_move #define z_take(this_, x) \ _Generic((this_), \ z_owned_bytes_t* : z_bytes_take, \ + z_owned_bytes_writer_t* : z_bytes_writer_take, \ z_owned_closure_hello_t* : z_closure_hello_take, \ z_owned_closure_query_t* : z_closure_query_take, \ z_owned_closure_reply_t* : z_closure_reply_take, \ @@ -253,6 +261,7 @@ static inline void zc_closure_log_take(zc_owned_closure_log_t* closure_, zc_move #define z_internal_check(this_) \ _Generic((this_), \ z_owned_bytes_t : z_internal_bytes_check, \ + z_owned_bytes_writer_t : z_internal_bytes_writer_check, \ z_owned_closure_hello_t : z_internal_closure_hello_check, \ z_owned_closure_query_t : z_internal_closure_query_check, \ z_owned_closure_reply_t : z_internal_closure_reply_check, \ @@ -332,6 +341,7 @@ static inline void zc_closure_log_take(zc_owned_closure_log_t* closure_, zc_move static inline z_moved_bytes_t* z_bytes_move(z_owned_bytes_t* x) { return reinterpret_cast(x); } +static inline z_moved_bytes_writer_t* z_bytes_writer_move(z_owned_bytes_writer_t* x) { return reinterpret_cast(x); } static inline z_moved_closure_hello_t* z_closure_hello_move(z_owned_closure_hello_t* x) { return reinterpret_cast(x); } static inline z_moved_closure_query_t* z_closure_query_move(z_owned_closure_query_t* x) { return reinterpret_cast(x); } static inline z_moved_closure_reply_t* z_closure_reply_move(z_owned_closure_reply_t* x) { return reinterpret_cast(x); } @@ -365,6 +375,7 @@ static inline zc_moved_closure_log_t* zc_closure_log_move(zc_owned_closure_log_t inline const z_loaned_bytes_t* z_loan(const z_owned_bytes_t& this_) { return z_bytes_loan(&this_); }; +inline const z_loaned_bytes_writer_t* z_loan(const z_owned_bytes_writer_t& this_) { return z_bytes_writer_loan(&this_); }; inline const z_loaned_closure_hello_t* z_loan(const z_owned_closure_hello_t& closure) { return z_closure_hello_loan(&closure); }; inline const z_loaned_closure_query_t* z_loan(const z_owned_closure_query_t& closure) { return z_closure_query_loan(&closure); }; inline const z_loaned_closure_reply_t* z_loan(const z_owned_closure_reply_t& closure) { return z_closure_reply_loan(&closure); }; @@ -398,6 +409,7 @@ inline const zc_loaned_closure_log_t* z_loan(const zc_owned_closure_log_t& closu inline z_loaned_bytes_t* z_loan_mut(z_owned_bytes_t& this_) { return z_bytes_loan_mut(&this_); }; +inline z_loaned_bytes_writer_t* z_loan_mut(z_owned_bytes_writer_t& this_) { return z_bytes_writer_loan_mut(&this_); }; inline z_loaned_condvar_t* z_loan_mut(z_owned_condvar_t& this_) { return z_condvar_loan_mut(&this_); }; inline z_loaned_config_t* z_loan_mut(z_owned_config_t& this_) { return z_config_loan_mut(&this_); }; inline z_loaned_encoding_t* z_loan_mut(z_owned_encoding_t& this_) { return z_encoding_loan_mut(&this_); }; @@ -407,6 +419,7 @@ inline z_loaned_string_array_t* z_loan_mut(z_owned_string_array_t& this_) { retu inline void z_drop(z_moved_bytes_t* this_) { z_bytes_drop(this_); }; +inline void z_drop(z_moved_bytes_writer_t* this_) { z_bytes_writer_drop(this_); }; inline void z_drop(z_moved_closure_hello_t* this_) { z_closure_hello_drop(this_); }; inline void z_drop(z_moved_closure_query_t* closure_) { z_closure_query_drop(closure_); }; inline void z_drop(z_moved_closure_reply_t* closure_) { z_closure_reply_drop(closure_); }; @@ -439,6 +452,7 @@ inline void z_drop(zc_moved_closure_log_t* closure_) { zc_closure_log_drop(closu inline z_moved_bytes_t* z_move(z_owned_bytes_t& this_) { return z_bytes_move(&this_); }; +inline z_moved_bytes_writer_t* z_move(z_owned_bytes_writer_t& this_) { return z_bytes_writer_move(&this_); }; inline z_moved_closure_hello_t* z_move(z_owned_closure_hello_t& this_) { return z_closure_hello_move(&this_); }; inline z_moved_closure_query_t* z_move(z_owned_closure_query_t& closure_) { return z_closure_query_move(&closure_); }; inline z_moved_closure_reply_t* z_move(z_owned_closure_reply_t& closure_) { return z_closure_reply_move(&closure_); }; @@ -471,6 +485,7 @@ inline zc_moved_closure_log_t* z_move(zc_owned_closure_log_t& closure_) { return inline void z_internal_null(z_owned_bytes_t* this_) { z_internal_bytes_null(this_); }; +inline void z_internal_null(z_owned_bytes_writer_t* this_) { z_internal_bytes_writer_null(this_); }; inline void z_internal_null(z_owned_closure_hello_t* this_) { z_internal_closure_hello_null(this_); }; inline void z_internal_null(z_owned_closure_query_t* this_) { z_internal_closure_query_null(this_); }; inline void z_internal_null(z_owned_closure_reply_t* this_) { z_internal_closure_reply_null(this_); }; @@ -502,6 +517,7 @@ inline void z_internal_null(z_owned_task_t* this_) { z_internal_task_null(this_) inline void z_internal_null(zc_owned_closure_log_t* this_) { zc_internal_closure_log_null(this_); }; static inline void z_bytes_take(z_owned_bytes_t* this_, z_moved_bytes_t* x) { *this_ = x->_this; z_internal_bytes_null(&x->_this); } +static inline void z_bytes_writer_take(z_owned_bytes_writer_t* this_, z_moved_bytes_writer_t* x) { *this_ = x->_this; z_internal_bytes_writer_null(&x->_this); } static inline void z_closure_hello_take(z_owned_closure_hello_t* this_, z_moved_closure_hello_t* x) { *this_ = x->_this; z_internal_closure_hello_null(&x->_this); } static inline void z_closure_query_take(z_owned_closure_query_t* closure_, z_moved_closure_query_t* x) { *closure_ = x->_this; z_internal_closure_query_null(&x->_this); } static inline void z_closure_reply_take(z_owned_closure_reply_t* closure_, z_moved_closure_reply_t* x) { *closure_ = x->_this; z_internal_closure_reply_null(&x->_this); } @@ -537,6 +553,9 @@ static inline void zc_closure_log_take(zc_owned_closure_log_t* closure_, zc_move inline void z_take(z_owned_bytes_t* this_, z_moved_bytes_t* x) { z_bytes_take(this_, x); }; +inline void z_take(z_owned_bytes_writer_t* this_, z_moved_bytes_writer_t* x) { + z_bytes_writer_take(this_, x); +}; inline void z_take(z_owned_closure_hello_t* this_, z_moved_closure_hello_t* x) { z_closure_hello_take(this_, x); }; @@ -627,6 +646,7 @@ inline void z_take(zc_owned_closure_log_t* closure_, zc_moved_closure_log_t* x) inline bool z_internal_check(const z_owned_bytes_t& this_) { return z_internal_bytes_check(&this_); }; +inline bool z_internal_check(const z_owned_bytes_writer_t& this_) { return z_internal_bytes_writer_check(&this_); }; inline bool z_internal_check(const z_owned_closure_hello_t& this_) { return z_internal_closure_hello_check(&this_); }; inline bool z_internal_check(const z_owned_closure_query_t& this_) { return z_internal_closure_query_check(&this_); }; inline bool z_internal_check(const z_owned_closure_reply_t& this_) { return z_internal_closure_reply_check(&this_); }; @@ -790,6 +810,8 @@ template struct z_loaned_to_owned_type_t {}; template struct z_owned_to_loaned_type_t {}; template<> struct z_loaned_to_owned_type_t { typedef z_owned_bytes_t type; }; template<> struct z_owned_to_loaned_type_t { typedef z_loaned_bytes_t type; }; +template<> struct z_loaned_to_owned_type_t { typedef z_owned_bytes_writer_t type; }; +template<> struct z_owned_to_loaned_type_t { typedef z_loaned_bytes_writer_t type; }; template<> struct z_loaned_to_owned_type_t { typedef z_owned_closure_hello_t type; }; template<> struct z_owned_to_loaned_type_t { typedef z_loaned_closure_hello_t type; }; template<> struct z_loaned_to_owned_type_t { typedef z_owned_closure_query_t type; }; diff --git a/splitguide.yaml b/splitguide.yaml index 22bd854e5..2392dfd4b 100644 --- a/splitguide.yaml +++ b/splitguide.yaml @@ -20,7 +20,8 @@ zenoh_opaque.h: - z_owned_sample_t! - z_loaned_sample_t! - z_bytes_reader_t! - - z_bytes_writer_t! + - z_owned_bytes_writer_t! + - z_loaned_bytes_writer_t! - z_bytes_iterator_t! - z_owned_encoding_t! - z_loaned_encoding_t! diff --git a/src/payload.rs b/src/payload.rs index bbd4b254a..ec59e73fb 100644 --- a/src/payload.rs +++ b/src/payload.rs @@ -941,14 +941,54 @@ pub unsafe extern "C" fn z_bytes_reader_tell(this_: &mut z_bytes_reader_t) -> i6 reader.stream_position().map(|p| p as i64).unwrap_or(-1) } -pub use crate::opaque_types::z_bytes_writer_t; +pub use crate::opaque_types::{ + z_loaned_bytes_writer_t, z_moved_bytes_writer_t, z_owned_bytes_writer_t, +}; + +#[derive(Default)] +pub struct OwnedWriter { + b: Box, + w: Option>, +} + +impl OwnedWriter { + fn new(bytes: ZBytes) -> Self { + let mut s = Self { + b: Box::new(bytes), + w: None, + }; + let b_ptr = s.b.as_mut() as *mut ZBytes; + unsafe { s.w = Some(b_ptr.as_mut().unwrap_unchecked().writer()) }; + s + } + + fn null() -> Self { + Self { + b: Box::new(ZBytes::empty()), + w: None, + } + } -decl_c_type! {loaned(z_bytes_writer_t, ZBytesWriter<'static>)} + fn writer(&mut self) -> &mut ZBytesWriter<'static> { + unsafe { self.w.as_mut().unwrap_unchecked() } + } +} + +decl_c_type!( + owned(z_owned_bytes_writer_t, OwnedWriter), + loaned(z_loaned_bytes_writer_t), +); /// Gets writer for `this_`. +/// @param this_ Data to write to. Consumed by writer. Can be extracted after all writes are done using `z_bytes_writer_get_bytes`. +/// @param writer An uninitialized memory location where writer will be constructed. #[no_mangle] -extern "C" fn z_bytes_get_writer(this: &'static mut z_loaned_bytes_t) -> z_bytes_writer_t { - *this.as_rust_type_mut().writer().as_loaned_c_type_ref() +extern "C" fn z_bytes_get_writer( + this: &'static mut z_moved_bytes_t, + writer: &mut MaybeUninit, +) { + let b = this.take_rust_type(); + writer.as_rust_type_mut_uninit().write(OwnedWriter::new(b)); } /// Writes `len` bytes from `src` into underlying data. @@ -957,11 +997,15 @@ extern "C" fn z_bytes_get_writer(this: &'static mut z_loaned_bytes_t) -> z_bytes #[allow(clippy::missing_safety_doc)] #[no_mangle] unsafe extern "C" fn z_bytes_writer_write_all( - this: &mut z_bytes_writer_t, + this: &mut z_loaned_bytes_writer_t, src: *const u8, len: usize, ) -> z_result_t { - match this.as_rust_type_mut().write_all(from_raw_parts(src, len)) { + match this + .as_rust_type_mut() + .writer() + .write_all(from_raw_parts(src, len)) + { Ok(_) => Z_OK, Err(_) => Z_EIO, } @@ -972,25 +1016,81 @@ unsafe extern "C" fn z_bytes_writer_write_all( /// Said in other terms, it allows to create a linear view on different memory regions without copy. /// /// @return 0 in case of success, negative error code otherwise -#[allow(clippy::missing_safety_doc)] #[no_mangle] -unsafe extern "C" fn z_bytes_writer_append( - this: &mut z_bytes_writer_t, +pub extern "C" fn z_bytes_writer_append( + this: &mut z_loaned_bytes_writer_t, bytes: &mut z_moved_bytes_t, ) -> z_result_t { - this.as_rust_type_mut().append(bytes.take_rust_type()); + this.as_rust_type_mut() + .writer() + .append(bytes.take_rust_type()); result::Z_OK } /// Appends bytes, with boundaries information. It would allow to read the same piece of data using `z_bytes_reader_read_bounded()`. /// /// @return 0 in case of success, negative error code otherwise -#[allow(clippy::missing_safety_doc)] #[no_mangle] -unsafe extern "C" fn z_bytes_writer_append_bounded( - this: &mut z_bytes_writer_t, +pub extern "C" fn z_bytes_writer_append_bounded( + this: &mut z_loaned_bytes_writer_t, bytes: &mut z_moved_bytes_t, ) -> z_result_t { - this.as_rust_type_mut().serialize(bytes.take_rust_type()); + this.as_rust_type_mut() + .writer() + .serialize(bytes.take_rust_type()); result::Z_OK } + +/// Extracts data from writer. After the function return, writer is invalidated. +/// +/// @param this_ Writer to extract data from. +/// @param bytes Uninitialized memory location where z_bytes оbject containing extracted data will be constructed. +#[no_mangle] +pub unsafe extern "C" fn z_bytes_writer_get_bytes( + this: &mut z_moved_bytes_writer_t, + bytes: &mut MaybeUninit, +) { + let ow = this.take_rust_type(); + bytes.as_rust_type_mut_uninit().write(*ow.b); +} + +/// Constructs a writer from empty data. +#[no_mangle] +extern "C" fn z_bytes_writer_new(this: &mut MaybeUninit) { + this.as_rust_type_mut_uninit() + .write(OwnedWriter::new(ZBytes::empty())); +} + +/// Drops `this_`, resetting it to gravestone value. +#[no_mangle] +extern "C" fn z_bytes_writer_drop(this_: &mut z_moved_bytes_writer_t) { + let _ = this_.take_rust_type(); +} + +/// Returns ``true`` if `this_` is in a valid state, ``false`` if it is in a gravestone state. +#[no_mangle] +extern "C" fn z_internal_bytes_writer_check(this: &z_owned_bytes_writer_t) -> bool { + this.as_rust_type_ref().w.is_some() +} + +/// Borrows writer. +#[no_mangle] +unsafe extern "C" fn z_bytes_writer_loan( + this: &z_owned_bytes_writer_t, +) -> &z_loaned_bytes_writer_t { + this.as_rust_type_ref().as_loaned_c_type_ref() +} + +/// Muatably borrows writer. +#[no_mangle] +extern "C" fn z_bytes_writer_loan_mut( + this: &mut z_owned_bytes_writer_t, +) -> &mut z_loaned_bytes_writer_t { + this.as_rust_type_mut().as_loaned_c_type_mut() +} + +/// Constructs a serialized data writer in a gravestone state. +#[no_mangle] +pub extern "C" fn z_internal_bytes_writer_null(this: &mut MaybeUninit) { + this.as_rust_type_mut_uninit().write(OwnedWriter::null()); +} diff --git a/tests/z_api_payload_test.c b/tests/z_api_payload_test.c index 39eb6aa81..e58d70240 100644 --- a/tests/z_api_payload_test.c +++ b/tests/z_api_payload_test.c @@ -83,14 +83,15 @@ void test_writer() { uint8_t data_out[10] = {0}; z_owned_bytes_t payload; - z_bytes_empty(&payload); - z_bytes_writer_t writer = z_bytes_get_writer(z_loan_mut(payload)); + z_owned_bytes_writer_t writer; + z_bytes_writer_new(&writer); - assert(z_bytes_writer_write_all(&writer, data, 3) == 0); - assert(z_bytes_writer_write_all(&writer, data + 3, 5) == 0); - assert(z_bytes_writer_write_all(&writer, data + 8, 2) == 0); + assert(z_bytes_writer_write_all(z_loan_mut(writer), data, 3) == 0); + assert(z_bytes_writer_write_all(z_loan_mut(writer), data + 3, 5) == 0); + assert(z_bytes_writer_write_all(z_loan_mut(writer), data + 8, 2) == 0); + z_bytes_writer_get_bytes(z_move(writer), &payload); z_bytes_reader_t reader = z_bytes_get_reader(z_loan(payload)); assert(10 == z_bytes_reader_read(&reader, data_out, 10)); @@ -104,19 +105,20 @@ void test_bounded(void) { uint32_t data_out[10] = {0}; z_owned_bytes_t payload; - z_bytes_empty(&payload); + z_owned_bytes_writer_t writer; + z_bytes_writer_new(&writer); - z_bytes_writer_t writer = z_bytes_get_writer(z_loan_mut(payload)); for (size_t i = 0; i < 10; ++i) { z_owned_bytes_t b; z_bytes_serialize_from_uint32(&b, data[i]); - assert(z_bytes_writer_append_bounded(&writer, z_move(b)) == 0); + assert(z_bytes_writer_append_bounded(z_loan_mut(writer), z_move(b)) == 0); } { z_owned_bytes_t b; z_bytes_serialize_from_str(&b, "test"); - assert(z_bytes_writer_append_bounded(&writer, z_move(b)) == 0); + assert(z_bytes_writer_append_bounded(z_loan_mut(writer), z_move(b)) == 0); } + z_bytes_writer_get_bytes(z_move(writer), &payload); z_bytes_reader_t reader = z_bytes_get_reader(z_loan(payload)); @@ -147,16 +149,17 @@ void test_append(void) { uint8_t data_out[10] = {0}; z_owned_bytes_t payload; - z_bytes_empty(&payload); + z_owned_bytes_writer_t writer; + z_bytes_writer_new(&writer); - z_bytes_writer_t writer = z_bytes_get_writer(z_loan_mut(payload)); - z_bytes_writer_write_all(&writer, data, 5); + z_bytes_writer_write_all(z_loan_mut(writer), data, 5); { z_owned_bytes_t b; z_bytes_serialize_from_buf(&b, data + 5, 5); - assert(z_bytes_writer_append(&writer, z_move(b)) == 0); + assert(z_bytes_writer_append(z_loan_mut(writer), z_move(b)) == 0); } + z_bytes_writer_get_bytes(z_move(writer), &payload); z_bytes_reader_t reader = z_bytes_get_reader(z_loan(payload)); z_bytes_reader_read(&reader, data_out, 10); @@ -319,24 +322,26 @@ bool check_slice(const z_loaned_bytes_t *b, const uint8_t *data, size_t len) { void test_slices(void) { uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; z_owned_bytes_t payload; - z_bytes_empty(&payload); - z_bytes_writer_t writer = z_bytes_get_writer(z_loan_mut(payload)); - z_bytes_writer_write_all(&writer, data, 10); + z_owned_bytes_writer_t writer; + z_bytes_writer_new(&writer); + z_bytes_writer_write_all(z_loan_mut(writer), data, 10); + z_bytes_writer_get_bytes(z_move(writer), &payload); assert(check_slice(z_loan(payload), data, 10)); z_drop(z_move(payload)); z_bytes_empty(&payload); // possible multiple slices - writer = z_bytes_get_writer(z_loan_mut(payload)); + z_bytes_writer_new(&writer); for (size_t i = 0; i < 10; i++) { z_owned_bytes_t b; z_bytes_serialize_from_buf(&b, data + i, 1); - z_bytes_writer_append(&writer, z_move(b)); + z_bytes_writer_append(z_loan_mut(writer), z_move(b)); } + z_bytes_writer_get_bytes(z_move(writer), &payload); assert(check_slice(z_loan(payload), data, 10)); z_drop(z_move(payload));