910e62b5创建于 1月15日历史提交
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_PROTOBUF_H_
#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_PROTOBUF_H_

#include "base/numerics/safe_conversions.h"
#include "mojo/public/cpp/bindings/array_traits.h"
#include "third_party/protobuf/src/google/protobuf/repeated_field.h"

namespace mojo {

template <typename T>
struct ArrayTraits<::google::protobuf::RepeatedPtrField<T>> {
  using Element = T;

  static bool IsNull(const ::google::protobuf::RepeatedPtrField<T>& input) {
    // Always convert RepeatedPtrField to a non-null mojom array.
    return false;
  }

  static T* GetData(::google::protobuf::RepeatedPtrField<T>& input) {
    return input.data();
  }

  static const T* GetData(
      const ::google::protobuf::RepeatedPtrField<T>& input) {
    return input.data();
  }

  static T& GetAt(::google::protobuf::RepeatedPtrField<T>& input,
                  size_t index) {
    return input.at(index);
  }

  static const T& GetAt(const ::google::protobuf::RepeatedPtrField<T>& input,
                        size_t index) {
    return input.at(index);
  }

  static size_t GetSize(const ::google::protobuf::RepeatedPtrField<T>& input) {
    return input.size();
  }

  static bool Resize(::google::protobuf::RepeatedPtrField<T>& input,
                     size_t new_size) {
    if (!base::IsValueInRangeForNumericType<int>(new_size)) {
      return false;
    }

    // We call Reserve() to set the capacity and then add elements to increase
    // the container size to the requested value. We can't rely on Reserve()
    // alone as that will resize the container but size() will still report the
    // previous number of elements which will cause deserialization failures.
    // Unfortunately there isn't an AddRange() or similar function available so
    // we need to add elements one at a time in a loop.
    int requested_size = base::checked_cast<int>(new_size);
    input.Reserve(requested_size);
    while (input.size() < requested_size) {
      input.Add();
    }

    return true;
  }
};

}  // namespace mojo

#endif  // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_PROTOBUF_H_