// WARNING: This file is machine generated by fidlgen.

#pragma once

#include <fidl/test/protocols/cpp/fidl.h>

#include "lib/fidl/cpp/fuzzing/traits.h"
#include "lib/fidl/cpp/internal/header.h"
// For ::std::max_element().
#include <algorithm>
// For uint64_t.
#include <stdint.h>

namespace fuzzing {

using obj_type = ::fidl::test::protocols::obj_type;
using WithErrorSyntax_ResponseAsStruct_Response =
    ::fidl::test::protocols::WithErrorSyntax_ResponseAsStruct_Response;
using WithErrorSyntax_ResponseAsStruct_Result =
    ::fidl::test::protocols::WithErrorSyntax_ResponseAsStruct_Result;
using WithErrorSyntax_ErrorAsPrimitive_Response =
    ::fidl::test::protocols::WithErrorSyntax_ErrorAsPrimitive_Response;
using WithErrorSyntax_ErrorAsPrimitive_Result =
    ::fidl::test::protocols::WithErrorSyntax_ErrorAsPrimitive_Result;
using WithErrorSyntax_ErrorAsEnum_Response =
    ::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Response;
using ErrorEnun = ::fidl::test::protocols::ErrorEnun;
using WithErrorSyntax_ErrorAsEnum_Result =
    ::fidl::test::protocols::WithErrorSyntax_ErrorAsEnum_Result;

template <>
struct MinSize<obj_type> {
  operator size_t() { return sizeof(uint64_t); }
};
template <>
struct Allocate<obj_type> {
  obj_type operator()(FuzzInput* src, size_t* size) {
    obj_type out;
    uint64_t selector;
    ZX_ASSERT(*size >= sizeof(uint64_t));
    ZX_ASSERT(src->CopyObject(&selector));
    *size = sizeof(uint64_t);

    switch (selector % 2) {
      case 0:
        out = obj_type::NONE;
        break;
      case 1:
        out = obj_type::SOCKET;
        break;
    }

    return out;
  }
};
template <>
struct MinSize<WithErrorSyntax_ResponseAsStruct_Response> {
  operator size_t() {
    return MinSize<int64_t>() + MinSize<int64_t>() + MinSize<int64_t>();
  }
};
template <>
struct Allocate<WithErrorSyntax_ResponseAsStruct_Response> {
  WithErrorSyntax_ResponseAsStruct_Response operator()(FuzzInput* src,
                                                       size_t* size) {
    ZX_ASSERT(*size >= MinSize<WithErrorSyntax_ResponseAsStruct_Response>());
    const size_t slack_per_member =
        (*size - MinSize<WithErrorSyntax_ResponseAsStruct_Response>()) / 3;
    WithErrorSyntax_ResponseAsStruct_Response out;
    size_t out_size;
    out_size = MinSize<int64_t>() + slack_per_member;
    out.a = Allocate<int64_t>{}(src, &out_size);
    out_size = MinSize<int64_t>() + slack_per_member;
    out.b = Allocate<int64_t>{}(src, &out_size);
    out_size = MinSize<int64_t>() + slack_per_member;
    out.c = Allocate<int64_t>{}(src, &out_size);
    return out;
  }
};
template <>
struct MinSize<WithErrorSyntax_ResponseAsStruct_Result> {
  operator size_t() {
    size_t sizes[] = {0, MinSize<WithErrorSyntax_ResponseAsStruct_Response>(),
                      MinSize<uint32_t>()};
    return 1 + *std::max_element(sizes, sizes + 2 + 1);
  }
};
template <>
struct Allocate<WithErrorSyntax_ResponseAsStruct_Result> {
  static_assert(2 > 0, "xunion must have at least one member");

