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

#include "chromeos/components/onc/onc_mapper.h"

#include <utility>

#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "chromeos/components/onc/onc_signature.h"

namespace chromeos {
namespace onc {

Mapper::Mapper() = default;

Mapper::~Mapper() = default;

base::Value Mapper::MapValue(const OncValueSignature& signature,
                             const base::Value& onc_value,
                             bool* error) {
  switch (onc_value.type()) {
    case base::Value::Type::DICT: {
      if (signature.onc_type != base::Value::Type::DICT) {
        *error = true;
        return {};
      }
      return base::Value(MapObject(signature, onc_value.GetDict(), error));
    }
    case base::Value::Type::LIST: {
      if (signature.onc_type != base::Value::Type::LIST) {
        *error = true;
        return {};
      }
      return base::Value(MapArray(signature, onc_value.GetList(), error));
    }
    default: {
      if ((signature.onc_type == base::Value::Type::DICT) ||
          (signature.onc_type == base::Value::Type::LIST)) {
        *error = true;
        return {};
      }
      return MapPrimitive(signature, onc_value, error);
    }
  }
}

base::Value::Dict Mapper::MapObject(const OncValueSignature& signature,
                                    const base::Value::Dict& onc_object,
                                    bool* error) {
  base::Value::Dict result;

  bool found_unknown_field = false;
  MapFields(signature, onc_object, &found_unknown_field, error, &result);
  if (found_unknown_field)
    *error = true;
  return result;
}

base::Value Mapper::MapPrimitive(const OncValueSignature& signature,
                                 const base::Value& onc_primitive,
                                 bool* error) {
  return onc_primitive.Clone();
}

void Mapper::MapFields(const OncValueSignature& object_signature,
                       const base::Value::Dict& onc_object,
                       bool* found_unknown_field,
                       bool* nested_error,
                       base::Value::Dict* result) {
  for (const auto [field_name, onc_value] : onc_object) {
    bool current_field_unknown = false;
    base::Value result_value = MapField(field_name, object_signature, onc_value,
                                        &current_field_unknown, nested_error);

    if (current_field_unknown)
      *found_unknown_field = true;
    else if (!result_value.is_none())
      result->Set(field_name, std::move(result_value));
    else
      DCHECK(*nested_error);
  }
}

base::Value Mapper::MapField(const std::string& field_name,
                             const OncValueSignature& object_signature,
                             const base::Value& onc_value,
                             bool* found_unknown_field,
                             bool* error) {
  const OncFieldSignature* field_signature =
      GetFieldSignature(object_signature, field_name);

  if (field_signature != nullptr) {
    DCHECK(field_signature->value_signature != nullptr)
        << "Found missing value signature at field '" << field_name << "'.";

    return MapValue(*field_signature->value_signature, onc_value, error);
  }
  DVLOG(1) << "Found unknown field name: '" << field_name << "'";
  *found_unknown_field = true;
  return {};
}

base::Value::List Mapper::MapArray(const OncValueSignature& array_signature,
                                   const base::Value::List& onc_array,
                                   bool* nested_error) {
  DCHECK(array_signature.onc_array_entry_signature != nullptr)
      << "Found missing onc_array_entry_signature.";

  base::Value::List result_array;
  int original_index = 0;
  for (const auto& entry : onc_array) {
    bool error = false;
    base::Value result_entry =
        MapEntry(original_index, *array_signature.onc_array_entry_signature,
                 entry, &error);
    if (!error) {
      result_array.Append(std::move(result_entry));
    }

    *nested_error |= error;
    ++original_index;
  }
  return result_array;
}

base::Value Mapper::MapEntry(int index,
                             const OncValueSignature& signature,
                             const base::Value& onc_value,
                             bool* error) {
  return MapValue(signature, onc_value, error);
}

}  // namespace onc
}  // namespace chromeos