// Protocol Buffers - Google's data interchange format
// Copyright 2026 Google LLC.  All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd

#include "upb/message/unknown_fields.h"

#include <stddef.h>
#include <stdint.h>
#include <string.h>

#include "upb/base/string_view.h"
#include "upb/mem/arena.h"
#include "upb/mem/internal/arena.h"
#include "upb/message/internal/extension.h"
#include "upb/message/internal/message.h"
#include "upb/message/internal/types.h"
#include "upb/mini_table/extension.h"
#include "upb/mini_table/field.h"
#include "upb/wire/encode.h"
#include "upb/wire/encode_extension.h"
#include "upb/wire/eps_copy_input_stream.h"
#include "upb/wire/reader.h"

// Must be last.
#include "upb/port/def.inc"

bool upb_Message_NextWireFormatUnknown(const struct upb_Message* msg,
                                       struct upb_Arena** arena,
                                       upb_StringView* data, uintptr_t* iter) {
  upb_MessageUnknown unknown;
  if (!upb_Message_NextUnknown2(msg, &unknown, iter)) {
    return false;
  }
  if (unknown.type == kUpb_MessageUnknownType_StringView) {
    *data = unknown.value.bytes;
    return true;
  }
  UPB_ASSERT(unknown.type == kUpb_MessageUnknownType_NonCanonicalExtension);
  if (!*arena) {
    *arena = upb_Arena_New();
    if (!*arena) {
      return false;
    }
  }
  upb_EncodeStatus status =
      upb_EncodeExtension(unknown.value.extension, *arena, data,
                          /*encode_options=*/0);
  if (status != kUpb_EncodeStatus_Ok) {
    return false;
  }
  return true;
}

static upb_FindUnknownRet2 upb_FindUnknownRet2_ParseError(void) {
  return (upb_FindUnknownRet2){.status = kUpb_FindUnknown_ParseError};
}

upb_FindUnknownRet2 upb_Message_FindUnknown2(const struct upb_Message* msg,
                                             uint32_t field_number,
                                             int depth_limit) {
  depth_limit = depth_limit ? depth_limit : 100;
  upb_FindUnknownRet2 ret;
  ret.iter = kUpb_Message_UnknownBegin;
  while (upb_Message_NextUnknown2(msg, &ret.unknown, &ret.iter)) {
    if (ret.unknown.type == kUpb_MessageUnknownType_StringView) {
      upb_EpsCopyInputStream stream;
      const char* ptr = ret.unknown.value.bytes.data;
      upb_EpsCopyInputStream_Init(&stream, &ptr, ret.unknown.value.bytes.size);

      while (!upb_EpsCopyInputStream_IsDone(&stream, &ptr)) {
        uint32_t tag;
        const char* unknown_begin = ptr;
        ptr = upb_WireReader_ReadTag(ptr, &tag, &stream);
        if (!ptr) return upb_FindUnknownRet2_ParseError();
        if (field_number == upb_WireReader_GetFieldNumber(tag)) {
          upb_StringView data;
          ret.status = kUpb_FindUnknown_Ok;
          upb_EpsCopyCapture capture;
          upb_EpsCopyCapture_Start(&capture, &stream, unknown_begin);
          ptr = _upb_WireReader_SkipValue(ptr, tag, depth_limit, &stream);
          if (!ptr || !upb_EpsCopyCapture_End(&capture, &stream, ptr, &data)) {
            return upb_FindUnknownRet2_ParseError();
          }
          ret.unknown.value.bytes = data;
          return ret;
        }

        ptr = _upb_WireReader_SkipValue(ptr, tag, depth_limit, &stream);
        if (!ptr) return upb_FindUnknownRet2_ParseError();
      }
    } else if (ret.unknown.type ==
               kUpb_MessageUnknownType_NonCanonicalExtension) {
      uint32_t ext_field_number = upb_MiniTableField_Number(
          upb_Extension_MiniTableField(ret.unknown.value.extension));
      if (ext_field_number == field_number) {
        ret.status = kUpb_FindUnknown_Ok;
        return ret;
      }
    }
  }
  ret.status = kUpb_FindUnknown_NotPresent;
  ret.unknown.type = kUpb_MessageUnknownType_StringView;
  ret.unknown.value.bytes.data = NULL;
  ret.unknown.value.bytes.size = 0;
  ret.iter = kUpb_Message_UnknownBegin;
  return ret;
}