  WithErrorSyntax_ResponseAsStruct_Result operator()(FuzzInput* src,
                                                     size_t* size) {
    ZX_ASSERT(*size >= MinSize<WithErrorSyntax_ResponseAsStruct_Result>());

    uint8_t selector;
    ZX_ASSERT(src->CopyBytes(&selector, 1));
    (*size)++;

    WithErrorSyntax_ResponseAsStruct_Result out;
    switch (selector % 2) {
      case 0: {
        out.set_response(
            Allocate<WithErrorSyntax_ResponseAsStruct_Response>{}(src, size));
        break;
      }
      case 1: {
        out.set_err(Allocate<uint32_t>{}(src, size));
        break;
      }
    }

    return out;
  }
};
template <>
struct MinSize<WithErrorSyntax_ErrorAsPrimitive_Response> {
  operator size_t() { return MinSize<uint8_t>(); }
};
template <>
struct Allocate<WithErrorSyntax_ErrorAsPrimitive_Response> {
  WithErrorSyntax_ErrorAsPrimitive_Response operator()(FuzzInput* src,
                                                       size_t* size) {
    ZX_ASSERT(*size >= MinSize<WithErrorSyntax_ErrorAsPrimitive_Response>());
    const size_t slack_per_member =
        (*size - MinSize<WithErrorSyntax_ErrorAsPrimitive_Response>()) / 1;
    WithErrorSyntax_ErrorAsPrimitive_Response out;
    size_t out_size;
    out_size = MinSize<uint8_t>() + slack_per_member;
    out.__reserved = Allocate<uint8_t>{}(src, &out_size);
    return out;
  }
};
template <>
struct MinSize<WithErrorSyntax_ErrorAsPrimitive_Result> {
  operator size_t() {
    size_t sizes[] = {0, MinSize<WithErrorSyntax_ErrorAsPrimitive_Response>(),
                      MinSize<uint32_t>()};
    return 1 + *std::max_element(sizes, sizes + 2 + 1);
  }
};
template <>
struct Allocate<WithErrorSyntax_ErrorAsPrimitive_Result> {
  static_assert(2 > 0, "xunion must have at least one member");

  WithErrorSyntax_ErrorAsPrimitive_Result operator()(FuzzInput* src,
                                                     size_t* size) {
    ZX_ASSERT(*size >= MinSize<WithErrorSyntax_ErrorAsPrimitive_Result>());

    uint8_t selector;
    ZX_ASSERT(src->CopyBytes(&selector, 1));
    (*size)++;

    WithErrorSyntax_ErrorAsPrimitive_Result out;
    switch (selector % 2) {
      case 0: {
        out.set_response(
            Allocate<WithErrorSyntax_ErrorAsPrimitive_Response>{}(src, size));
        break;
      }
      case 1: {
        out.set_err(Allocate<uint32_t>{}(src, size));
        break;
      }
    }

    return out;
  }
};
template <>
struct MinSize<WithErrorSyntax_ErrorAsEnum_Response> {
  operator size_t() { return MinSize<uint8_t>(); }
};
template <>
struct Allocate<WithErrorSyntax_ErrorAsEnum_Response> {
  WithErrorSyntax_ErrorAsEnum_Response operator()(FuzzInput* src,
                                                  size_t* size) {
    ZX_ASSERT(*size >= MinSize<WithErrorSyntax_ErrorAsEnum_Response>());
    const size_t slack_per_member =
        (*size - MinSize<WithErrorSyntax_ErrorAsEnum_Response>()) / 1;
    WithErrorSyntax_ErrorAsEnum_Response out;
    size_t out_size;
    out_size = MinSize<uint8_t>() + slack_per_member;
    out.__reserved = Allocate<uint8_t>{}(src, &out_size);
    return out;
  }
};
template <>
struct MinSize<ErrorEnun> {
  operator size_t() { return sizeof(uint64_t); }
};
template <>
struct Allocate<ErrorEnun> {
  ErrorEnun operator()(FuzzInput* src, size_t* size) {
    ErrorEnun out;
    uint64_t selector;
    ZX_ASSERT(*size >= sizeof(uint64_t));
    ZX_ASSERT(src->CopyObject(&selector));
    *size = sizeof(uint64_t);

    switch (selector % 2) {
      case 0:
        out = ErrorEnun::ERR_FOO;
        break;
      case 1:
        out = ErrorEnun::ERR_BAR;
        break;
    }

    return out;
  }
};
template <>
struct MinSize<WithErrorSyntax_ErrorAsEnum_Result> {
  operator size_t() {
    size_t sizes[] = {0, MinSize<WithErrorSyntax_ErrorAsEnum_Response>(),
                      MinSize<ErrorEnun>()};
    return 1 + *std::max_element(sizes, sizes + 2 + 1);
  }
};
template <>
struct Allocate<WithErrorSyntax_ErrorAsEnum_Result> {
  static_assert(2 > 0, "xunion must have at least one member");

  WithErrorSyntax_ErrorAsEnum_Result operator()(FuzzInput* src, size_t* size) {
    ZX_ASSERT(*size >= MinSize<WithErrorSyntax_ErrorAsEnum_Result>());

    uint8_t selector;
    ZX_ASSERT(src->CopyBytes(&selector, 1));
    (*size)++;

    WithErrorSyntax_ErrorAsEnum_Result out;
    switch (selector % 2) {
      case 0: {
        out.set_response(
            Allocate<WithErrorSyntax_ErrorAsEnum_Response>{}(src, size));
        break;
      }
      case 1: {
        out.set_err(Allocate<ErrorEnun>{}(src, size));
        break;
      }
    }

    return out;
  }
};

}  // namespace fuzzing
