blob: 61e64a6c8751f10953c0b57cbc71f1cc884ec011 [file] [edit]
/*
* Copyright (C) 2026 The Android Open Source Project
*
* 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
*
* http://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.
*/
#ifndef SRC_TOOLS_TRACING_PROTO_EXTENSIONS_H_
#define SRC_TOOLS_TRACING_PROTO_EXTENSIONS_H_
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
#include "perfetto/base/status.h"
#include "perfetto/ext/base/status_or.h"
namespace perfetto {
namespace gen_proto_extensions {
using Range = std::pair<int32_t, int32_t>;
// Represents an allocation entry in an extensions.json file.
struct Allocation {
std::string name;
std::vector<Range> ranges; // Each pair is [start, end] inclusive.
std::string contact;
std::string description;
std::string repo;
// Exactly one of proto or registry should be set (or neither for
// "unallocated" entries).
std::string proto; // Path to a leaf .proto file.
std::string registry; // Path to a sub-delegation .json file.
};
// Represents a parsed extensions.json file.
struct Registry {
// The fully-qualified proto message being extended. One of
// "perfetto.protos.TrackEvent", "perfetto.protos.TracePacket",
// "perfetto.protos.TrackEvent.State", or "perfetto.protos.InternedData".
std::string scope;
std::vector<Range> ranges; // Each pair is [start, end] inclusive.
std::vector<Allocation> allocations;
// The path of the .json file this was loaded from (for error messages).
std::string source_path;
};
// Parses an extensions.json file with the {"extensions": [...]}
// format. Returns one Registry per entry in the array.
base::StatusOr<std::vector<Registry>> ParseRegistryFile(
const std::string& json_contents,
const std::string& source_path);
// Validates a registry: checks that allocations tile the ranges exactly
// (no gaps or overlaps) and that constraints on proto/registry fields are met.
base::Status ValidateRegistry(const Registry& registry);
// Validates that no scope appears in more than one top-level Registry entry of
// the parsed extensions.json. Combined with the per-entry ValidateRegistry
// tile-exactness check, this guarantees that for each scope there is a single
// canonical range and a single canonical allocation tiling.
base::Status ValidateScopesUnique(const std::vector<Registry>& registries);
// Recursively walks the registry tree starting from |root_json_path|,
// compiles all referenced local .proto files, validates field numbers,
// and returns a serialized FileDescriptorSet containing only the extension
// descriptors (using the field subset from our descriptor.proto).
//
// |proto_paths| are the -I include directories for protoc.
// |root_dir| is the base directory for resolving relative paths in the JSON.
base::StatusOr<std::vector<uint8_t>> GenerateExtensionDescriptors(
const std::string& root_json_path,
const std::vector<std::string>& proto_paths,
const std::string& root_dir);
} // namespace gen_proto_extensions
} // namespace perfetto
#endif // SRC_TOOLS_TRACING_PROTO_EXTENSIONS_H_