// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  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

#ifndef GOOGLE_PROTOBUF_MICRO_STRING_H__
#define GOOGLE_PROTOBUF_MICRO_STRING_H__

#include <cstddef>
#include <cstdint>

#include "absl/base/config.h"
#include "absl/log/absl_check.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/arena.h"

// must be last:
#include "google/protobuf/port_def.inc"

namespace google {
namespace protobuf {
namespace internal {

struct MicroStringTestPeer;

// The MicroString class holds a `char` buffer.
// The basic usage provides `Set` and `Get` functions that deal with
// `absl::string_view`.
// It has several layers of optimizations for different sized payloads, as well
// as some features for unowned payloads.
//
// It can be in one of several representations, each with their own properties:
//  - Inline: When enabled, Inline instances store the bytes inlined in the
//            class. They require no memory allocation.
//            This representation holds the size in the first (lsb) byte (left
//            shifted to allow for tags) and the rest of the bytes are the data.
//            The inline buffer can span beyond the `MicroString` class (see
//            `MicroStringExtra` below). To support this most operations take
//            the `inline_capacity` dynamically so that `MicroStringExtra` and
//            the runtime can pass the real buffer size.
//  - MicroRep: Cheapest out of line representation. It is two `uint8_t` for
//              capacity and size, then the char buffer.
//  - LargeRep: The following representations use LargeRep as the header,
//              differentiating themselves via the `capacity` field.
//    * kOwned: A `char` array follows the base. Similar to MicroRep, but with
//              2^32 byte limit, instead of 2^8.
//    * kAlias: The base points into an aliased unowned buffer. The base itself
//              is owned. Used for `SetAlias`.
//              Copying the MicroString will make its own copy of the data, as
//              alias lifetime is not guaranteed beyond the original message.
//    * kUnowned: Similar to kAlias, but the base is also unowned. Both the base
//                and the payload are guaranteed immutable and immortal. Used
//                for global strings, like non-empty default values.
//                Requires no memory allocation. Copying the MicroString will
//                maintain the unowned status and require no memory allocation.
//    * kString: The object holds a StringRep. The base points into the
//               `std::string` instance. Used for `SetString` to allow taking
//               ownership of `std::string` payloads.
//               Copying the MicroString will not maintain the kString state, as
//               it is unnecessary. The copy will use normal reps.
//
//
// All the functions that write to the inline space take the inline capacity as
// a parameter. This allows the subclass to extend the capacity while the base
// class handles the logic. It also allows external callers, like reflection, to
// pass the dynamically known capacity.
class PROTOBUF_EXPORT MicroString {
  struct LargeRep {
    char* payload;
    uint32_t size;
    // One of LargeRepKind, or the capacity for the owned buffer.
    uint32_t capacity;

    absl::string_view view() const { return {payload, size}; }
    char* owned_head() {
      ABSL_DCHECK_GE(capacity, kOwned);
      return reinterpret_cast<char*>(this + 1);
    }

    void SetExternalBuffer(absl::string_view buffer) {
      payload = const_cast<char*>(buffer.data());
      size = buffer.size();
    }

    void SetInitialSize(size_t size) {
      PoisonMemoryRegion(owned_head() + size, capacity - size);
      this->size = size;
    }

    void Unpoison() { UnpoisonMemoryRegion(owned_head(), capacity); }

    void ChangeSize(size_t new_size) {
      PoisonMemoryRegion(owned_head() + new_size, capacity - new_size);
      UnpoisonMemoryRegion(owned_head(), new_size);
      size = new_size;
    }
  };

  struct MicroRep {
    uint8_t size;
    uint8_t capacity;

    char* data() { return reinterpret_cast<char*>(this + 1); }
    const char* data() const { return reinterpret_cast<const char*>(this + 1); }
    absl::string_view view() const { return {data(), size}; }

    void SetInitialSize(uint8_t size) {
      PoisonMemoryRegion(data() + size, capacity - size);
      this->size = size;
    }

