blob: 33261f0c2fe8448afdaf14ae7c40dea0902ec1c6 [file] [log] [blame]
Alex Vakulenko66ec2922014-06-17 15:30:22 -07001// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BUFFET_COMMANDS_SCHEMA_UTILS_H_
6#define BUFFET_COMMANDS_SCHEMA_UTILS_H_
7
8#include <limits>
9#include <map>
10#include <memory>
11#include <string>
12#include <type_traits>
13#include <vector>
14
15#include <base/values.h>
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -070016#include <chromeos/any.h>
Alex Vakulenkoa8b95bc2014-08-27 11:00:57 -070017#include <chromeos/errors/error.h>
Alex Vakulenko66ec2922014-06-17 15:30:22 -070018
19namespace buffet {
20
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -070021class PropType;
Alex Vakulenko66ec2922014-06-17 15:30:22 -070022class PropValue;
23class ObjectSchema;
24
25namespace native_types {
26// C++ representation of object values.
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070027using Object = std::map<std::string, std::shared_ptr<const PropValue>>;
Alex Vakulenko66ec2922014-06-17 15:30:22 -070028} // namespace native_types
29// Converts an object to string.
30std::string ToString(const native_types::Object& obj);
31
32// InheritableAttribute class is used for specifying various command parameter
33// attributes that can be inherited from a base (parent) schema.
34// The |value| still specifies the actual attribute values, whether it
35// is inherited or overridden, while |is_inherited| can be used to identify
36// if the attribute was inherited (true) or overridden (false).
37template<typename T>
38class InheritableAttribute {
39 public:
40 InheritableAttribute() = default;
41 explicit InheritableAttribute(T val)
42 : value(std::move(val)), is_inherited(true) {}
43 InheritableAttribute(T val, bool inherited)
44 : value(std::move(val)), is_inherited(inherited) {}
45 T value{};
46 bool is_inherited{true};
47};
48
49// A bunch of helper function to create base::Value for specific C++ classes,
50// including vectors of types. These are used in template classes below
51// to simplify specialization logic.
Alex Vakulenko5f472062014-08-14 17:54:04 -070052std::unique_ptr<base::Value> TypedValueToJson(bool value,
53 chromeos::ErrorPtr* error);
54std::unique_ptr<base::Value> TypedValueToJson(int value,
55 chromeos::ErrorPtr* error);
56std::unique_ptr<base::Value> TypedValueToJson(double value,
57 chromeos::ErrorPtr* error);
Alex Vakulenko66ec2922014-06-17 15:30:22 -070058std::unique_ptr<base::Value> TypedValueToJson(const std::string& value,
Alex Vakulenko5f472062014-08-14 17:54:04 -070059 chromeos::ErrorPtr* error);
Alex Vakulenko66ec2922014-06-17 15:30:22 -070060std::unique_ptr<base::Value> TypedValueToJson(const native_types::Object& value,
Alex Vakulenko5f472062014-08-14 17:54:04 -070061 chromeos::ErrorPtr* error);
Alex Vakulenko66ec2922014-06-17 15:30:22 -070062template<typename T>
63std::unique_ptr<base::Value> TypedValueToJson(const std::vector<T>& values,
Alex Vakulenko5f472062014-08-14 17:54:04 -070064 chromeos::ErrorPtr* error) {
Alex Vakulenko66ec2922014-06-17 15:30:22 -070065 std::unique_ptr<base::ListValue> list(new base::ListValue);
66 for (const auto& v : values) {
67 auto json = TypedValueToJson(v, error);
68 if (!json)
69 return std::unique_ptr<base::Value>();
70 list->Append(json.release());
71 }
72 return std::move(list);
73}
74
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -070075// Similarly to TypedValueToJson() function above, the following overloaded
Alex Vakulenko66ec2922014-06-17 15:30:22 -070076// helper methods allow to extract specific C++ data types from base::Value.
77// Also used in template classes below to simplify specialization logic.
78bool TypedValueFromJson(const base::Value* value_in,
79 const ObjectSchema* object_schema,
Alex Vakulenko5f472062014-08-14 17:54:04 -070080 bool* value_out, chromeos::ErrorPtr* error);
Alex Vakulenko66ec2922014-06-17 15:30:22 -070081bool TypedValueFromJson(const base::Value* value_in,
82 const ObjectSchema* object_schema,
Alex Vakulenko5f472062014-08-14 17:54:04 -070083 int* value_out, chromeos::ErrorPtr* error);
Alex Vakulenko66ec2922014-06-17 15:30:22 -070084bool TypedValueFromJson(const base::Value* value_in,
85 const ObjectSchema* object_schema,
Alex Vakulenko5f472062014-08-14 17:54:04 -070086 double* value_out, chromeos::ErrorPtr* error);
Alex Vakulenko66ec2922014-06-17 15:30:22 -070087bool TypedValueFromJson(const base::Value* value_in,
88 const ObjectSchema* object_schema,
Alex Vakulenko5f472062014-08-14 17:54:04 -070089 std::string* value_out, chromeos::ErrorPtr* error);
Alex Vakulenko66ec2922014-06-17 15:30:22 -070090bool TypedValueFromJson(const base::Value* value_in,
91 const ObjectSchema* object_schema,
Alex Vakulenko5f472062014-08-14 17:54:04 -070092 native_types::Object* value_out,
93 chromeos::ErrorPtr* error);
Alex Vakulenko66ec2922014-06-17 15:30:22 -070094
95bool operator==(const native_types::Object& obj1,
96 const native_types::Object& obj2);
97
98// CompareValue is a helper function to help with implementing EqualsTo operator
99// for various data types. For most scalar types it is using operator==(),
100// however, for floating point values, rounding errors in binary representation
101// of IEEE floats/doubles can cause straight == comparison to fail for seemingly
102// equivalent values. For these, use approximate comparison with the error
103// margin equal to the epsilon value defined for the corresponding data type.
104// This is used when looking up values for implementation of OneOf constraints
105// which should work reliably for floating points also ("number" type).
106
107// Compare exact types using ==.
108template<typename T>
109inline typename std::enable_if<!std::is_floating_point<T>::value, bool>::type
110CompareValue(const T& v1, const T& v2) {
111 return v1 == v2;
112}
113
114// Compare non-exact types (such as double) using precision margin (epsilon).
115template<typename T>
116inline typename std::enable_if<std::is_floating_point<T>::value, bool>::type
117CompareValue(const T& v1, const T& v2) {
118 return std::abs(v1 - v2) <= std::numeric_limits<T>::epsilon();
119}
120
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -0700121// Converts PropValue to Any in a format understood by D-Bus data serialization.
122// Has special handling for Object types where native_types::Object are
Alex Vakulenko576c9792014-09-22 16:49:45 -0700123// converted to chromeos::VariantDictionary.
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -0700124chromeos::Any PropValueToDBusVariant(const PropValue* value);
125// Converts D-Bus variant to PropValue.
Alex Vakulenko576c9792014-09-22 16:49:45 -0700126// Has special handling for Object types where chromeos::VariantDictionary
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -0700127// is converted to native_types::Object.
128std::shared_ptr<const PropValue> PropValueFromDBusVariant(
129 const PropType* type,
130 const chromeos::Any& value,
131 chromeos::ErrorPtr* error);
132
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700133} // namespace buffet
134
135#endif // BUFFET_COMMANDS_SCHEMA_UTILS_H_