Bug 1941046 - Part 4: Send a callback request for impression and clicks of MARS Top...
[gecko.git] / dom / quota / Flatten.h
blob4525c038e877766602cb10536beb74b89f56121e
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef DOM_QUOTA_FLATTEN_H_
8 #define DOM_QUOTA_FLATTEN_H_
10 #include <iterator>
11 #include <type_traits>
12 #include <utility>
14 // XXX This should be moved to MFBT.
16 namespace mozilla::dom::quota {
18 namespace detail {
20 using std::begin;
21 using std::end;
23 template <typename T, typename NestedRange>
24 auto Flatten(NestedRange&& aRange)
25 -> std::enable_if_t<
26 std::is_same_v<T,
27 std::decay_t<typename decltype(begin(
28 std::declval<const NestedRange&>()))::value_type>>,
29 std::conditional_t<std::is_rvalue_reference_v<NestedRange>,
30 std::decay_t<NestedRange>, NestedRange>> {
31 return std::forward<NestedRange>(aRange);
34 template <typename T, typename NestedRange>
35 struct FlatIter {
36 using OuterIterator =
37 decltype(begin(std::declval<const std::decay_t<NestedRange>&>()));
38 using InnerIterator =
39 decltype(begin(*begin(std::declval<const std::decay_t<NestedRange>&>())));
41 explicit FlatIter(const NestedRange& aRange, OuterIterator aIter)
42 : mOuterIter{std::move(aIter)}, mOuterEnd{end(aRange)} {
43 InitInner();
46 const T& operator*() const { return *mInnerIter; }
48 FlatIter& operator++() {
49 ++mInnerIter;
50 if (mInnerIter == mInnerEnd) {
51 ++mOuterIter;
52 InitInner();
54 return *this;
57 bool operator!=(const FlatIter& aOther) const {
58 return mOuterIter != aOther.mOuterIter ||
59 (mOuterIter != mOuterEnd && mInnerIter != aOther.mInnerIter);
62 private:
63 void InitInner() {
64 while (mOuterIter != mOuterEnd) {
65 const typename OuterIterator::value_type& innerRange = *mOuterIter;
67 mInnerIter = begin(innerRange);
68 mInnerEnd = end(innerRange);
70 if (mInnerIter != mInnerEnd) {
71 break;
74 ++mOuterIter;
78 OuterIterator mOuterIter;
79 const OuterIterator mOuterEnd;
81 InnerIterator mInnerIter;
82 InnerIterator mInnerEnd;
85 template <typename T, typename NestedRange>
86 struct FlatRange {
87 explicit FlatRange(NestedRange aRange) : mRange{std::move(aRange)} {}
89 auto begin() const {
90 using std::begin;
91 return FlatIter<T, NestedRange>{mRange, begin(mRange)};
93 auto end() const {
94 using std::end;
95 return FlatIter<T, NestedRange>{mRange, end(mRange)};
98 private:
99 NestedRange mRange;
102 template <typename T, typename NestedRange>
103 auto Flatten(NestedRange&& aRange)
104 -> std::enable_if_t<
105 !std::is_same_v<T, std::decay_t<typename decltype(begin(
106 std::declval<const std::decay_t<
107 NestedRange>&>()))::value_type>>,
108 FlatRange<T, NestedRange>> {
109 return FlatRange<T, NestedRange>{std::forward<NestedRange>(aRange)};
112 } // namespace detail
114 template <typename T, typename NestedRange>
115 auto Flatten(NestedRange&& aRange) -> decltype(auto) {
116 return detail::Flatten<T>(std::forward<NestedRange>(aRange));
119 } // namespace mozilla::dom::quota
121 #endif