blob: 73c605231433d00f58d80096808511de8e5a722b [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.
//! WebRTC Rust Portability Import Proc-Macro Wrapper.
//!
//! This crate provides the `import!` macro which serves as a layer of
//! indirection over Chromium's `chromium::import!`. It rewrites source-relative
//! GN paths dynamically based on whether WebRTC is built standalone or embedded
//! inside a vendor directory tree (like `//third_party/webrtc`).
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::{parse_macro_input, Ident, LitStr, Token, Visibility};
mod path_utils;
/// Represents a single dependency import line item inside the macro.
///
/// Example syntax: `pub "//api/units:time_delta_rs" as time_delta;`
struct ImportItem {
/// Optional visibility prefix (e.g., `pub`, `pub(crate)`).
vis: Option<Visibility>,
/// Quoted string literal containing the absolute or relative GN target
/// label.
path: LitStr,
/// Optional custom crate rename alias (e.g., `as renamed_crate`).
alias: Option<(Token![as], Ident)>,
}
impl Parse for ImportItem {
/// Parses a single import entry matching: `[vis] "path" [as alias]`
fn parse(input: ParseStream) -> syn::Result<Self> {
let vis = input.parse::<Visibility>().ok();
let path = input.parse::<LitStr>()?;
let alias = if input.peek(Token![as]) {
Some((input.parse::<Token![as]>()?, input.parse::<Ident>()?))
} else {
None
};
Ok(ImportItem { vis, path, alias })
}
}
/// Represents the full body of the macro invocation, containing
/// semicolon-separated entries.
struct ImportList {
imports: Punctuated<ImportItem, Token![;]>,
}
impl Parse for ImportList {
/// Parses a full stream of semicolon-terminated `ImportItem` entries.
fn parse(input: ParseStream) -> syn::Result<Self> {
Ok(ImportList { imports: Punctuated::parse_terminated(input)? })
}
}
/// The entry point for `webrtc::import!`.
///
/// This proc-macro executes during host compile time. It scans the list of
/// absolute GN path strings, prepends the build context's `WEBRTC_GN_PREFIX`
/// (injected via GN `rustenv`), and forwards the rewritten token tree onto
/// Chromium's canonical `chromium::import!` macro.
#[proc_macro]
pub fn import(input: TokenStream) -> TokenStream {
// Read the build root prefix provided by GN's `rustenv` definition.
// Defaults to standalone root "//" if not set.
let prefix = std::env::var("WEBRTC_GN_PREFIX").unwrap_or_else(|_| "//".to_string());
let list = parse_macro_input!(input as ImportList);
let mut adjusted_tokens = quote! {};
for item in list.imports {
let vis = item.vis;
let path_str = item.path.value();
// Delegate the string manipulation logic to the shared, unittested path_utils
// module.
let adjusted_path = path_utils::adjust_path(&prefix, &path_str);
let new_path = LitStr::new(&adjusted_path, item.path.span());
let alias_tokens = item.alias.map(|(as_tok, ident)| quote! { #as_tok #ident });
// Reassemble the item with the new path literal token
adjusted_tokens.extend(quote! {
#vis #new_path #alias_tokens ;
});
}
// Expand into a call to Chromium's macro backend, passing the modified paths.
let expanded = quote! {
::chromium::import! { #adjusted_tokens }
};
expanded.into()
}