/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

#ifndef mozilla_OriginTrials_h
#error "Don't include this file directly, include mozilla/OriginTrials.h instead"
#endif


#ifndef mozilla_OriginTrials_ffi_h
#define mozilla_OriginTrials_ffi_h

/* Generated with cbindgen:0.29.2 */

#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>
#include "mozilla/Assertions.h"

namespace mozilla {
namespace origin_trials_ffi {

enum class OriginTrial : uint8_t {
  TestTrial = 1,
  CoepCredentialless = 2,
  PrivateAttributionV2 = 3,
  MLS = 4,
  MAX,
};

union OriginTrialResult {
  enum class Tag : uint8_t {
    Ok,
    BufferTooSmall,
    MismatchedPayloadSize,
    InvalidSignature,
    UnknownVersion,
    UnsupportedThirdPartyToken,
    UnexpectedUsageInNonThirdPartyToken,
    MalformedPayload,
    ExpiredToken,
    UnknownTrial,
    OriginMismatch,
  };

  struct Ok_Body {
    Tag tag;
    OriginTrial trial;
  };

  struct MismatchedPayloadSize_Body {
    Tag tag;
    uintptr_t expected;
    uintptr_t actual;
  };

  struct {
    Tag tag;
  };
  Ok_Body ok;
  MismatchedPayloadSize_Body mismatched_payload_size;

  static OriginTrialResult Ok(const OriginTrial &trial) {
    OriginTrialResult result;
    ::new (&result.ok.trial) (OriginTrial)(trial);
    result.tag = Tag::Ok;
    return result;
  }

  bool IsOk() const {
    return tag == Tag::Ok;
  }

  const Ok_Body& AsOk() const {
    MOZ_DIAGNOSTIC_ASSERT(IsOk());
    return ok;
  }

  static OriginTrialResult BufferTooSmall() {
    OriginTrialResult result;
    result.tag = Tag::BufferTooSmall;
    return result;
  }

  bool IsBufferTooSmall() const {
    return tag == Tag::BufferTooSmall;
  }

  static OriginTrialResult MismatchedPayloadSize(const uintptr_t &expected,
                                                 const uintptr_t &actual) {
    OriginTrialResult result;
    ::new (&result.mismatched_payload_size.expected) (uintptr_t)(expected);
    ::new (&result.mismatched_payload_size.actual) (uintptr_t)(actual);
    result.tag = Tag::MismatchedPayloadSize;
    return result;
  }

  bool IsMismatchedPayloadSize() const {
    return tag == Tag::MismatchedPayloadSize;
  }

  const MismatchedPayloadSize_Body& AsMismatchedPayloadSize() const {
    MOZ_DIAGNOSTIC_ASSERT(IsMismatchedPayloadSize());
    return mismatched_payload_size;
  }

  static OriginTrialResult InvalidSignature() {
    OriginTrialResult result;
    result.tag = Tag::InvalidSignature;
    return result;
  }

  bool IsInvalidSignature() const {
    return tag == Tag::InvalidSignature;
  }

  static OriginTrialResult UnknownVersion() {
    OriginTrialResult result;
    result.tag = Tag::UnknownVersion;
    return result;
  }

  bool IsUnknownVersion() const {
    return tag == Tag::UnknownVersion;
  }

  static OriginTrialResult UnsupportedThirdPartyToken() {
    OriginTrialResult result;
    result.tag = Tag::UnsupportedThirdPartyToken;
    return result;
  }

  bool IsUnsupportedThirdPartyToken() const {
    return tag == Tag::UnsupportedThirdPartyToken;
  }

  static OriginTrialResult UnexpectedUsageInNonThirdPartyToken() {
    OriginTrialResult result;
    result.tag = Tag::UnexpectedUsageInNonThirdPartyToken;
    return result;
  }

  bool IsUnexpectedUsageInNonThirdPartyToken() const {
    return tag == Tag::UnexpectedUsageInNonThirdPartyToken;
  }

  static OriginTrialResult MalformedPayload() {
    OriginTrialResult result;
    result.tag = Tag::MalformedPayload;
    return result;
  }

  bool IsMalformedPayload() const {
    return tag == Tag::MalformedPayload;
  }

  static OriginTrialResult ExpiredToken() {
    OriginTrialResult result;
    result.tag = Tag::ExpiredToken;
    return result;
  }

  bool IsExpiredToken() const {
    return tag == Tag::ExpiredToken;
  }

  static OriginTrialResult UnknownTrial() {
    OriginTrialResult result;
    result.tag = Tag::UnknownTrial;
    return result;
  }

  bool IsUnknownTrial() const {
    return tag == Tag::UnknownTrial;
  }

  static OriginTrialResult OriginMismatch() {
    OriginTrialResult result;
    result.tag = Tag::OriginMismatch;
    return result;
  }

  bool IsOriginMismatch() const {
    return tag == Tag::OriginMismatch;
  }
};

/// A struct that allows you to configure how validation on works, and pass
/// state to the signature verification.
struct OriginTrialValidationParams {
  /// Verify a given signature against the signed data.
  bool (*verify_signature)(const uint8_t *signature,
                           uintptr_t signature_len,
                           const uint8_t *data,
                           uintptr_t data_len,
                           void *user_data);
  /// Returns whether a given origin, which is passed as the first two
  /// arguments, and guaranteed to be valid UTF-8, passes the validation for a
  /// given invocation.
  bool (*matches_origin)(const uint8_t *origin,
                         uintptr_t len,
                         bool is_subdomain,
                         bool is_third_party,
                         bool is_usage_subset,
                         void *user_data);
  /// A pointer with user-supplied data that will be passed down to the
  /// other functions in this method.
  void *user_data;
};

extern "C" {

OriginTrialResult origin_trials_parse_and_validate_token(const uint8_t *bytes,
                                                         uintptr_t len,
                                                         const OriginTrialValidationParams *params);

}  // extern "C"

}  // namespace origin_trials_ffi
}  // namespace mozilla

#endif  // mozilla_OriginTrials_ffi_h