    void Unpoison() { UnpoisonMemoryRegion(data(), capacity); }

    void ChangeSize(uint8_t new_size) {
      PoisonMemoryRegion(data() + new_size, capacity - new_size);
      UnpoisonMemoryRegion(data(), new_size);
      size = new_size;
    }
  };

 public:
  // We don't allow extra capacity in big-endian because it is harder to manage
  // the pointer to the MicroString "base".
  static constexpr bool kAllowExtraCapacity = IsLittleEndian();
  static constexpr size_t kInlineCapacity = sizeof(uintptr_t) - 1;
  static constexpr size_t kMaxMicroRepCapacity = 256 - sizeof(MicroRep);

  // Empty string.
  constexpr MicroString() : rep_() {}

  explicit MicroString(Arena*) : MicroString() {}

  MicroString(Arena* arena, const MicroString& other)
      : MicroString(FromOtherTag{}, other, arena) {}

  // Trivial destructor.
  // The payload must be destroyed via `Destroy()` when not in an arena. If
  // using arenas, no destruction is necessary and calls to `Destroy()` are
  // invalid.
  ~MicroString() = default;

  union UnownedPayload {
    LargeRep payload;
    // We use a union to be able to get an unaligned pointer for the
    // payload in the constexpr constructor. `for_tag + kIsLargeRepTag` is
    // equivalent to `reinterpret_cast<uintptr_t>(&payload) | kIsLargeRepTag`
    // but works during constant evaluation.
    char for_tag[1];

    // To match the LazyString API.
    auto get() const { return payload.view(); }
  };
  constexpr MicroString(const UnownedPayload& unowned_input)  // NOLINT
      : rep_(const_cast<char*>(unowned_input.for_tag + kIsLargeRepTag)) {}

  // Like the constructor above, but for DynamicMessage where we don't have a
  // generated UnownedPayload to pass.
  // The instance created has to be destroyed with
  // `DestroyDefaultValuePrototype`.
  static MicroString MakeDefaultValuePrototype(absl::string_view default_value);
  void DestroyDefaultValuePrototype();

  // Resets value to the default constructor state.
  // Disregards initial value of rep_ (so this is the *ONLY* safe method to call
  // after construction or when reinitializing after becoming the active field
  // in a oneof union).
  void InitDefault() { rep_ = nullptr; }

  // Destroys the payload.
  // REQUIRES: no arenas. Trying to destroy a string constructed with arenas is
  // invalid and there is no checking for it.
  void Destroy() {
    if (!is_inline()) DestroySlow();
  }

  // Resets the object to the empty string.
  // Does not necessarily release any memory.
  void Clear() {
    if (is_inline()) {
      set_inline_size(0);
      return;
    }
    ClearSlow();
  }

  // Sets the payload to `other`. Copy behavior depends on the kind of payload.
  void Set(const MicroString& other, Arena* arena) {
    SetFromOtherImpl(*this, other, arena);
  }

  void Set(const MicroString& other, Arena* arena, size_t inline_capacity) {
    // Unowned property gets propagated, even if we have a rep already.
    if (other.is_large_rep() && other.large_rep_kind() == kUnowned) {
      if (arena == nullptr) Destroy();
      rep_ = other.rep_;
      return;
    }
    Set(other.Get(), arena, inline_capacity);
  }

  // Sets the payload to `data`. Always copies the data.
  void Set(absl::string_view data, Arena* arena) {
    SetMaybeConstant(*this, data, arena);
  }
  void Set(absl::string_view data, Arena* arena, size_t inline_capacity) {
    SetImpl(data, arena, inline_capacity);
  }

  // Extra overloads to allow for other implicit conversions.
  // Eg types that convert to `std::string` (like
  // `std::reference_wrapper<std::string>`).
  template <typename... Args>
  void Set(const std::string& data, Args... args) {
    Set(absl::string_view(data), args...);
  }
  template <typename... Args>
  void Set(std::string&& data, Args... args) {
    SetString(std::move(data), args...);
  }
  template <typename... Args>
  void Set(const char* data, Args... args) {
    Set(absl::string_view(data), args...);
  }

