blob: 2e44de899c6ae98a60761d7fc450bb0f30fe816c [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 "validator/asset_validator_impl.h"
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include "absl/base/nullability.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "bindings/validator.h"
#include "formats/core_registry.h"
#include "formats/extractor.h"
#include "formats/format.h"
#include "formats/registry.h"
#include "proto/validation_result.pb.h"
#include "riegeli/bytes/reader.h"
#include "validator/manifest_store_validator.h"
#include "validator/manifest_store_validator_impl.h"
#include "validator/result.h"
#include "validator/validation_result_internal.h"
#include "validator/validator_metrics.h"
#include "validator/validator_options.h"
namespace credentio {
namespace {
absl::StatusOr<std::unique_ptr<ValidationResult>> FinalizePartialResult(
std::unique_ptr<PartialValidationResultProto> partial_validation_result,
riegeli::Reader& input, const Format& format,
std::optional<absl::string_view> media_type,
ValidatorMetrics* absl_nullable metrics, std::string manifest_store_bytes) {
std::unique_ptr<ValidationResultProto> validation_result;
if (partial_validation_result->has_hard_binding_uri()) {
if (!input.Seek(0)) {
return absl::InternalError(
"Failed to seek to the beginning of the input.");
}
ABSL_ASSIGN_OR_RETURN(
validation_result,
ContentBindingValidator().Validate(
input, format, std::move(partial_validation_result)));
} else {
ABSL_ASSIGN_OR_RETURN(
validation_result,
MakeFullValidationResult(std::move(partial_validation_result)));
}
if (media_type.has_value()) {
validation_result->set_media_type(*media_type);
}
if (metrics != nullptr) {
metrics->RecordValidationResult(
media_type.has_value() ? *media_type : format.mime_types()[0],
*validation_result);
}
return std::make_unique<ValidationResult>(std::move(validation_result),
std::move(manifest_store_bytes));
}
ValidatorOptions OptionsWithoutMetrics(ValidatorOptions options) {
options.metrics = nullptr;
return options;
}
} // namespace
absl::StatusOr<std::unique_ptr<ValidationResult>> AssetValidatorImpl::Validate(
riegeli::Reader& input, std::optional<absl::string_view> media_type) const {
if (!input.SupportsSize() || !input.SupportsRandomAccess()) {
return absl::InvalidArgumentError(
"The input does not support backwards seeks, it is required.");
}
if (!input.Seek(0)) {
return absl::InternalError("Failed to seek to the beginning of the input.");
}
const Format* format;
if (media_type.has_value()) {
ABSL_ASSIGN_OR_RETURN(format,
format_registry_->GetFormat(*media_type, input));
} else {
ABSL_ASSIGN_OR_RETURN(format, format_registry_->GetFormat(input));
}
if (!input.Seek(0)) {
return absl::InternalError("Failed to seek to the beginning of the input.");
}
ABSL_ASSIGN_OR_RETURN(auto manifest_store,
format->extractor()->ExtractManifestStore(input));
absl::string_view manifest_str = manifest_store;
ABSL_ASSIGN_OR_RETURN(
std::unique_ptr<PartialValidationResultProto> partial_validation_result,
manifest_store_validator_->Validate(manifest_str));
return FinalizePartialResult(std::move(partial_validation_result), input,
*format, media_type, options_.metrics,
std::move(manifest_store));
}
AssetValidatorImpl::AssetValidatorImpl(ValidatorOptions options)
: options_(options),
format_registry_(CreateCoreFormatRegistry()),
manifest_store_validator_(std::make_unique<ManifestStoreValidatorImpl>(
OptionsWithoutMetrics(std::move(options)))) {}
} // namespace credentio