blob: e247ff34e2097066167cb377b66c942a51efc9fd [file] [edit]
// 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