blob: 7b7cb30aa51069d67e7943341ebaacbe90945a7f [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 "jumbf/internal/parse_super_box.h"
#include <utility>
#include <vector>
#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 "jumbf/constants.h"
#include "jumbf/internal/consume_box.h"
#include "jumbf/internal/intermediate.h"
#include "jumbf/internal/parse_description_box.h"
namespace jumbf_internal {
absl::StatusOr<IntermediateSuperBox> ParseSuperBox(
const IntermediateBox& unwrapped_super_box) {
if (unwrapped_super_box.type != jumbf::kSuperBoxType) {
return absl::InvalidArgumentError(
absl::StrCat("box is not a super box: got type 0x",
absl::Hex(unwrapped_super_box.type), " need 0x",
absl::Hex(jumbf::kSuperBoxType), " ('jumb')"));
}
absl::string_view temp_super_box_payload = unwrapped_super_box.payload;
ABSL_ASSIGN_OR_RETURN(
auto unwrapped_description_box,
ConsumeBox(&temp_super_box_payload, /*allow_implicit_length=*/false),
_.SetPrepend() << "cannot unwrap description box: ");
ABSL_ASSIGN_OR_RETURN(auto description_box,
ParseDescriptionBox(unwrapped_description_box),
_.SetPrepend() << "cannot parse description box: ");
if (temp_super_box_payload.empty()) {
return absl::InvalidArgumentError(
R"(super box has no content; at least one content box is required)");
}
std::vector<IntermediateBox> content;
while (!temp_super_box_payload.empty()) {
ABSL_ASSIGN_OR_RETURN(
auto unwrapped_content,
ConsumeBox(
&temp_super_box_payload,
/*allow_implicit_length=*/unwrapped_super_box.implicit_length),
_.SetPrepend() << "cannot unwrap content box for index "
<< content.size() << ": ");
if (unwrapped_content.type == jumbf::kPaddingBoxType) {
if (!temp_super_box_payload.empty()) {
return absl::InvalidArgumentError(
absl::StrCat("input remaining after padding box; if a padding box "
"is present within a super box, it must occupy the "
"entire remainder of the box's size; after reading "
"one padding box there were ",
temp_super_box_payload.length(), " bytes remaining"));
}
} else {
content.push_back(std::move(unwrapped_content));
}
}
return IntermediateSuperBox{
.description = std::move(description_box),
.content = std::move(content),
.serialized = unwrapped_super_box.serialized,
};
}
} // namespace jumbf_internal