  // Sets the payload to `data`. Might copy the data or alias the input buffer.
  void SetAlias(absl::string_view data, Arena* arena,
                size_t inline_capacity = kInlineCapacity);

  // Set the payload to `unowned`. Will not allocate memory, but might free
  // memory if already set.
  void SetUnowned(const UnownedPayload& unowned_input, Arena* arena);

  // To match the API of ArenaStringPtr.
  // It resets the value to the passed default, trying to keep preexisting
  // buffer if we are on an arena. This reduces arena bloat when reusing a
  // message.
  void ClearToDefault(const UnownedPayload& unowned_input, Arena* arena);

  // Like above, but takes a prototype `MicroString` that has the unowned rep.
  // Used for reflection that does not have access to the `UnownedPayload`.
  void ClearToDefault(const MicroString& other, Arena* arena);

  // Set the string, but the input comes in individual chunks.
  // This function is designed to be called from the parser.
  // `size` is the expected total size of the string. It is ok to append fewer
  // bytes than `size`, but never more. The final size of the string will be
  // whatever was appended to it.
  // `size` is used as a hint to reserve space, but the implementation might
  // decide not to do so for very large values and just grow on append.
  //
  // The `setter` callback is passed an `append` callback that it can use to
  // append the chunks one by one.
  // Eg
  //
  // str.SetInChunks(10, arena, [](auto append) {
  //   append("12345");
  //   append("67890");
  // });
  //
  // The callback approach reduces the dispatch overhead to be done only once
  // instead of on each append call.
  template <typename F>
  void SetInChunks(size_t size, Arena* arena, F setter,
                   size_t inline_capacity = kInlineCapacity);

  // The capacity for write access of this string.
  // It can be 0 if the payload is not writable. For example, aliased buffers.
  size_t Capacity() const;

  size_t SpaceUsedExcludingSelfLong() const;

  absl::string_view Get() const {
    if (is_micro_rep()) {
      return micro_rep()->view();
    } else if (is_inline()) {
      return inline_view();
    } else {
      return large_rep()->view();
    }
  }

  // To be used by constexpr constructors of fields with non-empty default
  // values. It will alias `data` so it must be an immutable input, like a
  // literal string.
  static constexpr UnownedPayload MakeUnownedPayload(absl::string_view data) {
    return UnownedPayload{LargeRep{const_cast<char*>(data.data()),
                                   static_cast<uint32_t>(data.size()),
                                   kUnowned}};
  }

  void InternalSwap(MicroString* other,
                    size_t inline_capacity = kInlineCapacity) {
    std::swap_ranges(reinterpret_cast<char*>(this),
                     reinterpret_cast<char*>(this) + inline_capacity + 1,
                     reinterpret_cast<char*>(other));
  }

 protected:
  friend MicroStringTestPeer;

  struct StringRep : LargeRep {
    std::string str;
    void ResetBase() { SetExternalBuffer(str); }
  };

  static_assert(alignof(void*) >= 4, "We need two tag bits from pointers.");
  static constexpr uintptr_t kIsLargeRepTag = 0x1;
  static_assert(sizeof(UnownedPayload::for_tag) == kIsLargeRepTag,
                "See comment in for_tag declaration above.");

  static constexpr uintptr_t kIsMicroRepTag = 0x2;
  static constexpr int kTagShift = 2;
  static constexpr size_t kMaxInlineCapacity = 255 >> kTagShift;

  static_assert((kIsLargeRepTag & kIsMicroRepTag) == 0,
                "The tags are exclusive.");

