Skip to main content

ab_riscv_macros_common/
code_utils.rs

1//! This module contains hacks for Rust nightly syntax to make it compatible with `syn`
2// TODO: Remove this module once `syn` supports used Rust nightly syntax
3
4const FROM_IMPL_CONST_1: &str = " const ";
5const TO_IMPL_CONST_1: &str = " cnst::";
6const FROM_IMPL_CONST_2: &str = " const  ";
7const TO_IMPL_CONST_2: &str = " cnst ::";
8const FROM_IMPL_CONST_REVERT_1: &str = "pub cnst::";
9const TO_IMPL_CONST_REVERT_1: &str = "pub const ";
10const FROM_IMPL_CONST_REVERT_2: &str = "pub cnst ::";
11const TO_IMPL_CONST_REVERT_2: &str = "pub const  ";
12const FROM_IMPL_CONST_REVERT_3: &str = ") cnst::";
13const TO_IMPL_CONST_REVERT_3: &str = ") const ";
14const FROM_IMPL_CONST_REVERT_4: &str = ") cnst ::";
15const TO_IMPL_CONST_REVERT_4: &str = ") const  ";
16const FROM_IMPL_CONST_REVERT_5: &str = "cnst::fn";
17const TO_IMPL_CONST_REVERT_5: &str = "const fn";
18
19const FROM_BRACKETS_CONST_1: &str = "[const] ";
20const TO_BRACKETS_CONST_1: &str = "BRCONST+";
21const FROM_BRACKETS_CONST_2: &str = " [const] ";
22const TO_BRACKETS_CONST_2: &str = "BRCONST +";
23
24/// Replace bits of Rust nightly syntax with something that is technically valid in stable Rust, so
25/// `syn` can parse it
26pub fn pre_process_rust_code(s: &mut str) {
27    replace_inplace(s, FROM_IMPL_CONST_1, TO_IMPL_CONST_1);
28    replace_inplace(s, FROM_IMPL_CONST_2, TO_IMPL_CONST_2);
29    replace_inplace(s, FROM_IMPL_CONST_REVERT_1, TO_IMPL_CONST_REVERT_1);
30    replace_inplace(s, FROM_IMPL_CONST_REVERT_2, TO_IMPL_CONST_REVERT_2);
31    replace_inplace(s, FROM_IMPL_CONST_REVERT_3, TO_IMPL_CONST_REVERT_3);
32    replace_inplace(s, FROM_IMPL_CONST_REVERT_4, TO_IMPL_CONST_REVERT_4);
33    replace_inplace(s, FROM_IMPL_CONST_REVERT_5, TO_IMPL_CONST_REVERT_5);
34    replace_inplace(s, FROM_BRACKETS_CONST_1, TO_BRACKETS_CONST_1);
35    replace_inplace(s, FROM_BRACKETS_CONST_2, TO_BRACKETS_CONST_2);
36}
37
38/// The inverse of [`pre_process_rust_code()`]
39pub fn post_process_rust_code(s: &mut str) {
40    replace_inplace(s, TO_IMPL_CONST_1, FROM_IMPL_CONST_1);
41    replace_inplace(s, TO_IMPL_CONST_2, FROM_IMPL_CONST_2);
42    replace_inplace(s, TO_BRACKETS_CONST_1, FROM_BRACKETS_CONST_1);
43    replace_inplace(s, TO_BRACKETS_CONST_2, FROM_BRACKETS_CONST_2);
44}
45
46fn replace_inplace(mut s: &mut str, from: &str, to: &str) {
47    assert_eq!(from.len(), to.len(), "`{from}` != `{to}`");
48
49    if from.is_empty() {
50        return;
51    }
52
53    while let Some(found) = s.find(from) {
54        let start = found;
55        let end = found + from.len();
56
57        // SAFETY: Replacing a valid string with a valid string of the same length
58        unsafe { s.as_bytes_mut() }
59            .get_mut(start..end)
60            .expect("Just found a string of the desired length; qed")
61            .copy_from_slice(to.as_bytes());
62
63        s = &mut s[end..];
64    }
65}