upb_Message_DeleteUnknownStatus upb_Message_DeleteUnknown2(
    struct upb_Message* msg, struct upb_MessageUnknown* data, uintptr_t* iter,
    struct upb_Arena* arena) {
  UPB_ASSERT(!upb_Message_IsFrozen(msg));
  UPB_ASSERT(*iter != kUpb_Message_UnknownBegin);
  upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
  UPB_ASSERT(in);
  UPB_ASSERT(*iter <= in->size);
  upb_TaggedAuxPtr unknown_ptr = in->aux_data[*iter - 1];

  if (data->type == kUpb_MessageUnknownType_NonCanonicalExtension) {
    UPB_ASSERT(upb_TaggedAuxPtr_IsNonCanonicalExtension(unknown_ptr));
    // When the unknown is a non-canonical extension, we just remove it from the
    // aux data array.
    in->aux_data[*iter - 1] = upb_TaggedAuxPtr_Null();
    return upb_Message_NextUnknown2(msg, data, iter)
               ? kUpb_DeleteUnknown_IterUpdated
               : kUpb_DeleteUnknown_DeletedLast;
  }

  UPB_ASSERT(upb_TaggedAuxPtr_IsUnknownStringView(unknown_ptr));
  upb_StringView* unknown = upb_TaggedPtrAux_StringViewRepr(unknown_ptr);
  UPB_ASSERT(data->type == kUpb_MessageUnknownType_StringView);
  upb_StringView* data_bytes = &data->value.bytes;
  if (unknown->data == data_bytes->data && unknown->size == data_bytes->size) {
    // Remove whole field
    in->aux_data[*iter - 1] = upb_TaggedAuxPtr_Null();
  } else if (unknown->data == data_bytes->data) {
    // Strip prefix
    unknown->data += data_bytes->size;
    unknown->size -= data_bytes->size;
    *data_bytes = *unknown;
    return kUpb_DeleteUnknown_IterUpdated;
  } else if (unknown->data + unknown->size ==
             data_bytes->data + data_bytes->size) {
    // Truncate existing field
    unknown->size -= data_bytes->size;
    if (!upb_TaggedAuxPtr_IsUnknownAliased(unknown_ptr)) {
      in->aux_data[*iter - 1] =
          upb_TaggedAuxPtr_MakeUnknownDataAliased(unknown);
    }
  } else {
    UPB_ASSERT(unknown->data < data_bytes->data &&
               unknown->data + unknown->size >
                   data_bytes->data + data_bytes->size);
    // Split in the middle
    upb_StringView* prefix = unknown;
    upb_StringView* suffix = upb_Arena_Malloc(arena, sizeof(upb_StringView));
    if (!suffix) {
      return kUpb_DeleteUnknown_AllocFail;
    }
    if (!UPB_PRIVATE(_upb_Message_ReserveSlot)(msg, arena)) {
      return kUpb_DeleteUnknown_AllocFail;
    }
    in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
    if (*iter != in->size) {
      // Shift later entries down so that unknown field ordering is preserved
      memmove(&in->aux_data[*iter + 1], &in->aux_data[*iter],
              sizeof(upb_TaggedAuxPtr) * (in->size - *iter));
    }
    in->aux_data[*iter] = upb_TaggedAuxPtr_MakeUnknownDataAliased(suffix);
    if (!upb_TaggedAuxPtr_IsUnknownAliased(unknown_ptr)) {
      in->aux_data[*iter - 1] = upb_TaggedAuxPtr_MakeUnknownDataAliased(prefix);
    }
    in->size++;
    suffix->data = data_bytes->data + data_bytes->size;
    suffix->size = (prefix->data + prefix->size) - suffix->data;
    prefix->size = data_bytes->data - prefix->data;
  }
  return upb_Message_NextUnknown2(msg, data, iter)
             ? kUpb_DeleteUnknown_IterUpdated
             : kUpb_DeleteUnknown_DeletedLast;
}

upb_Message_DeleteUnknownStatus upb_Message_DeleteUnknown(
    struct upb_Message* msg, upb_StringView* data, uintptr_t* iter,
    struct upb_Arena* arena) {
  upb_MessageUnknown unknown;
  unknown.type = kUpb_MessageUnknownType_StringView;
  unknown.value.bytes = *data;

  upb_Message_DeleteUnknownStatus res =
      upb_Message_DeleteUnknown2(msg, &unknown, iter, arena);
  UPB_ASSERT(unknown.type == kUpb_MessageUnknownType_StringView);
  if (res == kUpb_DeleteUnknown_IterUpdated ||
      res == kUpb_DeleteUnknown_DeletedLast) {
    // the unknown data remains the same on the result of
    // kUpb_DeleteUnknown_AllocFail.
    *data = unknown.value.bytes;
  }
  return res;
}
