From 44fc3501977198917e40938c963a9691ff917b87 Mon Sep 17 00:00:00 2001 From: Jamieson Pryor Date: Mon, 29 Aug 2022 18:28:48 +0000 Subject: [PATCH] Rev JNI Bind release header to v 0.6. PiperOrigin-RevId: 470771470 Change-Id: I0639ed351a59a16ee87be691add29e7435aadbbd --- README.md | 2 +- jni_bind_release.h | 963 +++++++++++++++++++++++++++------------------ 2 files changed, 575 insertions(+), 390 deletions(-) diff --git a/README.md b/README.md index c17f17d7..0c5aeff3 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ If you're already using Bazel add the following to your WORKSPACE: ```starlark http_archive( name = "jni-bind", - urls = ["https://github.com/google/jni-bind/archive/refs/tags/Release-0.5.0-alpha.zip"], + urls = ["https://github.com/google/jni-bind/archive/refs/tags/Release-0.6.0-alpha.zip"], strip_prefix = "jni-bind-Release-0.5.0-alpha", ) ``` diff --git a/jni_bind_release.h b/jni_bind_release.h index 4837b2ea..a37ac34f 100644 --- a/jni_bind_release.h +++ b/jni_bind_release.h @@ -1025,7 +1025,7 @@ constexpr std::size_t ModifiedMax( } // namespace jni::metaprogramming - +#include #include #include #include @@ -1033,8 +1033,14 @@ constexpr std::size_t ModifiedMax( namespace jni { static constexpr struct NoClass { + const char* name_ = "__JNI_BIND__NO_CLASS__"; + const std::tuple<> methods_{}; + const std::tuple<> fields_{}; } kNoClassSpecified; +static constexpr std::size_t kNoClassSpecifiedIdx = + std::numeric_limits::max(); + template struct Class {}; @@ -1337,6 +1343,37 @@ inline constexpr Method kGetClassLoaderMethod{ } // namespace jni +#include +#include +#include + +namespace jni::metaprogramming { + +// Wrapper to convert a sequence of values into a type. +template +struct Vals { + static constexpr std::array val{Vs...}; +}; + +// Wrapper to convert a sequence of const values into a type. +template +struct ValsConst { + static constexpr std::array val{Vs...}; +}; + +// Wrapper to convert a sequence of ref values into a type. +template +struct ValsRef { + static constexpr std::array val{Vs...}; +}; + +// Wrapper to convert a sequence of const ref values into a type. +template +struct ValsConstRef { + static constexpr std::array val{Vs...}; +}; + +} // namespace jni::metaprogramming #include @@ -1392,6 +1429,213 @@ using TypeToTypeMapFromKeyValuesTup_t = } // namespace jni::metaprogramming +#include +#include +#include + +namespace jni { + +inline constexpr struct NoClassLoader { +} kNoClassLoaderSpecified; + +static constexpr std::size_t kNoClassLoaderSpecifiedIdx = + std::numeric_limits::max(); + +// Represents the compile time info we have about a class loader. In general, +// this is just the list of classes we expect to be loadable from a class loader +// and its parent loader. +// +// Classes from different loaders are typically incompatible, but Class loaders +// delegate classes that they cannot directly load to their parent loaders, so +// classes attached to two different class loaders will still be compatible if +// they were loaded by a shared parent loader. +template +class ClassLoader { + public: + const ParentLoader_ parent_loader_; + const std::tuple supported_classes_; + + // TODO (b/143908983): Loaders should not be able to supply classes that their + // parents do. + explicit constexpr ClassLoader( + ParentLoader_ parent_loader, + SupportedClassSet supported_class_set) + : parent_loader_(parent_loader), + supported_classes_(supported_class_set.supported_classes_) {} + + explicit constexpr ClassLoader( + SupportedClassSet supported_class_set) + : parent_loader_(kDefaultClassLoader), + supported_classes_(supported_class_set.supported_classes_) {} + + bool constexpr operator==( + const ClassLoader& rhs) const { + return (*this).parent_loader_ == rhs.parent_loader_ && + (*this).supported_classes_ == rhs.supported_classes_; + } + template + bool constexpr operator==(const T& rhs) const { + return false; + } + template + bool constexpr operator!=(const T& rhs) const { + return !(*this == rhs); + } + + template + constexpr std::size_t IdxOfClassHelper( + std::integer_sequence) const { + // std::max appears to be missing the initializer list overload in Bazel's + // implementation of clang. This should simply be std::max. + return metaprogramming::ModifiedMax( + {((std::get(supported_classes_) == class_v) + ? std::size_t{Is} + : metaprogramming::kNegativeOne)..., + metaprogramming::kNegativeOne}); + } + + // Returns the index for a given class within this set (any given class ref is + // defined by this index). + template + constexpr std::size_t IdxOfClass() const { + return IdxOfClassHelper( + std::make_integer_sequence()); + } + + // Tests if a class is supported by this class loader (not ancestors). + template + constexpr bool SupportedByThisSet() const { + return IdxOfClass() != kClassNotInLoaderSetIdx; + } + + // Tests if a class is supported by this class loader (ancestors included). + template + constexpr bool SupportedDirectlyOrIndirectly() const { + return parent_loader_.template SupportedDirectlyOrIndirectly< + possibly_supported_class>() || + SupportedByThisSet(); + } + + // Returns the index for parent-most ancestor that supports a given class. + template + constexpr std::size_t IdxOfAncestor(std::size_t cur_idx = 0) const { + if (SupportedByThisSet() && + !parent_loader_.template SupportedDirectlyOrIndirectly< + possibly_supported_class, true>()) { + return cur_idx; + } + return parent_loader_.template IdxOfAncestor( + cur_idx + 1); + } +}; + +template +ClassLoader(ParentLoader_ parent_loader, + SupportedClassSet supported_classes) + -> ClassLoader; + +template +ClassLoader(SupportedClassSet) + -> ClassLoader; + +template +constexpr auto& GetAncestor(const T& loader) { + if constexpr (I == 0) { + return loader; + } else { + return GetAncestor( + loader.parent_loader_); + } +} + +template +constexpr const auto& ParentLoaderForClass() { + if constexpr (!loader.template SupportedDirectlyOrIndirectly< + possibly_supported_class>()) { + return kNullClassLoader; + } else if constexpr (loader.template IdxOfAncestor< + possibly_supported_class>() != + kClassNotInLoaderSetIdx) { + return GetAncestor< + decltype(loader), + loader.template IdxOfAncestor()>(loader); + } else { + return kDefaultClassLoader; + } +} + +} // namespace jni + +#include +#include + +namespace jni::metaprogramming { + +// Performs a deep equality comparison of T, but is leniant about containers. +// Returns true iff types are equal or both types are containers and their +// non-type template parameters are equal. +template +struct ValsEqual { + template + struct Helper { + static constexpr bool val = std::is_same_v; + }; + + // Value comparison. + template