Bug 1642744 [wpt PR 23920] - [ScrollTimeline] Update compositor timeline from blink...
[gecko.git] / mfbt / Algorithm.h
blobc79a74a75a10cb9c175824cbd5430a5383d359e0
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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* A polyfill for `<algorithm>`. */
9 #ifndef mozilla_Algorithm_h
10 #define mozilla_Algorithm_h
12 #include "mozilla/Result.h"
14 #include <iterator>
15 #include <type_traits>
17 namespace mozilla {
19 // Returns true if all elements in the range [aFirst, aLast)
20 // satisfy the predicate aPred.
21 template <class Iter, class Pred>
22 constexpr bool AllOf(Iter aFirst, Iter aLast, Pred aPred) {
23 for (; aFirst != aLast; ++aFirst) {
24 if (!aPred(*aFirst)) {
25 return false;
28 return true;
31 namespace detail {
32 template <typename Transform, typename SrcIter>
33 using ArrayElementTransformType = typename std::invoke_result_t<
34 Transform, typename std::iterator_traits<SrcIter>::reference>;
36 template <typename Transform, typename SrcIter>
37 struct TransformTraits {
38 using result_type = ArrayElementTransformType<Transform, SrcIter>;
40 using result_ok_type = typename result_type::ok_type;
41 using result_err_type = typename result_type::err_type;
43 } // namespace detail
45 // An algorithm similar to TransformAbortOnErr combined with a condition that
46 // allows to skip elements. At most std::distance(aIter, aEnd) elements will be
47 // inserted into aDst.
49 // Type requirements, in addition to those specified in TransformAbortOnErr:
50 // - Cond must be compatible with signature
51 // bool (const SrcIter::value_type&)
52 template <typename SrcIter, typename DstIter, typename Cond, typename Transform>
53 Result<Ok,
54 typename detail::TransformTraits<Transform, SrcIter>::result_err_type>
55 TransformIfAbortOnErr(SrcIter aIter, SrcIter aEnd, DstIter aDst, Cond aCond,
56 Transform aTransform) {
57 for (; aIter != aEnd; ++aIter) {
58 if (!aCond(static_cast<std::add_const_t<
59 typename std::iterator_traits<SrcIter>::value_type>&>(
60 *aIter))) {
61 continue;
64 auto res = aTransform(*aIter);
65 if (res.isErr()) {
66 return Err(res.unwrapErr());
69 *aDst++ = res.unwrap();
71 return Ok{};
74 template <typename SrcRange, typename DstIter, typename Cond,
75 typename Transform>
76 auto TransformIfAbortOnErr(SrcRange& aRange, DstIter aDst, Cond aCond,
77 Transform aTransform) {
78 using std::begin;
79 using std::end;
80 return TransformIfAbortOnErr(begin(aRange), end(aRange), aDst, aCond,
81 aTransform);
84 // An algorithm similar to std::transform, adapted to error handling based on
85 // mozilla::Result<V, E>. It iterates through the input range [aIter, aEnd) and
86 // inserts the result of applying aTransform to each element into aDst, if
87 // aTransform returns a success result. On the first error result, iterating is
88 // aborted, and the error result is returned as an overall result. If all
89 // transformations return a success result, Ok is returned as an overall result.
91 // Type requirements:
92 // - SrcIter must be an InputIterator.
93 // - DstIter must be an OutputIterator.
94 // - Transform must be compatible with signature
95 // Result<DstIter::value_type, E> (SrcIter::reference)
96 template <typename SrcIter, typename DstIter, typename Transform>
97 Result<Ok,
98 typename detail::TransformTraits<Transform, SrcIter>::result_err_type>
99 TransformAbortOnErr(SrcIter aIter, SrcIter aEnd, DstIter aDst,
100 Transform aTransform) {
101 return TransformIfAbortOnErr(
102 aIter, aEnd, aDst, [](const auto&) { return true; }, aTransform);
105 template <typename SrcRange, typename DstIter, typename Transform>
106 auto TransformAbortOnErr(SrcRange& aRange, DstIter aDst, Transform aTransform) {
107 using std::begin;
108 using std::end;
109 return TransformIfAbortOnErr(
110 begin(aRange), end(aRange), aDst, [](const auto&) { return true; },
111 aTransform);
114 } // namespace mozilla
116 #endif // mozilla_Algorithm_h