// 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, /// 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 { let vis = input.parse::().ok(); let path = input.parse::()?; let alias = if input.peek(Token![as]) { Some((input.parse::()?, input.parse::()?)) } else { None }; Ok(ImportItem { vis, path, alias }) } } /// Represents the full body of the macro invocation, containing /// semicolon-separated entries. struct ImportList { imports: Punctuated, } impl Parse for ImportList { /// Parses a full stream of semicolon-terminated `ImportItem` entries. fn parse(input: ParseStream) -> syn::Result { 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() }