// Copyright 2022 The Dawn & Tint Authors // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // 3. Neither the name of the copyright holder nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef SRC_DAWN_NATIVE_STREAM_STREAM_H_ #define SRC_DAWN_NATIVE_STREAM_STREAM_H_ #include <algorithm> #include <bitset> #include <functional> #include <limits> #include <unordered_map> #include <unordered_set> #include <utility> #include <vector> #include <optional> #include "dawn/common/Platform.h" #include "dawn/common/TypedInteger.h" #include "dawn/native/Error.h" #include "dawn/native/stream/Sink.h" #include "dawn/native/stream/Source.h" namespace dawn::ityp { template <typename Index, size_t N> class bitset; } // namespace dawn::ityp namespace dawn::native::stream { // Base Stream template for specialization. Specializations may define static methods: // static void Write(Sink* s, const T& v); // static MaybeError Read(Source* s, T* v); template <typename T, typename SFINAE = void> class Stream { … }; // Helper to call Stream<T>::Write. // By default, calling StreamIn will call this overload inside the stream namespace. // Other definitons of StreamIn found by ADL may override this one. template <typename T> constexpr void StreamIn(Sink* s, const T& v) { … } // Helper to call Stream<T>::Read // By default, calling StreamOut will call this overload inside the stream namespace. // Other definitons of StreamOut found by ADL may override this one. template <typename T> MaybeError StreamOut(Source* s, T* v) { … } // Helper to take an rvalue passed to StreamOut and forward it as a pointer. // This makes it possible to pass output wrappers like stream::StructMembers inline. // For example: `DAWN_TRY(StreamOut(&source, stream::StructMembers(...)));` template <typename T> MaybeError StreamOut(Source* s, T&& v) { … } // Helper to call StreamIn on a parameter pack. template <typename T, typename... Ts> constexpr void StreamIn(Sink* s, const T& v, const Ts&... vs) { … } // Helper to call StreamOut on a parameter pack. template <typename T, typename... Ts> MaybeError StreamOut(Source* s, T* v, Ts*... vs) { … } // Stream specialization for fundamental types. Stream<T, std::enable_if_t<std::is_fundamental_v<T>>>; namespace detail { // NOLINTNEXTLINE(runtime/int) Alias "unsigned long long" type to match std::bitset to_ullong BitsetUllong; constexpr size_t kBitsPerUllong = …; constexpr bool BitsetSupportsToUllong(size_t N) { … } } // namespace detail // Stream specialization for bitsets that are smaller than BitsetUllong. Stream<std::bitset<N>, std::enable_if_t<detail::BitsetSupportsToUllong(N)>>; // Stream specialization for bitsets since using the built-in to_ullong has a size limit. Stream<std::bitset<N>, std::enable_if_t<!detail::BitsetSupportsToUllong(N)>>; Stream<ityp::bitset<Index, N>>; // Stream specialization for enums. Stream<T, std::enable_if_t<std::is_enum_v<T>>>; // Stream specialization for TypedInteger. Stream< ::dawn::detail::TypedIntegerImpl<Tag, Integer>>; // Stream specialization for pointers. We always serialize via value, not by pointer. // To handle nullptr scenarios, we always serialize whether the pointer was not nullptr, // followed by the contents if applicable. Stream<T, std::enable_if_t<std::is_pointer_v<T>>>; // Stream specialization for std::optional Stream<std::optional<T>>; // Stream specialization for fixed arrays of fundamental types. Stream<T[N], std::enable_if_t<std::is_fundamental_v<T>>>; // Specialization for fixed arrays of non-fundamental types. Stream<T[N], std::enable_if_t<!std::is_fundamental_v<T>>>; // Stream specialization for std::vector. Stream<std::vector<T>>; // Stream specialization for std::pair. Stream<std::pair<A, B>>; // Stream specialization for std::unordered_map<K, V> which sorts the entries // to provide a stable ordering. Stream<std::unordered_map<K, V>>; // Stream specialization for std::unordered_set<V> which sorts the entries // to provide a stable ordering. Stream<std::unordered_set<V>>; // Helper class to contain the begin/end iterators of an iterable. namespace detail { template <typename Iterator> struct Iterable { … }; } // namespace detail // Helper for making detail::Iterable from a pointer and count. template <typename T> auto Iterable(const T* ptr, size_t count) { … } // Stream specialization for detail::Iterable which writes the number of elements, // followed by the elements. Stream<detail::Iterable<Iterator>>; } // namespace dawn::native::stream #endif // SRC_DAWN_NATIVE_STREAM_STREAM_H_