| // 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/jpeg/testing/app_segment_creator.h" |
| |
| #include <cstdint> |
| #include <string> |
| #include <vector> |
| |
| #include "absl/status/status.h" |
| #include "absl/status/status_macros.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/string_view.h" |
| #include "utils/byte_readers.h" |
| #include "utils/byte_writers.h" |
| |
| namespace credentio { |
| |
| absl::StatusOr<std::vector<std::string>> CreateAppSegments( |
| AppSegmentParams params) { |
| absl::string_view payload(params.payload); |
| |
| std::vector<std::string> segments; |
| |
| ABSL_ASSIGN_OR_RETURN(uint32_t lbox, ConsumeUint<uint32_t>(&payload)); |
| ABSL_ASSIGN_OR_RETURN(uint32_t tbox, ConsumeUint<uint32_t>(&payload)); |
| uint64_t xlbox = 0; |
| if (lbox == 1) { |
| ABSL_ASSIGN_OR_RETURN(xlbox, ConsumeUint<uint64_t>(&payload)); |
| } |
| |
| if (!params.en.has_value()) { |
| params.en = 1; |
| } |
| |
| uint32_t z = params.starting_z; |
| uint16_t base_le = sizeof(uint16_t) + // le |
| sizeof(uint16_t) + // cl |
| sizeof(uint16_t) + // en |
| sizeof(uint32_t) + // z |
| sizeof(uint32_t) + // lbox |
| sizeof(uint32_t) + // tbox |
| (lbox == 1 ? sizeof(uint64_t) : 0); // xlbox |
| |
| if (params.max_size <= base_le) { |
| return absl::InvalidArgumentError( |
| "AppSegmentParams max_size must be strictly greater than base_le."); |
| } |
| |
| uint16_t max_segment_size = params.max_size - base_le; |
| while (!payload.empty()) { |
| std::vector<uint8_t> bytes; |
| // The maximum size of the segment is params.max_size. The bytes vector |
| // also includes the 2-byte marker. |
| bytes.reserve(sizeof(uint16_t) + params.max_size); |
| |
| // Add Marker |
| WriteUint16NetworkOrder(params.marker, &bytes); |
| |
| uint16_t le = |
| base_le + (payload.length() < max_segment_size ? payload.length() |
| : max_segment_size); |
| // Add Size |
| WriteUint16NetworkOrder(le, &bytes); |
| |
| // Add Extension Type |
| WriteUint16NetworkOrder(params.cl, &bytes); |
| |
| // Add Identifier |
| WriteUint16NetworkOrder(*params.en, &bytes); |
| |
| // Add Sequence Number |
| WriteUint32NetworkOrder(z, &bytes); |
| |
| // Add LBox |
| WriteUint32NetworkOrder(lbox, &bytes); |
| |
| // Add TBox |
| WriteUint32NetworkOrder(tbox, &bytes); |
| |
| // Maybe Add XLBox |
| if (lbox == 1) { |
| WriteUint64NetworkOrder(xlbox, &bytes); |
| } |
| |
| for (int i = 0; i < max_segment_size && !payload.empty(); ++i) { |
| // Will Always Contain at least one byte |
| ABSL_ASSIGN_OR_RETURN(auto byte, ConsumeUint<uint8_t>(&payload)); |
| bytes.push_back(byte); |
| } |
| |
| z = params.z_incrementer(z); |
| |
| segments.push_back(std::string(bytes.begin(), bytes.end())); |
| } |
| |
| return segments; |
| } |
| |
| } // namespace credentio |