| Line |
Branch |
Exec |
Source |
| 1 |
|
|
// SPDX-License-Identifier: BSD-3-Clause |
| 2 |
|
|
/// @file schema.cpp |
| 3 |
|
|
/// @brief Schema lookups and value validation. |
| 4 |
|
|
#include "ernie/scene/schema.h" |
| 5 |
|
|
|
| 6 |
|
|
#include "ernie/scene/convert.h" |
| 7 |
|
|
#include "ernie/util/text.h" |
| 8 |
|
|
|
| 9 |
|
|
#include <algorithm> |
| 10 |
|
|
#include <cmath> |
| 11 |
|
|
#include <stdexcept> |
| 12 |
|
|
#include <string> |
| 13 |
|
|
|
| 14 |
|
|
namespace ernie { |
| 15 |
|
|
namespace { |
| 16 |
|
|
|
| 17 |
|
|
/// What the bounds take: "above 0 and below 170", "from 0 to 1", "finite and 1 or more". |
| 18 |
|
8 |
std::string RangeText(const AttributeMeta& meta) { |
| 19 |
|
8 |
const std::optional<Bound>& lower = meta.lower; |
| 20 |
|
8 |
const std::optional<Bound>& upper = meta.upper; |
| 21 |
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 |
std::string text; |
| 22 |
5/8
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
8 |
if (lower && upper && !lower->exclusive && !upper->exclusive) { |
| 23 |
4/8
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
|
6 |
text = "from " + ToText(lower->value) + " to " + ToText(upper->value); |
| 24 |
|
|
} else { |
| 25 |
|
5 |
std::vector<std::string> limits; |
| 26 |
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 |
if (lower) { |
| 27 |
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
|
20 |
limits.push_back(lower->exclusive ? "above " + ToText(lower->value) |
| 28 |
3/10
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
15 |
: ToText(lower->value) + " or more"); |
| 29 |
|
|
} |
| 30 |
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 |
if (upper) { |
| 31 |
0/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
✗ |
limits.push_back(upper->exclusive ? "below " + ToText(upper->value) |
| 32 |
0/10
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
✗ |
: ToText(upper->value) + " or less"); |
| 33 |
|
|
} |
| 34 |
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 |
text = Join(limits, " and "); |
| 35 |
|
5 |
} |
| 36 |
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
|
8 |
if (meta.finite) { |
| 37 |
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
|
5 |
text = text.empty() ? "finite" : "finite and " + text; |
| 38 |
|
|
} |
| 39 |
|
8 |
return text; |
| 40 |
|
✗ |
} |
| 41 |
|
|
|
| 42 |
|
1363 |
bool Fits(const AttributeMeta& meta, double number) { |
| 43 |
|
|
// Written to fail for NaN. |
| 44 |
3/4
✓ Branch 0 taken 1237 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1311 times.
✓ Branch 3 taken 52 times.
|
1363 |
return (!meta.finite || std::isfinite(number)) && |
| 45 |
3/4
✓ Branch 0 taken 1311 times.
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
|
1403 |
(!meta.lower || |
| 46 |
11/12
✓ Branch 0 taken 1237 times.
✓ Branch 1 taken 126 times.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 1271 times.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1266 times.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 29 times.
✓ Branch 9 taken 1329 times.
✓ Branch 10 taken 3 times.
✓ Branch 11 taken 26 times.
|
2726 |
(meta.lower->exclusive ? number > meta.lower->value : number >= meta.lower->value)) && |
| 47 |
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 1329 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
1361 |
(!meta.upper || |
| 48 |
5/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 23 times.
✓ Branch 5 taken 3 times.
|
29 |
(meta.upper->exclusive ? number < meta.upper->value : number <= meta.upper->value)); |
| 49 |
|
|
} |
| 50 |
|
|
|
| 51 |
|
|
/// @return Why `value` doesn't fit the attribute, or empty when it does. |
| 52 |
|
3107 |
std::string Problem(const AttributeDef& def, const Value& value) { |
| 53 |
|
3107 |
const std::vector<double> numbers = ToNumbers(value); |
| 54 |
2/2
✓ Branch 0 taken 1363 times.
✓ Branch 1 taken 3099 times.
|
4462 |
for (const double number : numbers) { |
| 55 |
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1355 times.
|
1363 |
if (!Fits(def.meta, number)) { |
| 56 |
3/6
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
|
24 |
return "must be " + RangeText(def.meta) + |
| 57 |
3/6
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
|
32 |
(numbers.size() > 1 ? " in each component" : "") + ", not " + ToText(number); |
| 58 |
|
|
} |
| 59 |
|
|
} |
| 60 |
|
3099 |
const std::vector<std::string_view>& options = def.meta.options; |
| 61 |
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 2973 times.
|
3099 |
if (const auto* token = value.Get<std::string>(); |
| 62 |
4/4
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 21 times.
✓ Branch 3 taken 99 times.
✓ Branch 4 taken 6 times.
|
126 |
token && !options.empty() && std::ranges::find(options, *token) == options.end()) { |
| 63 |
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
|
18 |
return "must be one of " + Join(options, ", ") + ", not " + *token; |
| 64 |
|
|
} |
| 65 |
|
3093 |
return {}; |
| 66 |
|
3107 |
} |
| 67 |
|
|
|
| 68 |
|
|
/// @return Why `array` doesn't fit the tensor attribute, or empty when it does. |
| 69 |
|
116 |
std::string ArrayProblem(const AttributeDef& def, const Tensor& array) { |
| 70 |
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 115 times.
|
116 |
if (def.type != ColumnType::Tensor) { |
| 71 |
|
1 |
return "takes one value, not an array; set it"; |
| 72 |
|
|
} |
| 73 |
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 114 times.
|
115 |
if (def.meta.bytes) { |
| 74 |
|
1 |
return {}; |
| 75 |
|
|
} |
| 76 |
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 66 times.
|
114 |
const DType type = array.Type(); |
| 77 |
|
114 |
const bool integer = type == DType::Int32 || type == DType::Int64 || type == DType::UInt32; |
| 78 |
|
114 |
const bool floating = type == DType::Float32 || type == DType::Float64; |
| 79 |
4/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 113 times.
|
114 |
if (def.meta.integer ? !integer : !floating) { |
| 80 |
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 |
return def.meta.integer ? "must hold integers" : "must hold float32 or float64 numbers"; |
| 81 |
|
|
} |
| 82 |
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 110 times.
|
113 |
if (const std::vector<std::int64_t>& ranks = def.meta.ranks; !ranks.empty()) { |
| 83 |
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 |
if (std::ranges::find(ranks, static_cast<std::int64_t>(array.Rank())) != ranks.end()) { |
| 84 |
|
3 |
return {}; |
| 85 |
|
|
} |
| 86 |
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
✗ |
return "must have " + |
| 87 |
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
✗ |
Join(ranks, " or ", [](std::int64_t rank) { return std::to_string(rank); }) + |
| 88 |
|
✗ |
" dimensions"; |
| 89 |
|
|
} |
| 90 |
|
110 |
const std::int64_t components = def.meta.components; |
| 91 |
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 61 times.
|
110 |
const bool rows = |
| 92 |
5/6
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 44 times.
|
110 |
array.Rank() == 2 && array.Shape()[1] == std::max<std::int64_t>(components, 1); |
| 93 |
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 49 times.
|
110 |
const bool flat = |
| 94 |
4/6
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 49 times.
✓ Branch 3 taken 61 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 61 times.
|
171 |
array.Rank() == 1 && array.Elements() % std::max<std::int64_t>(components, 1) == 0; |
| 95 |
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 105 times.
|
110 |
if (!rows && !flat) { |
| 96 |
4/10
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
15 |
return components > 1 ? "must be (n, " + std::to_string(components) + ") or flat" |
| 97 |
2/8
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
5 |
: "must be flat"; |
| 98 |
|
|
} |
| 99 |
|
105 |
return {}; |
| 100 |
|
|
} |
| 101 |
|
|
|
| 102 |
|
3223 |
void ThrowIf(const std::string& problem, std::string_view attribute, const Path& path) { |
| 103 |
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 3202 times.
|
3223 |
if (!problem.empty()) { |
| 104 |
4/8
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 21 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 21 times.
✗ Branch 11 not taken.
|
84 |
throw std::invalid_argument("'" + path.String() + "': '" + std::string(attribute) + "' " + |
| 105 |
2/4
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 21 times.
✗ Branch 6 not taken.
|
63 |
problem); |
| 106 |
|
|
} |
| 107 |
|
3202 |
} |
| 108 |
|
|
|
| 109 |
|
|
} // namespace |
| 110 |
|
|
|
| 111 |
|
6042 |
bool SchemaDef::IsA(const SchemaDef& other) const { |
| 112 |
2/2
✓ Branch 0 taken 12207 times.
✓ Branch 1 taken 5312 times.
|
23561 |
return FirstInLineage([&](const SchemaDef& type) { return &type == &other; }) != nullptr; |
| 113 |
|
|
} |
| 114 |
|
|
|
| 115 |
|
1803 |
bool SchemaDef::IsOpen(std::string_view attribute) const { |
| 116 |
|
1803 |
return FirstInLineage([&](const SchemaDef& type) { |
| 117 |
|
5273 |
return std::ranges::any_of(type.openNamespaces, [&](std::string_view space) { |
| 118 |
4/4
✓ Branch 0 taken 2324 times.
✓ Branch 1 taken 619 times.
✓ Branch 3 taken 1173 times.
✓ Branch 4 taken 1151 times.
|
2943 |
return space == "*" || attribute.starts_with(space); |
| 119 |
|
5273 |
}); |
| 120 |
|
1803 |
}) != nullptr; |
| 121 |
|
|
} |
| 122 |
|
|
|
| 123 |
|
7 |
const AttributeDef* SchemaDef::Find(std::string_view attribute) const { |
| 124 |
|
7 |
const AttributeDef* found = nullptr; |
| 125 |
|
7 |
FirstInLineage([&](const SchemaDef& type) { |
| 126 |
|
11 |
const auto def = std::ranges::find(type.attributes, attribute, &AttributeDef::name); |
| 127 |
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
|
11 |
found = def != type.attributes.end() ? &*def : nullptr; |
| 128 |
|
11 |
return found != nullptr; |
| 129 |
|
|
}); |
| 130 |
|
7 |
return found; |
| 131 |
|
|
} |
| 132 |
|
|
|
| 133 |
|
2403 |
std::vector<const AttributeDef*> SchemaDef::AllAttributes() const { |
| 134 |
|
2403 |
std::vector<const AttributeDef*> all = |
| 135 |
2/2
✓ Branch 0 taken 1594 times.
✓ Branch 1 taken 809 times.
|
2403 |
base != nullptr ? base->AllAttributes() : std::vector<const AttributeDef*>{}; |
| 136 |
2/2
✓ Branch 0 taken 7514 times.
✓ Branch 1 taken 2403 times.
|
9917 |
for (const AttributeDef& def : attributes) { |
| 137 |
1/2
✓ Branch 1 taken 7514 times.
✗ Branch 2 not taken.
|
7514 |
all.push_back(&def); |
| 138 |
|
|
} |
| 139 |
|
2403 |
return all; |
| 140 |
|
✗ |
} |
| 141 |
|
|
|
| 142 |
|
3065 |
std::vector<std::string_view> SchemaDef::AllBuiltinApis() const { |
| 143 |
|
3065 |
std::vector<std::string_view> all = |
| 144 |
2/2
✓ Branch 0 taken 1962 times.
✓ Branch 1 taken 1103 times.
|
3065 |
base != nullptr ? base->AllBuiltinApis() : std::vector<std::string_view>{}; |
| 145 |
1/2
✓ Branch 1 taken 3065 times.
✗ Branch 2 not taken.
|
3065 |
all.insert(all.end(), builtinApis.begin(), builtinApis.end()); |
| 146 |
|
3065 |
return all; |
| 147 |
|
✗ |
} |
| 148 |
|
|
|
| 149 |
|
15480 |
const Value* SchemaDef::FallbackOverride(std::string_view attribute) const { |
| 150 |
|
15480 |
const Value* found = nullptr; |
| 151 |
|
15480 |
FirstInLineage([&](const SchemaDef& type) { |
| 152 |
|
41714 |
const auto override = std::ranges::find(type.fallbackOverrides, attribute, |
| 153 |
|
|
&std::pair<std::string_view, Value>::first); |
| 154 |
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 41573 times.
|
41714 |
found = override != type.fallbackOverrides.end() ? &override->second : nullptr; |
| 155 |
|
41714 |
return found != nullptr; |
| 156 |
|
|
}); |
| 157 |
|
15480 |
return found; |
| 158 |
|
|
} |
| 159 |
|
|
|
| 160 |
|
14162 |
ExtentRule SchemaDef::Extent() const { |
| 161 |
|
14162 |
const SchemaDef* ruled = FirstInLineage( |
| 162 |
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 14162 times.
|
14255 |
[](const SchemaDef& type) { return type.extent.kind != ExtentRule::Kind::Inherit; }); |
| 163 |
1/2
✓ Branch 0 taken 14162 times.
✗ Branch 1 not taken.
|
14162 |
return ruled != nullptr ? ruled->extent : kInheritExtent; |
| 164 |
|
|
} |
| 165 |
|
|
|
| 166 |
|
3323 |
const SchemaDef* FindSchema(std::string_view name) { |
| 167 |
|
3323 |
const std::span<const SchemaDef* const> schemas = Schemas(); |
| 168 |
|
3323 |
const auto found = std::ranges::find_if( |
| 169 |
2/2
✓ Branch 0 taken 55367 times.
✓ Branch 1 taken 3316 times.
|
58683 |
schemas, [&](const SchemaDef* schema) { return schema->name == name; }); |
| 170 |
2/2
✓ Branch 0 taken 3316 times.
✓ Branch 1 taken 7 times.
|
3323 |
return found != schemas.end() ? *found : nullptr; |
| 171 |
|
|
} |
| 172 |
|
|
|
| 173 |
|
517 |
std::span<const AttributeDef* const> InheritedAttributes() { |
| 174 |
|
130 |
static const std::vector<const AttributeDef*> kInherited = [] { |
| 175 |
|
130 |
std::vector<const AttributeDef*> inherited; |
| 176 |
3/4
✓ Branch 1 taken 130 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8450 times.
✓ Branch 4 taken 130 times.
|
8580 |
for (const SchemaDef* schema : Schemas()) { |
| 177 |
2/2
✓ Branch 0 taken 39650 times.
✓ Branch 1 taken 8450 times.
|
48100 |
for (const AttributeDef& def : schema->attributes) { |
| 178 |
2/2
✓ Branch 0 taken 520 times.
✓ Branch 1 taken 39130 times.
|
39650 |
if (def.meta.inherited) { |
| 179 |
1/2
✓ Branch 1 taken 520 times.
✗ Branch 2 not taken.
|
520 |
inherited.push_back(&def); |
| 180 |
|
|
} |
| 181 |
|
|
} |
| 182 |
|
|
} |
| 183 |
|
130 |
return inherited; |
| 184 |
4/6
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 387 times.
✓ Branch 3 taken 130 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 130 times.
✗ Branch 7 not taken.
|
517 |
}(); |
| 185 |
|
517 |
return kInherited; |
| 186 |
|
|
} |
| 187 |
|
|
|
| 188 |
|
21 |
const AttributeDef* FindInherited(std::string_view name) { |
| 189 |
|
21 |
const std::span<const AttributeDef* const> inherited = InheritedAttributes(); |
| 190 |
|
21 |
const auto found = |
| 191 |
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 21 times.
|
75 |
std::ranges::find_if(inherited, [&](const AttributeDef* def) { return def->name == name; }); |
| 192 |
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 |
return found != inherited.end() ? *found : nullptr; |
| 193 |
|
|
} |
| 194 |
|
|
|
| 195 |
|
515 |
ApiName ApiName::Parse(std::string_view api) { |
| 196 |
|
515 |
const std::size_t colon = api.find(':'); |
| 197 |
|
515 |
const std::string_view name = api.substr(0, colon); |
| 198 |
|
515 |
const ApiName parsed{FindSchema(name), colon == std::string_view::npos ? std::string_view() |
| 199 |
2/2
✓ Branch 0 taken 291 times.
✓ Branch 1 taken 224 times.
|
515 |
: api.substr(colon + 1)}; |
| 200 |
4/4
✓ Branch 0 taken 513 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 225 times.
✓ Branch 3 taken 288 times.
|
515 |
const bool single = parsed.schema != nullptr && parsed.schema->kind == SchemaKind::SingleApply; |
| 201 |
|
1030 |
const bool multiple = |
| 202 |
4/4
✓ Branch 0 taken 513 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 289 times.
✓ Branch 3 taken 224 times.
|
515 |
parsed.schema != nullptr && parsed.schema->kind == SchemaKind::MultipleApply; |
| 203 |
8/8
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 227 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 287 times.
✓ Branch 4 taken 224 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 222 times.
|
515 |
if (!(single && parsed.instance.empty()) && !(multiple && IsIdentifier(parsed.instance))) { |
| 204 |
|
6 |
throw std::invalid_argument( |
| 205 |
5/8
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
|
22 |
"'" + std::string(api) + "' is no API schema" + |
| 206 |
|
|
(multiple ? ": a multiple-apply one takes an instance name, as CollectionAPI:lights" |
| 207 |
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
18 |
: "")); |
| 208 |
|
|
} |
| 209 |
|
509 |
return parsed; |
| 210 |
|
|
} |
| 211 |
|
|
|
| 212 |
|
7129 |
std::string ApiName::Attribute(std::string_view declared) const { |
| 213 |
|
7129 |
return Replace(declared, kInstanceName, instance); |
| 214 |
|
|
} |
| 215 |
|
|
|
| 216 |
|
220 |
std::string ApiName::ToString() const { |
| 217 |
9/16
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 64 times.
✓ Branch 3 taken 156 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 64 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 64 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 220 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 220 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 64 times.
✓ Branch 19 taken 156 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
504 |
return std::string(schema->name) + (instance.empty() ? "" : ":" + std::string(instance)); |
| 218 |
|
|
} |
| 219 |
|
|
|
| 220 |
|
3107 |
void Validate(const AttributeDef& def, std::string_view attribute, const Value& value, |
| 221 |
|
|
const Path& path) { |
| 222 |
2/2
✓ Branch 2 taken 3093 times.
✓ Branch 3 taken 14 times.
|
3107 |
ThrowIf(Problem(def, value), attribute, path); |
| 223 |
|
3093 |
} |
| 224 |
|
|
|
| 225 |
|
116 |
void ValidateArray(const AttributeDef& def, std::string_view attribute, const Tensor& array, |
| 226 |
|
|
const Path& path) { |
| 227 |
2/2
✓ Branch 2 taken 109 times.
✓ Branch 3 taken 7 times.
|
116 |
ThrowIf(ArrayProblem(def, array), attribute, path); |
| 228 |
|
109 |
} |
| 229 |
|
|
|
| 230 |
|
|
} // namespace ernie |
| 231 |
|
|
|