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

#include <fidl/test/nullable/cpp/natural_types.h>

#include "lib/fidl/cpp/internal/natural_types_implementation.h"

//
// Domain objects definitions (i.e. "natural types" in unified bindings)
//
namespace fidl {
namespace test {
namespace nullable {
extern "C" const fidl_type_t fidl_test_nullable_StructWithNullableVectorTable;
const fidl_type_t* StructWithNullableVector::FidlType =
    &fidl_test_nullable_StructWithNullableVectorTable;

void StructWithNullableVector::Encode(
    ::fidl::Encoder* _encoder, size_t _offset,
    cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  if (::fidl::IsMemcpyCompatible<StructWithNullableVector>::value) {
    memcpy(_encoder->template GetPtr<StructWithNullableVector>(_offset), this,
           sizeof(StructWithNullableVector));
  } else {
    ::fidl::Encode(_encoder, &val, _offset + 0);
  }
}

void StructWithNullableVector::Decode(::fidl::Decoder* _decoder,
                                      StructWithNullableVector* _value,
                                      size_t _offset) {
  if (::fidl::IsMemcpyCompatible<StructWithNullableVector>::value) {
    memcpy(_value, _decoder->template GetPtr<StructWithNullableVector>(_offset),
           sizeof(StructWithNullableVector));
  } else {
    ::fidl::Decode(_decoder, &_value->val, _offset + 0);
  }
}

zx_status_t StructWithNullableVector::Clone(
    StructWithNullableVector* _result) const {
  zx_status_t _status = ::fidl::Clone(val, &_result->val);
  if (_status != ZX_OK) return _status;
  return ZX_OK;
}

extern "C" const fidl_type_t fidl_test_nullable_StructWithNullableUnionTable;
const fidl_type_t* StructWithNullableUnion::FidlType =
    &fidl_test_nullable_StructWithNullableUnionTable;

void StructWithNullableUnion::Encode(
    ::fidl::Encoder* _encoder, size_t _offset,
    cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  if (::fidl::IsMemcpyCompatible<StructWithNullableUnion>::value) {
    memcpy(_encoder->template GetPtr<StructWithNullableUnion>(_offset), this,
           sizeof(StructWithNullableUnion));
  } else {
    ::fidl::Encode(_encoder, &val, _offset + 0);
  }
}

void StructWithNullableUnion::Decode(::fidl::Decoder* _decoder,
                                     StructWithNullableUnion* _value,
                                     size_t _offset) {
  if (::fidl::IsMemcpyCompatible<StructWithNullableUnion>::value) {
    memcpy(_value, _decoder->template GetPtr<StructWithNullableUnion>(_offset),
           sizeof(StructWithNullableUnion));
  } else {
    ::fidl::Decode(_decoder, &_value->val, _offset + 0);
  }
}

zx_status_t StructWithNullableUnion::Clone(
    StructWithNullableUnion* _result) const {
  zx_status_t _status = ::fidl::Clone(val, &_result->val);
  if (_status != ZX_OK) return _status;
  return ZX_OK;
}

extern "C" const fidl_type_t fidl_test_nullable_StructWithNullableStructTable;
const fidl_type_t* StructWithNullableStruct::FidlType =
    &fidl_test_nullable_StructWithNullableStructTable;

void StructWithNullableStruct::Encode(
    ::fidl::Encoder* _encoder, size_t _offset,
    cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  if (::fidl::IsMemcpyCompatible<StructWithNullableStruct>::value) {
    memcpy(_encoder->template GetPtr<StructWithNullableStruct>(_offset), this,
           sizeof(StructWithNullableStruct));
  } else {
    ::fidl::Encode(_encoder, &val, _offset + 0);
  }
}

void StructWithNullableStruct::Decode(::fidl::Decoder* _decoder,
                                      StructWithNullableStruct* _value,
                                      size_t _offset) {
  if (::fidl::IsMemcpyCompatible<StructWithNullableStruct>::value) {
    memcpy(_value, _decoder->template GetPtr<StructWithNullableStruct>(_offset),
           sizeof(StructWithNullableStruct));
  } else {
    ::fidl::Decode(_decoder, &_value->val, _offset + 0);
  }
}

zx_status_t StructWithNullableStruct::Clone(
    StructWithNullableStruct* _result) const {
  zx_status_t _status = ::fidl::Clone(val, &_result->val);
  if (_status != ZX_OK) return _status;
  return ZX_OK;
}

extern "C" const fidl_type_t fidl_test_nullable_StructWithNullableStringTable;
const fidl_type_t* StructWithNullableString::FidlType =
    &fidl_test_nullable_StructWithNullableStringTable;

void StructWithNullableString::Encode(
    ::fidl::Encoder* _encoder, size_t _offset,
    cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  if (::fidl::IsMemcpyCompatible<StructWithNullableString>::value) {
    memcpy(_encoder->template GetPtr<StructWithNullableString>(_offset), this,
           sizeof(StructWithNullableString));
  } else {
    ::fidl::Encode(_encoder, &val, _offset + 0);
  }
}

void StructWithNullableString::Decode(::fidl::Decoder* _decoder,
                                      StructWithNullableString* _value,
                                      size_t _offset) {
  if (::fidl::IsMemcpyCompatible<StructWithNullableString>::value) {
    memcpy(_value, _decoder->template GetPtr<StructWithNullableString>(_offset),
           sizeof(StructWithNullableString));
  } else {
    ::fidl::Decode(_decoder, &_value->val, _offset + 0);
  }
}

zx_status_t StructWithNullableString::Clone(
    StructWithNullableString* _result) const {
  zx_status_t _status = ::fidl::Clone(val, &_result->val);
  if (_status != ZX_OK) return _status;
  return ZX_OK;
}

#ifdef __Fuchsia__

extern "C" const fidl_type_t fidl_test_nullable_StructWithNullableRequestTable;
const fidl_type_t* StructWithNullableRequest::FidlType =
    &fidl_test_nullable_StructWithNullableRequestTable;

void StructWithNullableRequest::Encode(
    ::fidl::Encoder* _encoder, size_t _offset,
    cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  if (::fidl::IsMemcpyCompatible<StructWithNullableRequest>::value) {
    memcpy(_encoder->template GetPtr<StructWithNullableRequest>(_offset), this,
           sizeof(StructWithNullableRequest));
  } else {
    ::fidl::Encode(_encoder, &val, _offset + 0);
  }
}

void StructWithNullableRequest::Decode(::fidl::Decoder* _decoder,
                                       StructWithNullableRequest* _value,
                                       size_t _offset) {
  if (::fidl::IsMemcpyCompatible<StructWithNullableRequest>::value) {
    memcpy(_value,
           _decoder->template GetPtr<StructWithNullableRequest>(_offset),
           sizeof(StructWithNullableRequest));
  } else {
    ::fidl::Decode(_decoder, &_value->val, _offset + 0);
  }
}

zx_status_t StructWithNullableRequest::Clone(
    StructWithNullableRequest* _result) const {
  zx_status_t _status = ::fidl::Clone(val, &_result->val);
  if (_status != ZX_OK) return _status;
  return ZX_OK;
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__

extern "C" const fidl_type_t fidl_test_nullable_StructWithNullableProtocolTable;
const fidl_type_t* StructWithNullableProtocol::FidlType =
    &fidl_test_nullable_StructWithNullableProtocolTable;

void StructWithNullableProtocol::Encode(
    ::fidl::Encoder* _encoder, size_t _offset,
    cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  if (::fidl::IsMemcpyCompatible<StructWithNullableProtocol>::value) {
    memcpy(_encoder->template GetPtr<StructWithNullableProtocol>(_offset), this,
           sizeof(StructWithNullableProtocol));
  } else {
    ::fidl::Encode(_encoder, &val, _offset + 0);
  }
}

void StructWithNullableProtocol::Decode(::fidl::Decoder* _decoder,
                                        StructWithNullableProtocol* _value,
                                        size_t _offset) {
  if (::fidl::IsMemcpyCompatible<StructWithNullableProtocol>::value) {
    memcpy(_value,
           _decoder->template GetPtr<StructWithNullableProtocol>(_offset),
           sizeof(StructWithNullableProtocol));
  } else {
    ::fidl::Decode(_decoder, &_value->val, _offset + 0);
  }
}

zx_status_t StructWithNullableProtocol::Clone(
    StructWithNullableProtocol* _result) const {
  zx_status_t _status = ::fidl::Clone(val, &_result->val);
  if (_status != ZX_OK) return _status;
  return ZX_OK;
}
#endif  // __Fuchsia__

#ifdef __Fuchsia__

extern "C" const fidl_type_t fidl_test_nullable_StructWithNullableHandleTable;
const fidl_type_t* StructWithNullableHandle::FidlType =
    &fidl_test_nullable_StructWithNullableHandleTable;

void StructWithNullableHandle::Encode(
    ::fidl::Encoder* _encoder, size_t _offset,
    cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  if (::fidl::IsMemcpyCompatible<StructWithNullableHandle>::value) {
    memcpy(_encoder->template GetPtr<StructWithNullableHandle>(_offset), this,
           sizeof(StructWithNullableHandle));
  } else {
    ::fidl::Encode(_encoder, &val, _offset + 0,
                   ::fidl::HandleInformation{
                       .object_type = ZX_OBJ_TYPE_VMO,
                       .rights = 0x80000000,
                   });
  }
}

void StructWithNullableHandle::Decode(::fidl::Decoder* _decoder,
                                      StructWithNullableHandle* _value,
                                      size_t _offset) {
  if (::fidl::IsMemcpyCompatible<StructWithNullableHandle>::value) {
    memcpy(_value, _decoder->template GetPtr<StructWithNullableHandle>(_offset),
           sizeof(StructWithNullableHandle));
  } else {
    ::fidl::Decode(_decoder, &_value->val, _offset + 0);
  }
}

zx_status_t StructWithNullableHandle::Clone(
    StructWithNullableHandle* _result) const {
  zx_status_t _status = ::fidl::Clone(val, &_result->val);
  if (_status != ZX_OK) return _status;
  return ZX_OK;
}
#endif  // __Fuchsia__

extern "C" const fidl_type_t fidl_test_nullable_SimpleUnionTable;
const fidl_type_t* SimpleUnion::FidlType = &fidl_test_nullable_SimpleUnionTable;

SimpleUnion::SimpleUnion() {}

SimpleUnion::~SimpleUnion() { Destroy(); }

SimpleUnion::SimpleUnion(SimpleUnion&& other) : tag_(other.tag_) {
  switch (tag_) {
    case ::fidl::test::nullable::SimpleUnion::Tag::kA:
      a_ = std::move(other.a_);
      break;
    case ::fidl::test::nullable::SimpleUnion::Tag::kB:
      b_ = std::move(other.b_);
      break;
    case static_cast<fidl_xunion_tag_t>(
        ::fidl::test::nullable::SimpleUnion::Tag::Invalid):
      break;
  }
}

SimpleUnion& SimpleUnion::operator=(SimpleUnion&& other) {
  if (this != &other) {
    Destroy();
    tag_ = other.tag_;
    switch (tag_) {
      case ::fidl::test::nullable::SimpleUnion::Tag::kA:
        a_ = std::move(other.a_);
        break;
      case ::fidl::test::nullable::SimpleUnion::Tag::kB:
        b_ = std::move(other.b_);
        break;
      case static_cast<fidl_xunion_tag_t>(
          ::fidl::test::nullable::SimpleUnion::Tag::Invalid):
        break;
    }
  }
  return *this;
}

SimpleUnion SimpleUnion::WithA(int32_t&& val) {
  SimpleUnion result;
  result.set_a(std::move(val));
  return result;
}
SimpleUnion SimpleUnion::WithB(float&& val) {
  SimpleUnion result;
  result.set_b(std::move(val));
  return result;
}

void SimpleUnion::Encode(
    ::fidl::Encoder* encoder, size_t offset,
    cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  const size_t length_before = encoder->CurrentLength();
  const size_t handles_before = encoder->CurrentHandleCount();

  size_t envelope_offset = 0;

  switch (Which()) {
    case ::fidl::test::nullable::SimpleUnion::Tag::kA: {
      envelope_offset = encoder->Alloc(
          ::fidl::EncodingInlineSize<int32_t, ::fidl::Encoder>(encoder));
      ::fidl::Encode(encoder, &a_, envelope_offset);
      break;
    }
    case ::fidl::test::nullable::SimpleUnion::Tag::kB: {
      envelope_offset = encoder->Alloc(
          ::fidl::EncodingInlineSize<float, ::fidl::Encoder>(encoder));
      ::fidl::Encode(encoder, &b_, envelope_offset);
      break;
    }
    default:
      break;
  }

  fidl_xunion_t* xunion = encoder->GetPtr<fidl_xunion_t>(offset);
  assert(xunion->envelope.presence == FIDL_ALLOC_ABSENT);

  if (envelope_offset) {
    xunion->tag = tag_;
    xunion->envelope.num_bytes =
        static_cast<uint32_t>(encoder->CurrentLength() - length_before);
    xunion->envelope.num_handles =
        static_cast<uint32_t>(encoder->CurrentHandleCount() - handles_before);
    xunion->envelope.presence = FIDL_ALLOC_PRESENT;
  }
}

void SimpleUnion::Decode(::fidl::Decoder* decoder, SimpleUnion* value,
                         size_t offset) {
  fidl_xunion_t* xunion = decoder->GetPtr<fidl_xunion_t>(offset);

  if (!xunion->envelope.data) {
    value->EnsureStorageInitialized(static_cast<fidl_xunion_tag_t>(
        ::fidl::test::nullable::SimpleUnion::Tag::Invalid));
    return;
  }

  value->EnsureStorageInitialized(xunion->tag);

  const size_t envelope_offset = decoder->GetOffset(xunion->envelope.data);

  switch (value->tag_) {
    case ::fidl::test::nullable::SimpleUnion::Tag::kA:
      ::fidl::Decode(decoder, &value->a_, envelope_offset);
      break;
    case ::fidl::test::nullable::SimpleUnion::Tag::kB:
      ::fidl::Decode(decoder, &value->b_, envelope_offset);
      break;
    default:
      break;
  }
}

zx_status_t SimpleUnion::Clone(SimpleUnion* result) const {
  result->Destroy();
  result->tag_ = tag_;
  switch (tag_) {
    case ::fidl::test::nullable::SimpleUnion::Tag::Invalid:
      return ZX_OK;
    case ::fidl::test::nullable::SimpleUnion::Tag::kA:
      return ::fidl::Clone(a_, &result->a_);
    case ::fidl::test::nullable::SimpleUnion::Tag::kB:
      return ::fidl::Clone(b_, &result->b_);
    default:
      return ZX_OK;
  }
}

SimpleUnion& SimpleUnion::set_a(int32_t value) {
  EnsureStorageInitialized(::fidl::test::nullable::SimpleUnion::Tag::kA);
  a_ = std::move(value);
  return *this;
}

SimpleUnion& SimpleUnion::set_b(float value) {
  EnsureStorageInitialized(::fidl::test::nullable::SimpleUnion::Tag::kB);
  b_ = std::move(value);
  return *this;
}

void SimpleUnion::Destroy() {
  switch (tag_) {
    case ::fidl::test::nullable::SimpleUnion::Tag::kA:
      break;
    case ::fidl::test::nullable::SimpleUnion::Tag::kB:
      break;

    default:
      break;
  }
  tag_ = static_cast<fidl_xunion_tag_t>(
      ::fidl::test::nullable::SimpleUnion::Tag::Invalid);
}

void SimpleUnion::EnsureStorageInitialized(::fidl_xunion_tag_t tag) {
  if (tag_ != tag) {
    Destroy();
    tag_ = tag;
    switch (tag_) {
      case static_cast<fidl_xunion_tag_t>(
          ::fidl::test::nullable::SimpleUnion::Tag::Invalid):
        break;
      case ::fidl::test::nullable::SimpleUnion::Tag::kA:
        new (&a_) int32_t();
        break;
      case ::fidl::test::nullable::SimpleUnion::Tag::kB:
        new (&b_) float();
        break;
      default:
        break;
    }
  }
}

extern "C" const fidl_type_t fidl_test_nullable_Int32WrapperTable;
const fidl_type_t* Int32Wrapper::FidlType =
    &fidl_test_nullable_Int32WrapperTable;

void Int32Wrapper::Encode(
    ::fidl::Encoder* _encoder, size_t _offset,
    cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
  if (::fidl::IsMemcpyCompatible<Int32Wrapper>::value) {
    memcpy(_encoder->template GetPtr<Int32Wrapper>(_offset), this,
           sizeof(Int32Wrapper));
  } else {
    ::fidl::Encode(_encoder, &val, _offset + 0);
  }
}

void Int32Wrapper::Decode(::fidl::Decoder* _decoder, Int32Wrapper* _value,
                          size_t _offset) {
  if (::fidl::IsMemcpyCompatible<Int32Wrapper>::value) {
    memcpy(_value, _decoder->template GetPtr<Int32Wrapper>(_offset),
           sizeof(Int32Wrapper));
  } else {
    ::fidl::Decode(_decoder, &_value->val, _offset + 0);
  }
}

zx_status_t Int32Wrapper::Clone(Int32Wrapper* _result) const {
  zx_status_t _status = ::fidl::Clone(val, &_result->val);
  if (_status != ZX_OK) return _status;
  return ZX_OK;
}

}  // namespace nullable
}  // namespace test
}  // namespace fidl
