Skip to content

Commit

Permalink
Merge pull request #189 from DenisBiryukov91/dev/interop_cleanup
Browse files Browse the repository at this point in the history
move interop functionality under separate namespace and make it public
  • Loading branch information
Mallets authored Aug 30, 2024
2 parents a2e92bb + 7a8b501 commit 2c5113b
Show file tree
Hide file tree
Showing 37 changed files with 853 additions and 576 deletions.
3 changes: 2 additions & 1 deletion docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ API Reference
publish_subscribe
query_reply
serialization_deserialization
channels
channels
interop
19 changes: 19 additions & 0 deletions docs/interop.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
..
.. Copyright (c) 2024 ZettaScale Technology
..
.. This program and the accompanying materials are made available under the
.. terms of the Eclipse Public License 2.0 which is available at
.. http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
.. which is available at https://www.apache.org/licenses/LICENSE-2.0.
..
.. SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
..
.. Contributors:
.. ZettaScale Zenoh Team, <zenoh@zettascale.tech>
..
Interoperability with Zenoh-c / Zenoh-pico
==========================================

.. doxygennamespace:: zenoh::interop
:content-only:
80 changes: 12 additions & 68 deletions include/zenoh/api/base.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,6 @@

namespace zenoh {

namespace detail {
template <typename T, typename = void>
struct is_loan_available : std::false_type {};

template <typename T>
struct is_loan_available<T, std::void_t<decltype(::z_loan(std::declval<const T&>()))>> : std::true_type {};

template <class T>
inline constexpr bool is_loan_available_v = is_loan_available<T>::value;

template <typename T, typename = void>
struct is_loan_mut_available : std::false_type {};

template <typename T>
struct is_loan_mut_available<T, std::void_t<decltype(::z_loan_mut(std::declval<T&>()))>> : std::true_type {};

template <class T>
inline constexpr bool is_loan_mut_available_v = is_loan_mut_available<T>::value;

} // namespace detail

/// @brief Error code returned by Zenoh API
typedef ::z_result_t ZResult;

Expand Down Expand Up @@ -76,13 +55,7 @@ class Copyable {

InnerType& inner() { return this->_0; }
const InnerType& inner() const { return this->_0; }

public:
/// @name Constructors
/// Construct from wrapped zenoh-c / zenoh-pico structure
explicit Copyable(const InnerType& v) : _0(v) {}
explicit operator const ZC_COPYABLE_TYPE&() const { return inner(); }
explicit operator ZC_COPYABLE_TYPE&() { return inner(); }
};

/// Base type for C++ wrappers of Zenoh owned structures
Expand All @@ -93,17 +66,6 @@ class Owned {
typedef ZC_OWNED_TYPE OwnedType;

public:
/// @name Constructors
/// @brief Construct from owned zenoh-c struct.
/// @param pv Pointer to valid owned zenoh-c struct. The ownership is transferred
/// to the constructed object.
explicit Owned(OwnedType* pv) {
if (pv) {
_0 = *pv;
::z_internal_null(pv);
} else
::z_internal_null(&this->_0);
}
/// Move constructor from other object
Owned(Owned&& v) : Owned(&v._0) {}
/// Move assignment from other object
Expand All @@ -118,39 +80,21 @@ class Owned {
/// Destructor drops owned value using z_drop from zenoh API
~Owned() { ::z_drop(::z_move(_0)); }

/// @name Methods

/// Take out zenoh structure and leave owned object in a null state.
OwnedType take() && {
auto r = this->_0;
::z_internal_null(&this->_0);
return r;
}

/// Check object validity uzing zenoh API
/// This is internal function made public for testing purposes
bool internal_check() const { return ::z_internal_check(_0); }

protected:
OwnedType _0;

template <class OtL = z_owned_to_loaned_type_t<ZC_OWNED_TYPE>,
class L = typename OtL::type, // SFINAE here if no loaned type declared
class LAvail = std::enable_if<detail::is_loan_available_v<ZC_OWNED_TYPE>, L>,
class T = typename LAvail::type // SFINAE here if immutable loan is not available
>
const T* loan() const {
return ::z_loan(_0);
}

template <class OtL = z_owned_to_loaned_type_t<ZC_OWNED_TYPE>,
class L = typename OtL::type, // SFINAE here if no loaned type declared
class LAvail = std::enable_if<detail::is_loan_mut_available_v<ZC_OWNED_TYPE>, L>,
class T = typename LAvail::type // SFINAE here if mutable loan is not available
>
T* loan() {
return ::z_loan_mut(_0);
explicit Owned(OwnedType* pv) {
if (pv) {
_0 = *pv;
::z_internal_null(pv);
} else
::z_internal_null(&this->_0);
}
};

} // namespace zenoh
namespace detail {
struct null_object_t {};
inline constexpr null_object_t null_object{};
} // namespace detail

} // namespace zenoh
87 changes: 48 additions & 39 deletions include/zenoh/api/bytes.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@

#include "../detail/closures.hxx"
#include "../detail/commons.hxx"
#include "../detail/interop.hxx"
#include "base.hxx"
#include "closures.hxx"
#include "interop.hxx"
#if (defined(SHARED_MEMORY) && defined(UNSTABLE))
#include "shm/buffer/buffer.hxx"
#endif
Expand Down Expand Up @@ -67,17 +67,17 @@ class Bytes : public Owned<::z_owned_bytes_t> {
/// @brief Construct a shallow copy of this data.
Bytes clone() const {
Bytes b;
::z_bytes_clone(&b._0, this->loan());
::z_bytes_clone(&b._0, interop::as_loaned_c_ptr(*this));
return b;
}

/// @brief Construct an empty data.
Bytes() : Owned(nullptr) { ::z_bytes_empty(detail::as_owned_c_ptr(*this)); }
Bytes() : Owned(nullptr) { ::z_bytes_empty(interop::as_owned_c_ptr(*this)); }

/// @name Methods

/// @brief Get number of bytes in the pyload.
size_t size() const { return ::z_bytes_len(this->loan()); }
size_t size() const { return ::z_bytes_len(interop::as_loaned_c_ptr(*this)); }

/// @brief Serialize specified type.
///
Expand Down Expand Up @@ -111,15 +111,15 @@ class Bytes : public Owned<::z_owned_bytes_t> {
// increment current, in case iterator dereference might invalidate it, which happens
// for map/set elements extraction while serializing std::move'd map/set
auto it = current++;
*b = Bytes::serialize(*it, codec).take();
*b = interop::move_to_c_obj(Bytes::serialize(*it, codec));
return true;
};
using F = decltype(f);

using ClosureType = typename detail::closures::Closure<F, closures::None, bool, z_owned_bytes_t*>;
auto closure = ClosureType(std::forward<F>(f), closures::none);

::z_bytes_from_iter(detail::as_owned_c_ptr(out), detail::closures::_zenoh_encode_iter, closure.as_context());
::z_bytes_from_iter(interop::as_owned_c_ptr(out), detail::closures::_zenoh_encode_iter, closure.as_context());
return out;
}

Expand Down Expand Up @@ -154,9 +154,10 @@ class Bytes : public Owned<::z_owned_bytes_t> {

/// @brief A reader for Zenoh-serialized data.
class Reader : public Copyable<::z_bytes_reader_t> {
public:
using Copyable::Copyable;
friend struct interop::detail::Converter;

public:
/// @name Methods

/// @brief Read data into specified destination.
Expand Down Expand Up @@ -210,13 +211,16 @@ class Bytes : public Owned<::z_owned_bytes_t> {

/// @brief Create data reader.
/// @return reader instance.
Reader reader() const { return Reader(::z_bytes_get_reader(this->loan())); }
Reader reader() const {
return interop::into_copyable_cpp_obj<Reader>(::z_bytes_get_reader(interop::as_loaned_c_ptr(*this)));
}

/// @brief A writer for Zenoh-serialized data.
class Writer : public Copyable<::z_bytes_writer_t> {
public:
using Copyable::Copyable;
friend struct interop::detail::Converter;

public:
/// @name Methods

/// @brief Copy data from sepcified source into underlying ``Bytes`` instance.
Expand Down Expand Up @@ -256,28 +260,33 @@ class Bytes : public Owned<::z_owned_bytes_t> {
/// It is the user responsibility to ensure that there is at most one active writer at
/// a given moment of time for a given ``Bytes`` instance.
/// @return writer instance.
Writer writer() { return Writer(::z_bytes_get_writer(this->loan())); }
Writer writer() {
return interop::into_copyable_cpp_obj<Writer>(::z_bytes_get_writer(interop::as_loaned_c_ptr(*this)));
}
};

/// @brief An iterator over multi-element serialized data.
class Bytes::Iterator : Copyable<::z_bytes_iterator_t> {
public:
using Copyable::Copyable;
friend struct interop::detail::Converter;

public:
/// @name Methods

/// @brief Return next element of serialized data.
/// @return next element of serialized data, if the iterator reached the end, an empty optional will be returned.
std::optional<Bytes> next() {
std::optional<Bytes> b(std::in_place);
if (!::z_bytes_iterator_next(&this->_0, detail::as_owned_c_ptr(b.value()))) {
if (!::z_bytes_iterator_next(&this->_0, interop::as_owned_c_ptr(b.value()))) {
b.reset();
}
return b;
}
};

inline Bytes::Iterator Bytes::iter() const { return Bytes::Iterator(::z_bytes_get_iterator(this->loan())); }
inline Bytes::Iterator Bytes::iter() const {
return interop::into_copyable_cpp_obj<Bytes::Iterator>(::z_bytes_get_iterator(interop::as_loaned_c_ptr(*this)));
}

namespace detail {

Expand All @@ -299,9 +308,9 @@ struct ZenohDeserializer<std::string> {
template <>
struct ZenohDeserializer<ZShm> {
static ZShm deserialize(const Bytes& b, ZResult* err = nullptr) {
ZShm shm(nullptr);
ZShm shm = interop::detail::null<ZShm>();
__ZENOH_RESULT_CHECK(
::z_bytes_deserialize_into_owned_shm(detail::as_loaned_c_ptr(b), detail::as_owned_c_ptr(shm)), err,
::z_bytes_deserialize_into_owned_shm(interop::as_loaned_c_ptr(b), interop::as_owned_c_ptr(shm)), err,
"Failed to deserialize into ZShm!");
return shm;
}
Expand All @@ -323,8 +332,8 @@ template <class A, class B>
struct ZenohDeserializer<std::pair<A, B>> {
static std::pair<A, B> deserialize(const Bytes& b, ZResult* err = nullptr) {
zenoh::Bytes ba, bb;
__ZENOH_RESULT_CHECK(::z_bytes_deserialize_into_pair(detail::as_loaned_c_ptr(b), detail::as_owned_c_ptr(ba),
detail::as_owned_c_ptr(bb)),
__ZENOH_RESULT_CHECK(::z_bytes_deserialize_into_pair(interop::as_loaned_c_ptr(b), interop::as_owned_c_ptr(ba),
interop::as_owned_c_ptr(bb)),
err, "Failed to deserialize into std::pair");
return {ZenohDeserializer<A>::deserialize(ba, err), ZenohDeserializer<B>::deserialize(bb, err)};
}
Expand Down Expand Up @@ -408,15 +417,15 @@ struct ZenohDeserializer<std::map<K, V, C, Allocator>> {
}
};

#define __ZENOH_DESERIALIZE_ARITHMETIC(TYPE, EXT) \
template <> \
struct ZenohDeserializer<TYPE> { \
static TYPE deserialize(const Bytes& b, ZResult* err = nullptr) { \
TYPE t; \
__ZENOH_RESULT_CHECK(::z_bytes_deserialize_into_##EXT(detail::as_loaned_c_ptr(b), &t), err, \
"Failed to deserialize into " #TYPE); \
return t; \
} \
#define __ZENOH_DESERIALIZE_ARITHMETIC(TYPE, EXT) \
template <> \
struct ZenohDeserializer<TYPE> { \
static TYPE deserialize(const Bytes& b, ZResult* err = nullptr) { \
TYPE t; \
__ZENOH_RESULT_CHECK(::z_bytes_deserialize_into_##EXT(interop::as_loaned_c_ptr(b), &t), err, \
"Failed to deserialize into " #TYPE); \
return t; \
} \
};

__ZENOH_DESERIALIZE_ARITHMETIC(uint8_t, uint8);
Expand All @@ -440,7 +449,7 @@ struct Slice {
size_t len;
};

auto make_slice(const uint8_t* data, size_t len) { return Slice{data, len}; };
inline auto make_slice(const uint8_t* data, size_t len) { return Slice{data, len}; };

template <class Deleter>
struct OwnedSlice {
Expand Down Expand Up @@ -469,7 +478,7 @@ class ZenohCodec {
Bytes serialize(const Slice& s) const {
Bytes b;
if (this->_alias_guard == nullptr) {
::z_bytes_serialize_from_buf(detail::as_owned_c_ptr(b), s.data, s.len);
::z_bytes_serialize_from_buf(interop::as_owned_c_ptr(b), s.data, s.len);
} else {
auto deleter = [ptr = this->_alias_guard](void*) mutable { ptr.reset(); };
b = serialize(make_owned_slice(const_cast<uint8_t*>(s.data), s.len, std::move(deleter)));
Expand All @@ -488,7 +497,7 @@ class ZenohCodec {
using Dval = std::remove_reference_t<D>;
using DroppableType = typename detail::closures::Droppable<Dval>;
auto drop = DroppableType::into_context(std::forward<D>(d));
::z_bytes_from_buf(detail::as_owned_c_ptr(b), data, len, detail::closures::_zenoh_drop_with_context, drop);
::z_bytes_from_buf(interop::as_owned_c_ptr(b), data, len, detail::closures::_zenoh_drop_with_context, drop);
return b;
}

Expand All @@ -513,14 +522,14 @@ class ZenohCodec {
#if (defined(SHARED_MEMORY) && defined(UNSTABLE))
Bytes serialize(ZShm&& shm, ZResult* err = nullptr) const {
Bytes b;
__ZENOH_RESULT_CHECK(::z_bytes_serialize_from_shm(detail::as_owned_c_ptr(b), detail::as_moved_c_ptr(shm)), err,
"Failed to serialize ZShm");
__ZENOH_RESULT_CHECK(::z_bytes_serialize_from_shm(interop::as_owned_c_ptr(b), interop::as_moved_c_ptr(shm)),
err, "Failed to serialize ZShm");
return b;
}

Bytes serialize(ZShmMut&& shm, ZResult* err = nullptr) const {
Bytes b;
__ZENOH_RESULT_CHECK(::z_bytes_serialize_from_shm_mut(detail::as_owned_c_ptr(b), detail::as_moved_c_ptr(shm)),
__ZENOH_RESULT_CHECK(::z_bytes_serialize_from_shm_mut(interop::as_owned_c_ptr(b), interop::as_moved_c_ptr(shm)),
err, "Failed to serialize ZShmMut");
return b;
}
Expand Down Expand Up @@ -628,7 +637,7 @@ class ZenohCodec {
auto ba = serialize(s.first);
auto bb = serialize(s.second);
Bytes b;
::z_bytes_from_pair(detail::as_owned_c_ptr(b), detail::as_moved_c_ptr(ba), detail::as_moved_c_ptr(bb));
::z_bytes_from_pair(interop::as_owned_c_ptr(b), interop::as_moved_c_ptr(ba), interop::as_moved_c_ptr(bb));
return b;
}

Expand All @@ -637,7 +646,7 @@ class ZenohCodec {
auto ba = serialize(std::move(s.first));
auto bb = serialize(std::move(s.second));
Bytes b;
::z_bytes_from_pair(detail::as_owned_c_ptr(b), detail::as_moved_c_ptr(ba), detail::as_moved_c_ptr(bb));
::z_bytes_from_pair(interop::as_owned_c_ptr(b), interop::as_moved_c_ptr(ba), interop::as_moved_c_ptr(bb));
return b;
}

Expand All @@ -653,11 +662,11 @@ class ZenohCodec {
}
}

#define __ZENOH_SERIALIZE_ARITHMETIC(TYPE, EXT) \
Bytes serialize(TYPE t) const { \
Bytes b; \
::z_bytes_serialize_from_##EXT(detail::as_owned_c_ptr(b), t); \
return b; \
#define __ZENOH_SERIALIZE_ARITHMETIC(TYPE, EXT) \
Bytes serialize(TYPE t) const { \
Bytes b; \
::z_bytes_serialize_from_##EXT(interop::as_owned_c_ptr(b), t); \
return b; \
}

__ZENOH_SERIALIZE_ARITHMETIC(uint8_t, uint8);
Expand Down
Loading

0 comments on commit 2c5113b

Please sign in to comment.