  enum LargeRepKind {
    // The buffer is unowned, but the large_rep payload is owned.
    kAlias,
    // The whole payload is unowned.
    kUnowned,
    // The payload is a StringRep payload.
    kString,
    // An owned LargeRep+chars payload.
    // kOwned must be the last one for large_rep_kind() to work.
    kOwned
  };
  LargeRepKind large_rep_kind() const {
    ABSL_DCHECK(is_large_rep());
    size_t cap = large_rep()->capacity;
    return cap >= kOwned ? kOwned : static_cast<LargeRepKind>(cap);
  }

  // Micro-optimization: by using kIsMicroRepTag as 2, the MicroRep `rep_`
  // pointer (with the tag) is already pointing into the data buffer.
  static_assert(sizeof(MicroRep) == kIsMicroRepTag);
  MicroRep* micro_rep() const {
    ABSL_DCHECK(is_micro_rep());
    // NOTE: We use `-` instead of `&` so that the arithmetic gets folded into
    // offsets after the cast.
    // ie `micro_rep()->data()` cancel each other out.
    return reinterpret_cast<MicroRep*>(reinterpret_cast<uintptr_t>(rep_) -
                                       kIsMicroRepTag);
  }
  static size_t MicroRepSize(size_t capacity) {
    return sizeof(MicroRep) + capacity;
  }
  static size_t OwnedRepSize(size_t capacity) {
    return sizeof(LargeRep) + capacity;
  }

  LargeRep* large_rep() const {
    ABSL_DCHECK(is_large_rep());
    // NOTE: We use `-` instead of `&` so that the arithmetic gets folded into
    // offsets after the cast.
    return reinterpret_cast<LargeRep*>(reinterpret_cast<uintptr_t>(rep_) -
                                       kIsLargeRepTag);
  }
  StringRep* string_rep() const {
    ABSL_DCHECK_EQ(+kString, +large_rep_kind());
    return static_cast<StringRep*>(large_rep());
  }

  bool is_micro_rep() const {
    return (reinterpret_cast<uintptr_t>(rep_) & kIsMicroRepTag) ==
           kIsMicroRepTag;
  }
  bool is_large_rep() const {
    return (reinterpret_cast<uintptr_t>(rep_) & kIsLargeRepTag) ==
           kIsLargeRepTag;
  }
  bool is_inline() const { return !is_micro_rep() && !is_large_rep(); }
  size_t inline_size() const {
    ABSL_DCHECK(is_inline());
    return static_cast<uint8_t>(reinterpret_cast<uintptr_t>(rep_)) >> kTagShift;
  }
  void set_inline_size(size_t size) {
    size <<= kTagShift;
    PROTOBUF_ASSUME(size <= 0xFF);
    // Only overwrite the size byte to avoid clobbering the char bytes in case
    // of aliasing.
    rep_ = reinterpret_cast<void*>((reinterpret_cast<uintptr_t>(rep_) & ~0xFF) |
                                   size);
    ABSL_DCHECK(is_inline());
  }
  char* inline_head() {
    ABSL_DCHECK(is_inline());

    // In little-endian the layout is
    //    [ size ] [ chars... ]
    // while in big endian it is
    //    [ chars... ] [ size ]
    return IsLittleEndian() ? reinterpret_cast<char*>(&rep_) + 1
                            : reinterpret_cast<char*>(&rep_);
  }
  const char* inline_head() const {
    return const_cast<MicroString*>(this)->inline_head();
  }
  absl::string_view inline_view() const {
    return {inline_head(), inline_size()};
  }

  // These are templates so that they can implement the logic for the derived
  // types too. We need the full type to do the assignment properly.
  struct FromOtherTag {};
  template <typename Self>
  MicroString(FromOtherTag, const Self& other, Arena* arena) {
    if (other.is_inline()) {
      static_cast<Self&>(*this) = other;
      return;
    }
    // Init as empty and run the slow path.
    InitDefault();
    SetFromOtherSlow(other, arena, Self::kInlineCapacity);
  }

