| // 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/encode.h" | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <limits> | |
| #include <utility> | |
| #include "absl/log/check.h" | |
| #include "absl/status/status.h" | |
| #include "absl/status/status_macros.h" | |
| #include "absl/strings/cord.h" | |
| #include "jumbf/constants.h" | |
| #include "jumbf/encode_params.h" | |
| #include "jumbf/internal/serialization_utils.h" | |
| #include "riegeli/base/types.h" | |
| #include "riegeli/bytes/backward_writer.h" | |
| #include "uuid/uuid.h" | |
| namespace jumbf { | |
| using ::jumbf_internal::WriteInteger; | |
| using ::jumbf_internal::WriteNulTerminated; | |
| using ::jumbf_internal::WritePadding; | |
| using ::jumbf_internal::WriteRaw; | |
| static_assert(std::numeric_limits<uint64_t>::max() >= | |
| std::numeric_limits<size_t>::max(), | |
| "This library converts from `size_t` to `uint64_t` when writing " | |
| "XLBox values."); | |
| absl::Status EncodePaddingBox(uint64_t padding_size, | |
| riegeli::BackwardWriter* writer) { | |
| ABSL_RETURN_IF_ERROR(WritePadding(padding_size, writer)); | |
| return EncodeBoxHeader(padding_size, kPaddingBoxType, writer); | |
| } | |
| absl::Status EncodeSerializedSuperBox(absl::Cord payload, | |
| riegeli::BackwardWriter* writer) { | |
| return WriteRaw(std::move(payload), writer); | |
| } | |
| absl::Status EncodeContentBox(uint32_t tbox, absl::Cord payload, | |
| riegeli::BackwardWriter* writer) { | |
| size_t payload_size = payload.size(); | |
| ABSL_RETURN_IF_ERROR(WriteRaw(std::move(payload), writer)); | |
| return EncodeBoxHeader(payload_size, tbox, writer); | |
| } | |
| absl::Status EncodeDescriptionBox(credentio::Uuid type_uuid, | |
| DescriptionBoxOptions options, | |
| riegeli::BackwardWriter* writer) { | |
| uint8_t toggles = 0; | |
| const riegeli::Position pos_before = writer->pos(); | |
| if (options.private_content.has_value()) { | |
| toggles |= kDescriptionTogglePrivatePresent; | |
| ABSL_RETURN_IF_ERROR(WriteRaw(*std::move(options.private_content), writer)); | |
| } | |
| if (options.label.has_value()) { | |
| if (options.requestable_iff_label) { | |
| toggles |= kDescriptionToggleRequestable; | |
| } | |
| toggles |= kDescriptionToggleLabelPresent; | |
| ABSL_RETURN_IF_ERROR(WriteNulTerminated(*std::move(options.label), writer)); | |
| } | |
| ABSL_RETURN_IF_ERROR(WriteInteger(toggles, writer)); | |
| ABSL_RETURN_IF_ERROR(WriteRaw(absl::Cord(type_uuid.ToProtoBytes()), writer)); | |
| return EncodeBoxHeader(writer->pos() - pos_before, kDescriptionBoxType, | |
| writer); | |
| } | |
| absl::Status EncodeBoxHeader(riegeli::Position payload_length, uint32_t tbox, | |
| riegeli::BackwardWriter* writer) { | |
| // Minimum box length is payload + mandatory header fields. | |
| constexpr size_t kMandatoryHeaderLength = | |
| 2 * sizeof(uint32_t); // LBox and TBox | |
| if (payload_length > std::numeric_limits<size_t>::max() - | |
| kMandatoryHeaderLength - sizeof(uint64_t)) { | |
| return absl::OutOfRangeError("maximum box size exceeded"); | |
| } | |
| size_t box_length = payload_length + kMandatoryHeaderLength; | |
| uint32_t lbox; | |
| if (box_length > std::numeric_limits<uint32_t>::max()) { | |
| uint64_t xlbox = box_length + sizeof(uint64_t); | |
| ABSL_RETURN_IF_ERROR(WriteInteger(xlbox, writer)); | |
| lbox = 1; | |
| } else { | |
| lbox = box_length; | |
| } | |
| ABSL_RETURN_IF_ERROR(WriteInteger(tbox, writer)); | |
| return WriteInteger(lbox, writer); | |
| } | |
| } // namespace jumbf |