| // 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 |