  template <typename Self>
  static void SetFromOtherImpl(Self& self, const Self& other, Arena* arena) {
    // If inline, just memcpy directly.
    // Use bitwise and because we don't want short circuiting. It adds extra
    // branches. Cast to `int` to silence -Wbitwise-instead-of-logical.
    if (static_cast<int>(self.is_inline()) &
        static_cast<int>(other.is_inline())) {
      self = other;
      return;
    }
    self.SetFromOtherSlow(other, arena, Self::kInlineCapacity);
  }

  // Sets the payload to `str`. Might copy the data or take ownership of `str`.
  void SetString(std::string&& data, Arena* arena,
                 size_t inline_capacity = kInlineCapacity);

  void SetFromOtherSlow(const MicroString& other, Arena* arena,
                        size_t inline_capacity);

  void ClearSlow();

  template <typename Self>
  static void SetMaybeConstant(Self& self, absl::string_view data,
                               Arena* arena) {
    const size_t size = data.size();
    if (PROTOBUF_BUILTIN_CONSTANT_P(size <= Self::kInlineCapacity) &&
        size <= Self::kInlineCapacity && self.is_inline()) {
      // Using a separate local variable allows the optimizer to merge the
      // writes better. We do a single write to memory on the assingment below.
      Self tmp;
      tmp.set_inline_size(size);
      if (size != 0) {
        memcpy(tmp.inline_head(), data.data(), data.size());
      }
      self = tmp;
      return;
    }
    self.SetImpl(data, arena, Self::kInlineCapacity);
  }
  void SetImpl(absl::string_view data, Arena* arena, size_t inline_capacity);

  void DestroySlow();

  // Allocate the corresponding rep, and sets its size and capacity.
  // The actual capacity might be larger than the requested one.
  // The data bytes are uninitialized.
  // rep_ is updated to point to the new rep without any cleanup of the old
  // value.
  MicroRep* AllocateMicroRep(size_t size, Arena* arena);
  LargeRep* AllocateOwnedRep(size_t size, Arena* arena);
  StringRep* AllocateStringRep(Arena* arena);

  void* rep_;
};

template <typename F>
void MicroString::SetInChunks(size_t size, Arena* arena, F setter,
                              size_t inline_capacity) {
  const auto invoke_setter = [&](char* p) {
    char* start = p;
    setter([&](absl::string_view chunk) {
      ABSL_DCHECK_LE(p - start + chunk.size(), size);
      memcpy(p, chunk.data(), chunk.size());
      p += chunk.size();
    });
    return p - start;
  };

  const auto do_inline = [&] {
    ABSL_DCHECK_LE(size, inline_capacity);
    set_inline_size(invoke_setter(inline_head()));
  };

  const auto do_micro = [&](MicroRep* r) {
    ABSL_DCHECK_LE(size, r->capacity);
    r->Unpoison();
    r->ChangeSize(invoke_setter(r->data()));
  };

  const auto do_owned = [&](LargeRep* r) {
    ABSL_DCHECK_LE(size, r->capacity);
    r->Unpoison();
    r->ChangeSize(invoke_setter(r->owned_head()));
  };

  const auto do_string = [&](StringRep* r) {
    r->str.clear();
    setter([&](absl::string_view chunk) {
      r->str.append(chunk.data(), chunk.size());
    });
    r->ResetBase();
  };

  if (is_inline()) {
    if (size <= inline_capacity) {
      return do_inline();
    }
  } else if (is_micro_rep()) {
    if (auto* r = micro_rep(); size <= r->capacity) {
      return do_micro(r);
    }
  } else if (is_large_rep()) {
    switch (large_rep_kind()) {
      case kOwned:
        if (auto* r = large_rep(); size <= r->capacity) {
          return do_owned(r);
        }
        break;
      case kString:
        return do_string(string_rep());
      case kAlias:
      case kUnowned:
        break;
    }
  }

  // Copied from ParseContext as an acceptable size that we can preallocate
  // without verifying.
  static constexpr size_t kSafeStringSize = 50000000;

  // We didn't have space for it, so allocate the space and dispatch.
  if (arena == nullptr) Destroy();

  if (size <= inline_capacity) {
    set_inline_size(0);
    do_inline();
  } else if (size <= kMaxMicroRepCapacity) {
    do_micro(AllocateMicroRep(size, arena));
  } else if (size <= kSafeStringSize) {
    do_owned(AllocateOwnedRep(size, arena));
  } else {
    // Fallback to using std::string and normal growth instead of reserving.
    do_string(AllocateStringRep(arena));
  }
}

// MicroStringExtra lays out the memory as:
//
//   [ MicroString ] [ extra char buffer ]
//
// which in little endian ends up as
//
//   [ char size/tag ] [ MicroStrings's inline space ] [ extra char buffer ]
//
// so from the inline_head() position we can access all the normal and extra
// buffer bytes.
//
// This does not work on bigendian so we disable Extra for now there.
template <size_t RequestedSpace>
class MicroStringExtraImpl : private MicroString {
  static constexpr size_t RoundUp(size_t n) {
    return (n + (alignof(MicroString) - 1)) & ~(alignof(MicroString) - 1);
  }

