# Copyright 2023 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

# DO NOT EDIT! This file is generated by generate_fuchsia_patch.py.
#
# To make changes, update and run ./generate_fuchsia_patch.py.

# Patch the fit::function implementation for use in Pigweed:
#
#   - Use PW_ASSERT instead of __builtin_abort.
#   - Temporarily disable sanitizers when invoking a function for b/241567321.
#
diff --git a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/function.h b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/function.h
--- a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/function.h
+++ b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/function.h
@@ -18,6 +18,8 @@
 #include <utility>

 #include "../nullable.h"
+#include "pw_assert/assert.h"
+#include "pw_preprocessor/compiler.h"

 namespace fit {
 namespace internal {
@@ -88,7 +90,7 @@ inline const void* unshared_target_type_id(void* /*bits*/, const void* impl_ops)
 // elsewhere in the header as an inline variable.
 template <typename Unused = void>
 struct null_target {
-  static void invoke(void* /*bits*/) { __builtin_abort(); }
+  static void invoke(void* /*bits*/) { PW_ASSERT(false); }

   static const target_ops<void> ops;

@@ -507,7 +509,8 @@ class function_base<inline_target_size, require_inline, Result(Args...), Allocat
   // Note that fit::callback will release the target immediately after
   // invoke() (also affecting any share()d copies).
   // Aborts if the function's target is empty.
-  Result invoke(Args... args) const {
+  // TODO: b/241567321 - Remove "no sanitize" after pw_protobuf is fixed.
+  Result invoke(Args... args) const PW_NO_SANITIZE("function") {
     // Down cast the ops to the derived type that this function was instantiated
     // with, which includes the invoke function.
     //
@@ -537,7 +540,7 @@ class function_base<inline_target_size, require_inline, Result(Args...), Allocat
   template <typename SharedFunction>
   void copy_shared_target_to(SharedFunction& copy) {
     copy.destroy_target();
-    assert(base::ops() == &shared_target_type<SharedFunction>::ops);
+    PW_ASSERT(base::ops() == &shared_target_type<SharedFunction>::ops);
     shared_target_type<SharedFunction>::copy_shared_ptr(base::bits(), copy.bits());
     copy.set_ops(base::ops());
   }
@@ -567,7 +570,7 @@ class function_base<inline_target_size, require_inline, Result(Args...), Allocat
   void check_target_type() const {
     if (target_type<Callable>::ops.target_type_id(nullptr, &target_type<Callable>::ops) !=
         base::target_type_id()) {
-      __builtin_abort();
+      PW_ASSERT(false);
     }
   }
 };
diff --git a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/nullable.h b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/nullable.h
--- a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/nullable.h
+++ b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/nullable.h
@@ -11,6 +11,8 @@
 #include <type_traits>
 #include <utility>

+#include "pw_assert/assert.h"
+
 namespace fit {

 // Determines whether a type can be compared with nullptr.
@@ -130,25 +132,25 @@ class nullable<T, true> final {
     if (has_value()) {
       return value_;
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }
   constexpr const T& value() const& {
     if (has_value()) {
       return value_;
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }
   constexpr T&& value() && {
     if (has_value()) {
       return std::move(value_);
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }
   constexpr const T&& value() const&& {
     if (has_value()) {
       return std::move(value_);
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }

   template <typename U = T>
diff --git a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/result.h b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/result.h
--- a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/result.h
+++ b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/result.h
@@ -55,6 +55,8 @@
 //                               // fit::result with a different "success" vluae type (or
 //                               // fit::result<E>).

+#include "pw_assert/assert.h"
+
 namespace fit {

 // Convenience type to indicate failure without elaboration.
@@ -286,25 +288,25 @@ class [[nodiscard]] result<E, T> {
     if (is_error()) {
       return storage_.error_or_value.error;
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }
   constexpr const E& error_value() const& {
     if (is_error()) {
       return storage_.error_or_value.error;
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }
   constexpr E&& error_value() && {
     if (is_error()) {
       return std::move(storage_.error_or_value.error);
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }
   constexpr const E&& error_value() const&& {
     if (is_error()) {
       return std::move(storage_.error_or_value.error);
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }

   // Moves the underlying error and returns it as an instance of fit::error, simplifying
@@ -315,7 +317,7 @@ class [[nodiscard]] result<E, T> {
     if (is_error()) {
       return error<E>(std::move(storage_.error_or_value.error));
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }

   // Accessors for the underlying value.
@@ -325,25 +327,25 @@ class [[nodiscard]] result<E, T> {
     if (is_ok()) {
       return storage_.error_or_value.value;
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }
   constexpr const T& value() const& {
     if (is_ok()) {
       return storage_.error_or_value.value;
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }
   constexpr T&& value() && {
     if (is_ok()) {
       return std::move(storage_.error_or_value.value);
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }
   constexpr const T&& value() const&& {
     if (is_ok()) {
       return std::move(storage_.error_or_value.value);
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }

   // Moves the underlying value and returns it as an instance of fit::success, simplifying
@@ -354,7 +356,7 @@ class [[nodiscard]] result<E, T> {
     if (is_ok()) {
       return success<T>(std::move(storage_.error_or_value.value));
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }

   // Contingent accessors for the underlying value.
@@ -383,13 +385,13 @@ class [[nodiscard]] result<E, T> {
     if (is_ok()) {
       return ::fit::internal::arrow_operator<T>::forward(storage_.error_or_value.value);
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }
   constexpr decltype(auto) operator->() const {
     if (is_ok()) {
       return ::fit::internal::arrow_operator<T>::forward(storage_.error_or_value.value);
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }

   // Accessors for the underlying value. This is a syntax sugar for value().
@@ -412,7 +414,7 @@ class [[nodiscard]] result<E, T> {
       storage_.error_or_value.error += std::move(error.value_);
       return *this;
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }

   // Maps a result<E, T> to a result<E2, T> by transforming the error through
@@ -523,25 +525,25 @@ class [[nodiscard]] result<E> {
     if (is_error()) {
       return storage_.error_or_value.error;
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }
   constexpr const E& error_value() const& {
     if (is_error()) {
       return storage_.error_or_value.error;
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }
   constexpr E&& error_value() && {
     if (is_error()) {
       return std::move(storage_.error_or_value.error);
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }
   constexpr const E&& error_value() const&& {
     if (is_error()) {
       return std::move(storage_.error_or_value.error);
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }

   // Moves the underlying error and returns it as an instance of fit::error, simplifying
@@ -552,7 +554,7 @@ class [[nodiscard]] result<E> {
     if (is_error()) {
       return error<E>(std::move(storage_.error_or_value.error));
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }

   // Augments the error value of the result with the given value. The operator E::operator+=(F) must
@@ -566,7 +568,7 @@ class [[nodiscard]] result<E> {
       storage_.error_or_value.error += std::move(error.value_);
       return *this;
     }
-    __builtin_abort();
+    PW_ASSERT(false);
   }

   // Maps a result<E, T> to a result<E2, T> by transforming the error through
diff --git a/third_party/fuchsia/repo/sdk/lib/fit/test/function_tests.cc b/third_party/fuchsia/repo/sdk/lib/fit/test/function_tests.cc
--- a/third_party/fuchsia/repo/sdk/lib/fit/test/function_tests.cc
+++ b/third_party/fuchsia/repo/sdk/lib/fit/test/function_tests.cc
@@ -4,7 +4,6 @@

 #include <lib/fit/function.h>
 #include <lib/stdcompat/bit.h>
-#include <zircon/compiler.h>

 #include <algorithm>
 #include <array>
@@ -15,6 +14,8 @@

 #include <zxtest/zxtest.h>

+#include "pw_polyfill/language_feature_macros.h"
+
 namespace {

 using ::std::size_t;
@@ -1029,8 +1030,8 @@ TEST(FunctionTests, callback_with_custom_allocator) {
   EXPECT_EQ(1, cbheapdestroy);
 }

-__CONSTINIT const fit::function<void()> kDefaultConstructed;
-__CONSTINIT const fit::function<void()> kNullptrConstructed(nullptr);
+PW_CONSTINIT const fit::function<void()> kDefaultConstructed;
+PW_CONSTINIT const fit::function<void()> kNullptrConstructed(nullptr);

 TEST(FunctionTests, null_constructors_are_constexpr) {
   EXPECT_EQ(kDefaultConstructed, nullptr);
