blob: 36ccede1b2c8fac2bce14333306bf8dce98b4f4b [file] [edit]
// Copyright (c) 2026 The WebRTC project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
//! Path manipulation utilities for the WebRTC Rust macro.
//!
//! This module contains the pure string transformation logic used by the import
//! macro. It is deliberately separated from the `proc_macro` crate file so that
//! it can be cross-compiled and validated via native target-platform unit
//! tests.
/// Re-routes a source-relative GN absolute path string based on the build root
/// prefix.
///
/// # Arguments
/// * `prefix` - The current build context prefix (e.g., `"//"` or
/// `"//third_party/webrtc"`).
/// * `path_str` - The raw GN label string literal passed into the macro.
///
/// # Behavior
/// - If `path_str` is a first-party absolute label (starts with `"//"`):
/// - If `prefix` is `"//"`, the project is standalone; the path is left
/// untouched.
/// - If `prefix` is a subfolder (e.g., `"//third_party/webrtc"`):
/// - If the remainder starts with a colon (e.g., `"//:target"`), it maps
/// directly to the parent directory, so it concatenates without adding a
/// slash (`//prefix:target`).
/// - Otherwise, it maps down a nested subdirectory folder
/// (`//prefix/path/to/target`).
/// - Third-party or relative paths are returned completely unmodified.
pub fn adjust_path(prefix: &str, path_str: &str) -> String {
if path_str.starts_with("//") {
if prefix == "//" {
path_str.to_string()
} else {
// Remove trailing slash from prefix if present.
let prefix = prefix.strip_suffix("/").unwrap_or(prefix);
let remainder = &path_str[2..];
if remainder.starts_with(':') {
format!("{}{}", prefix, remainder)
} else {
format!("{}/{}", prefix, remainder)
}
}
} else {
path_str.to_string()
}
}
#[cfg(test)]
mod tests {
use super::*;
/// Checks Standalone mode behavior where `WEBRTC_GN_PREFIX = "//"`.
/// Verifies that absolute paths remain completely untouched.
#[test]
fn test_adjust_path_standalone() {
assert_eq!(adjust_path("//", "//api/units:time_delta_rs"), "//api/units:time_delta_rs");
}
/// Checks Vendor Prefix mode behavior (e.g., nested under Chromium).
/// Verifies that `//third_party/webrtc` is successfully prepended onto
/// first-party paths.
#[test]
fn test_adjust_path_chromium() {
assert_eq!(
adjust_path("//third_party/webrtc", "//api/units:time_delta_rs"),
"//third_party/webrtc/api/units:time_delta_rs"
);
}
/// Checks third-party crate or target-relative imports.
/// Verifies that paths not beginning with `//` pass through without
/// alterations.
#[test]
fn test_adjust_path_relative() {
assert_eq!(
adjust_path("//third_party/webrtc", "api/units:time_delta_rs"),
"api/units:time_delta_rs"
);
}
/// Checks the open-source explicit root-colon syntax (e.g., `"//:target"`).
/// Verifies that the trailing slash is omitted right before the colon,
/// avoiding invalid GN path expansion errors in the underlying token
/// parser.
#[test]
fn test_adjust_path_with_colon() {
assert_eq!(
adjust_path("//third_party/webrtc", "//:webrtc_import_prefix_lib"),
"//third_party/webrtc:webrtc_import_prefix_lib"
);
}
/// Removes trailing slash from a path string.
#[test]
fn test_remove_trailing_slash() {
assert_eq!(
adjust_path("//third_party/webrtc/", "//:webrtc_import_prefix_lib"),
"//third_party/webrtc:webrtc_import_prefix_lib"
);
}
}