 public:
  // Round up to avoid padding
  static constexpr size_t kInlineCapacity =
      RoundUp(RequestedSpace + /* inline_size */ 1) - /* inline_size */ 1;

  static_assert(kInlineCapacity < MicroString::kMaxInlineCapacity,
                "Must fit with the tags.");

  constexpr MicroStringExtraImpl() {
    // Some compilers don't like to assert kAllowExtraCapacity directly, so make
    // the expression dependent.
    static_assert(static_cast<int>(RequestedSpace != 0) &
                  static_cast<int>(MicroString::kAllowExtraCapacity));
  }
  MicroStringExtraImpl(Arena* arena, const MicroStringExtraImpl& other)
      : MicroString(FromOtherTag{}, other, arena) {}

  using MicroString::Get;
  // Redefine the setters, passing the extended inline capacity.
  void Set(const MicroStringExtraImpl& other, Arena* arena) {
    SetFromOtherImpl(*this, other, arena);
  }
  void Set(absl::string_view data, Arena* arena) {
    SetMaybeConstant(*this, data, arena);
  }
  void Set(const std::string& data, Arena* arena) {
    Set(absl::string_view(data), arena);
  }
  void Set(const char* data, Arena* arena) {
    Set(absl::string_view(data), arena);
  }
  void Set(std::string&& str, Arena* arena) {
    MicroString::SetString(std::move(str), arena, kInlineCapacity);
  }

  void SetAlias(absl::string_view data, Arena* arena) {
    MicroString::SetAlias(data, arena, kInlineCapacity);
  }

  using MicroString::Destroy;

  size_t Capacity() const {
    return is_inline() ? kInlineCapacity : MicroString::Capacity();
  }

  void InternalSwap(MicroStringExtraImpl* other) {
    MicroString::InternalSwap(other, kInlineCapacity);
  }

  using MicroString::SpaceUsedExcludingSelfLong;

 private:
  friend MicroString;

  char extra_buffer_[kInlineCapacity - MicroString::kInlineCapacity];
};

// MicroStringExtra allows the user to specify the inline space.
// This will be used in conjunction with profiles that determine expected string
// sizes.
//
// MicroStringExtra<N> will contain at least `N` bytes of inline space, assuming
// inline strings are enabled in this platform.
// If inline strings are not enabled in this platform, then the argument is
// ignored and no inline space is provided.
// It could be rouneded up to prevent padding.
template <size_t InlineCapacity>
using MicroStringExtra =
    std::conditional_t<(!MicroString::kAllowExtraCapacity ||
                        InlineCapacity <= MicroString::kInlineCapacity),
                       MicroString, MicroStringExtraImpl<InlineCapacity>>;

}  // namespace internal
}  // namespace protobuf
}  // namespace google

#include "google/protobuf/port_undef.inc"

#endif  // GOOGLE_PROTOBUF_MICRO_STRING_H__
