1#![cfg_attr(not(target_os = "windows"), allow(unused))]
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::{LitStr, parse_macro_input};
6
7/// A macro used in tests for cross-platform path string literals in tests. On Windows it replaces
8/// `/` with `\\` and adds `C:` to the beginning of absolute paths. On other platforms, the path is
9/// returned unmodified.
10///
11/// # Example
12/// ```rust
13/// use util_macros::path;
14///
15/// let path = path!("/Users/user/file.txt");
16/// #[cfg(target_os = "windows")]
17/// assert_eq!(path, "C:\\Users\\user\\file.txt");
18/// #[cfg(not(target_os = "windows"))]
19/// assert_eq!(path, "/Users/user/file.txt");
20/// ```
21#[proc_macro]
22pub fn path(input: TokenStream) -> TokenStream {
23 let path = parse_macro_input!(input as LitStr);
24 let mut path = path.value();
25
26 #[cfg(target_os = "windows")]
27 {
28 path = path.replace("/", "\\");
29 if path.starts_with("\\") {
30 path = format!("C:{}", path);
31 }
32 }
33
34 TokenStream::from(quote! {
35 #path
36 })
37}
38
39/// This macro replaces the path prefix `file:///` with `file:///C:/` for Windows.
40/// But if the target OS is not Windows, the URI is returned as is.
41///
42/// # Example
43/// ```rust
44/// use util_macros::uri;
45///
46/// let uri = uri!("file:///path/to/file");
47/// #[cfg(target_os = "windows")]
48/// assert_eq!(uri, "file:///C:/path/to/file");
49/// #[cfg(not(target_os = "windows"))]
50/// assert_eq!(uri, "file:///path/to/file");
51/// ```
52#[proc_macro]
53pub fn uri(input: TokenStream) -> TokenStream {
54 let uri = parse_macro_input!(input as LitStr);
55 let uri = uri.value();
56
57 #[cfg(target_os = "windows")]
58 let uri = uri.replace("file:///", "file:///C:/");
59
60 TokenStream::from(quote! {
61 #uri
62 })
63}
64
65/// This macro replaces the line endings `\n` with `\r\n` for Windows.
66/// But if the target OS is not Windows, the line endings are returned as is.
67///
68/// # Example
69/// ```rust
70/// use util_macros::line_endings;
71///
72/// let text = line_endings!("Hello\nWorld");
73/// #[cfg(target_os = "windows")]
74/// assert_eq!(text, "Hello\r\nWorld");
75/// #[cfg(not(target_os = "windows"))]
76/// assert_eq!(text, "Hello\nWorld");
77/// ```
78#[proc_macro]
79pub fn line_endings(input: TokenStream) -> TokenStream {
80 let text = parse_macro_input!(input as LitStr);
81 let text = text.value();
82
83 #[cfg(target_os = "windows")]
84 let text = text.replace("\n", "\r\n");
85
86 TokenStream::from(quote! {
87 #text
88 })
89}