// BSD 3-Clause License
//
// Copyright (c) 2025, Woven by Toyota.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * 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.
//
// * 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.

#pragma once

#include <maliput/common/error.h>

#include <rust/cxx.h>

namespace rust {
namespace behavior {

/// Customized error handling for Rust bindings.
/// See https://cxx.rs/binding/result.html#returning-result-from-c-to-rust
/// for more details.
template <typename Try, typename Fail>
static void trycatch(Try &&func, Fail &&fail) noexcept {
  try {
    func();
  } catch (const maliput::common::road_network_description_parser_error &e) {
    fail("maliput::common::road_network_description_parser_error: " + std::string(e.what()));
  } catch (const maliput::common::road_geometry_construction_error &e) {
    fail("maliput::common::road_geometry_construction_error: " + std::string(e.what()));
  } catch (const maliput::common::rulebook_error &e) {
    fail("maliput::common::rulebook_error: " + std::string(e.what()));
  } catch (const maliput::common::rule_registry_error &e) {
    fail("maliput::common::rule_registry_error: " + std::string(e.what()));
  } catch (const maliput::common::traffic_light_book_error &e) {
    fail("maliput::common::traffic_light_book_error: " + std::string(e.what()));
  } catch (const maliput::common::phase_book_error &e) {
    fail("maliput::common::phase_book_error: " + std::string(e.what()));
  } catch (const maliput::common::state_provider_error &e) {
    fail("maliput::common::state_provider_error: " + std::string(e.what()));
  } catch (const maliput::common::assertion_error &e) {
    fail("maliput::common::assertion_error: " + std::string(e.what()));
  } catch (const maliput::common::maliput_error &e) {
    fail("maliput::common::maliput_error: " + std::string(e.what()));
  } catch (const std::exception &e) {
    fail("std::exception: " + std::string(e.what()));
  } catch (...) {
    fail("Unknown error type: " +
         std::string(typeid(std::current_exception()).name()));
  }
}

}  // namespace behavior
}  // namespace rust
