| // Copyright 2026 Google LLC | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // https://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| // | |
| #include "cbor/cbor.h" | |
| #include <cstdint> | |
| #include <optional> | |
| #include <string> | |
| #include <string_view> | |
| #include "absl/base/attributes.h" | |
| #include "absl/status/status.h" | |
| #include "absl/status/status_macros.h" | |
| #include "absl/status/statusor.h" | |
| #include "absl/strings/str_cat.h" | |
| #include "absl/strings/string_view.h" | |
| #include "cppbor/cppbor.h" | |
| namespace cbor { | |
| ItemView::Type ItemView::type() const { | |
| switch (item_->type()) { | |
| case cppbor::SIMPLE: | |
| switch (item_->asSimple()->simpleType()) { | |
| case cppbor::BOOLEAN: | |
| return Type::kBool; | |
| case cppbor::FLOAT: | |
| return Type::kFloat; | |
| case cppbor::DOUBLE: | |
| return Type::kDouble; | |
| default: | |
| return Type::kUnknown; | |
| } | |
| case cppbor::TSTR: | |
| return Type::kString; | |
| case cppbor::BSTR: | |
| return Type::kByteString; | |
| case cppbor::NINT: | |
| return Type::kInt64; | |
| case cppbor::UINT: | |
| return Type::kUint64; | |
| case cppbor::MAP: | |
| return Type::kMap; | |
| case cppbor::ARRAY: | |
| return Type::kArray; | |
| default: | |
| return Type::kUnknown; | |
| } | |
| } | |
| bool ItemView::IsNull() const { | |
| if (const auto* s = item_->asSimple(); s != nullptr) { | |
| if (const auto* v = s->asNull(); v != nullptr) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| absl::StatusOr<bool> ItemView::GetBool() const { | |
| if (const auto* s = item_->asSimple(); s != nullptr) { | |
| if (const auto* v = s->asBool(); v != nullptr) { | |
| return v->value(); | |
| } | |
| } | |
| return absl::InvalidArgumentError( | |
| absl::StrCat("CBOR item is not a bool. Type: ", item_->type())); | |
| } | |
| absl::StatusOr<float> ItemView::GetFloat() const { | |
| if (const auto* s = item_->asSimple(); s != nullptr) { | |
| if (const auto* v = s->asFloat(); v != nullptr) { | |
| return v->value(); | |
| } | |
| } | |
| return absl::InvalidArgumentError( | |
| absl::StrCat("CBOR item is not a float. Type: ", item_->type())); | |
| } | |
| absl::StatusOr<double> ItemView::GetDouble() const { | |
| if (const auto* s = item_->asSimple(); s != nullptr) { | |
| if (const auto* v = s->asDouble(); v != nullptr) { | |
| return v->value(); | |
| } | |
| } | |
| return absl::InvalidArgumentError( | |
| absl::StrCat("CBOR item is not a double. Type: ", item_->type())); | |
| } | |
| absl::StatusOr<int64_t> ItemView::GetInt64() const { | |
| if (const auto* v = item_->asInt(); v != nullptr) { | |
| return v->value(); | |
| } | |
| return absl::InvalidArgumentError( | |
| absl::StrCat("CBOR item is not an int. Type: ", item_->type())); | |
| } | |
| absl::StatusOr<uint64_t> ItemView::GetUint64() const { | |
| if (const auto* v = item_->asUint(); v != nullptr) { | |
| return v->value(); | |
| } | |
| return absl::InvalidArgumentError( | |
| absl::StrCat("CBOR item is not an uint. Type: ", item_->type())); | |
| } | |
| absl::StatusOr<absl::string_view> ItemView::GetString() const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| if (const auto* v = item_->asTstr(); v != nullptr) { | |
| return v->value(); | |
| } | |
| return absl::InvalidArgumentError( | |
| absl::StrCat("CBOR item is not a string. Type: ", item_->type())); | |
| } | |
| absl::StatusOr<absl::string_view> ItemView::GetByteString() const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| if (const auto* v = item_->asBstr(); v != nullptr) { | |
| absl::string_view str(reinterpret_cast<const char*>(v->value().data()), | |
| v->value().size()); | |
| return str; | |
| } | |
| return absl::InvalidArgumentError( | |
| absl::StrCat("CBOR item is not a byte string. Type: ", item_->type())); | |
| } | |
| absl::StatusOr<MapView> ItemView::GetMap() const ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| if (const auto* v = item_->asMap(); v != nullptr) { | |
| return MapView(v); | |
| } | |
| return absl::InvalidArgumentError( | |
| absl::StrCat("CBOR item is not a map. Type: ", item_->type())); | |
| } | |
| absl::StatusOr<ArrayView> ItemView::GetArray() const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| if (const auto* v = item_->asArray(); v != nullptr) { | |
| return ArrayView(v); | |
| } | |
| return absl::InvalidArgumentError( | |
| absl::StrCat("CBOR item is not an array. Type: ", item_->type())); | |
| } | |
| std::string ItemView::ToString() const { return item_->toString(); } | |
| absl::StatusOr<ItemView> MapView::Get(uint32_t key) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| const auto& item = map_->get(key); | |
| if (!item) { | |
| return absl::InvalidArgumentError(absl::StrCat("Key not found: ", key)); | |
| } | |
| return ItemView(item.get()); | |
| } | |
| absl::StatusOr<ItemView> MapView::Get(absl::string_view key) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| const auto& item = map_->get(std::string_view(key)); | |
| if (!item) { | |
| return absl::InvalidArgumentError(absl::StrCat("Key not found: ", key)); | |
| } | |
| return ItemView(item.get()); | |
| } | |
| std::optional<ItemView> MapView::GetOptional(absl::string_view key) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| const auto& item = map_->get(std::string_view(key)); | |
| if (!item) { | |
| return std::nullopt; | |
| } | |
| return ItemView(item.get()); | |
| } | |
| absl::StatusOr<bool> MapView::GetBool(absl::string_view key) const { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(key)); | |
| return item.GetBool(); | |
| } | |
| std::optional<bool> MapView::GetOptionalBool(absl::string_view key) const { | |
| if (auto item = GetOptional(key); item.has_value()) { | |
| if (auto value = item->GetBool(); value.ok()) { | |
| return *value; | |
| } | |
| } | |
| return std::nullopt; | |
| } | |
| absl::StatusOr<float> MapView::GetFloat(absl::string_view key) const { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(key)); | |
| return item.GetFloat(); | |
| } | |
| std::optional<float> MapView::GetOptionalFloat(absl::string_view key) const { | |
| if (auto item = GetOptional(key); item.has_value()) { | |
| if (auto value = item->GetFloat(); value.ok()) { | |
| return *value; | |
| } | |
| } | |
| return std::nullopt; | |
| } | |
| absl::StatusOr<double> MapView::GetDouble(absl::string_view key) const { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(key)); | |
| return item.GetDouble(); | |
| } | |
| std::optional<double> MapView::GetOptionalDouble(absl::string_view key) const { | |
| if (auto item = GetOptional(key); item.has_value()) { | |
| if (auto value = item->GetDouble(); value.ok()) { | |
| return *value; | |
| } | |
| } | |
| return std::nullopt; | |
| } | |
| absl::StatusOr<absl::string_view> MapView::GetString( | |
| absl::string_view key) const ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(key)); | |
| ABSL_ASSIGN_OR_RETURN(auto str, item.GetString()); | |
| return str; | |
| } | |
| std::optional<absl::string_view> MapView::GetOptionalString( | |
| absl::string_view key) const ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| if (auto item = GetOptional(key); item.has_value()) { | |
| if (auto value = item->GetString(); value.ok()) { | |
| return *value; | |
| } | |
| } | |
| return std::nullopt; | |
| } | |
| absl::StatusOr<absl::string_view> MapView::GetByteString(uint32_t key) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(key)); | |
| ABSL_ASSIGN_OR_RETURN(auto str, item.GetByteString()); | |
| return str; | |
| } | |
| absl::StatusOr<absl::string_view> MapView::GetByteString( | |
| absl::string_view key) const ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(key)); | |
| ABSL_ASSIGN_OR_RETURN(auto str, item.GetByteString()); | |
| return str; | |
| } | |
| std::optional<absl::string_view> MapView::GetOptionalByteString( | |
| absl::string_view key) const ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| if (auto item = GetOptional(key); item.has_value()) { | |
| if (auto value = item->GetByteString(); value.ok()) { | |
| return *value; | |
| } | |
| } | |
| return std::nullopt; | |
| } | |
| std::optional<MapView> MapView::GetOptionalMap(absl::string_view key) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| if (auto item = GetOptional(key); item.has_value()) { | |
| if (auto value = item->GetMap(); value.ok()) { | |
| return *value; | |
| } | |
| } | |
| return std::nullopt; | |
| } | |
| absl::StatusOr<int64_t> MapView::GetInt64(absl::string_view key) const { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(key)); | |
| return item.GetInt64(); | |
| } | |
| std::optional<int64_t> MapView::GetOptionalInt64(absl::string_view key) const { | |
| if (auto item = GetOptional(key); item.has_value()) { | |
| if (auto value = item->GetInt64(); value.ok()) { | |
| return *value; | |
| } | |
| } | |
| return std::nullopt; | |
| } | |
| absl::StatusOr<int64_t> MapView::GetInt64(uint32_t key) const { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(key)); | |
| return item.GetInt64(); | |
| } | |
| absl::StatusOr<uint64_t> MapView::GetUint64(absl::string_view key) const { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(key)); | |
| return item.GetUint64(); | |
| } | |
| std::optional<int64_t> MapView::GetOptionalUint64(absl::string_view key) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| if (auto item = GetOptional(key); item.has_value()) { | |
| if (auto value = item->GetUint64(); value.ok()) { | |
| return *value; | |
| } | |
| } | |
| return std::nullopt; | |
| } | |
| absl::StatusOr<MapView> MapView::GetMap(absl::string_view key) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(key)); | |
| ABSL_ASSIGN_OR_RETURN(auto map, item.GetMap()); | |
| return map; | |
| } | |
| absl::StatusOr<ArrayView> MapView::GetArray(uint32_t key) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(key)); | |
| ABSL_ASSIGN_OR_RETURN(auto array, item.GetArray()); | |
| return array; | |
| } | |
| absl::StatusOr<ArrayView> MapView::GetArray(absl::string_view key) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(key)); | |
| ABSL_ASSIGN_OR_RETURN(auto array, item.GetArray()); | |
| return array; | |
| } | |
| std::optional<ArrayView> MapView::GetOptionalArray(absl::string_view key) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| if (auto item = GetOptional(key); item.has_value()) { | |
| if (auto value = item->GetArray(); value.ok()) { | |
| return *value; | |
| } | |
| } | |
| return std::nullopt; | |
| } | |
| uint32_t ArrayView::size() const { return array_->size(); } | |
| ItemView::Type ArrayView::value_type(uint32_t index) const { | |
| if (index >= size()) { | |
| return ItemView::Type::kUnknown; | |
| } | |
| ItemView item(array_->get(index).get()); | |
| return item.type(); | |
| } | |
| absl::StatusOr<ItemView> ArrayView::Get(uint32_t index) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| if (index >= array_->size()) { | |
| return absl::InvalidArgumentError( | |
| absl::StrCat("Index out of range: ", index, " >= ", array_->size())); | |
| } | |
| return ItemView(array_->get(index).get()); | |
| } | |
| absl::StatusOr<bool> ArrayView::GetBool(uint32_t index) const { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(index)); | |
| return item.GetBool(); | |
| } | |
| absl::StatusOr<float> ArrayView::GetFloat(uint32_t index) const { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(index)); | |
| return item.GetFloat(); | |
| } | |
| absl::StatusOr<double> ArrayView::GetDouble(uint32_t index) const { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(index)); | |
| return item.GetDouble(); | |
| } | |
| absl::StatusOr<absl::string_view> ArrayView::GetString(uint32_t index) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(index)); | |
| ABSL_ASSIGN_OR_RETURN(auto str, item.GetString()); | |
| return str; | |
| } | |
| absl::StatusOr<absl::string_view> ArrayView::GetByteString(uint32_t index) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(index)); | |
| ABSL_ASSIGN_OR_RETURN(auto str, item.GetByteString()); | |
| return str; | |
| } | |
| absl::StatusOr<int64_t> ArrayView::GetInt64(uint32_t index) const { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(index)); | |
| return item.GetInt64(); | |
| } | |
| absl::StatusOr<uint64_t> ArrayView::GetUint64(uint32_t index) const { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(index)); | |
| return item.GetUint64(); | |
| } | |
| absl::StatusOr<MapView> ArrayView::GetMap(uint32_t index) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(index)); | |
| ABSL_ASSIGN_OR_RETURN(auto map, item.GetMap()); | |
| return map; | |
| } | |
| absl::StatusOr<ArrayView> ArrayView::GetArray(uint32_t index) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(index)); | |
| ABSL_ASSIGN_OR_RETURN(auto array, item.GetArray()); | |
| return array; | |
| } | |
| absl::StatusOr<bool> ArrayView::IsNull(uint32_t index) const | |
| ABSL_ATTRIBUTE_LIFETIME_BOUND { | |
| ABSL_ASSIGN_OR_RETURN(auto item, Get(index)); | |
| return item.IsNull(); | |
| } | |
| } // namespace cbor |