| // 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 |