blob: f67680eca6951c27c2de5fe2d9ba83c8f56af14f [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 "formats/pdf/manifest_store_merger.h"
#include <string>
#include <utility>
#include <vector>
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/cord.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "constants/labels.h"
#include "jumbf/box.h"
#include "jumbf/box_builder.h"
#include "jumbf/encode_params.h"
#include "jumbf/parse.h"
namespace credentio {
using ::jumbf::DescriptionBoxOptions;
using ::jumbf::SuperBox;
using ::jumbf::SuperBoxBuilder;
absl::StatusOr<std::string> MergeManifestStores(
absl::Span<const absl::string_view> stores) {
if (stores.empty()) {
return absl::InvalidArgumentError("No manifest stores provided to merge.");
}
if (stores.size() == 1) {
return std::string(stores.front());
}
SuperBoxBuilder builder(credentio::kManifestStoreUuid,
DescriptionBoxOptions{
.requestable_iff_label = true,
.label = absl::Cord(kManifestStoreLabel),
});
// SuperBoxBuilder uses a CordBackwardWriter (LIFO insertion order).
// To ensure the newest PDF increment's manifest ends up at the BACK of the
// content list, we iterate through stores in REVERSE chronological order
// (stores.rbegin() to stores.rend()).
for (auto store_it = stores.rbegin(); store_it != stores.rend(); ++store_it) {
absl::string_view store_view = *store_it;
ABSL_ASSIGN_OR_RETURN(
SuperBox ms_superbox,
jumbf::ConsumeSuperBox(&store_view, /*recursion_limit=*/9));
// Iterate contents in REVERSE order so LIFO AddChild restores the exact
// original order of children inside each store.
for (auto box_it = ms_superbox.contents.rbegin();
box_it != ms_superbox.contents.rend(); ++box_it) {
ABSL_RETURN_IF_ERROR(builder.AddChild(absl::Cord(box_it->raw_bytes)));
}
}
ABSL_ASSIGN_OR_RETURN(auto built_box, std::move(builder).Finalize());
return std::string(std::move(built_box).AsCord());
}
} // namespace credentio