cxx_build/syntax/
symbol.rs

1use crate::syntax::namespace::Namespace;
2use crate::syntax::{ForeignName, Pair};
3use proc_macro2::{Ident, TokenStream};
4use quote::ToTokens;
5use std::fmt::{self, Display, Write};
6
7// A mangled symbol consisting of segments separated by '$'.
8// Example: cxxbridge1$string$new
9#[derive(#[automatically_derived]
impl ::core::cmp::Eq for Symbol {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) -> () {
        let _: ::core::cmp::AssertParamIsEq<String>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for Symbol {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
        ::core::hash::Hash::hash(&self.0, state)
    }
}Hash, #[automatically_derived]
impl ::core::cmp::PartialEq for Symbol {
    #[inline]
    fn eq(&self, other: &Symbol) -> bool { self.0 == other.0 }
}PartialEq)]
10pub(crate) struct Symbol(String);
11
12impl Display for Symbol {
13    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
14        Display::fmt(&self.0, formatter)
15    }
16}
17
18impl ToTokens for Symbol {
19    fn to_tokens(&self, tokens: &mut TokenStream) {
20        ToTokens::to_tokens(&self.0, tokens);
21    }
22}
23
24impl Symbol {
25    fn push(&mut self, segment: &dyn Display) {
26        let len_before = self.0.len();
27        if !self.0.is_empty() {
28            self.0.push('$');
29        }
30        self.0.write_fmt(format_args!("{0}", segment)format_args!("{}", segment)).unwrap();
31        if !(self.0.len() > len_before) {
    ::core::panicking::panic("assertion failed: self.0.len() > len_before")
};assert!(self.0.len() > len_before);
32    }
33
34    pub(crate) fn from_idents<'a>(it: impl Iterator<Item = &'a dyn Segment>) -> Self {
35        let mut symbol = Symbol(String::new());
36        for segment in it {
37            segment.write(&mut symbol);
38        }
39        if !!symbol.0.is_empty() {
    ::core::panicking::panic("assertion failed: !symbol.0.is_empty()")
};assert!(!symbol.0.is_empty());
40        symbol
41    }
42
43    #[cfg_attr(proc_macro, expect(dead_code))]
44    pub(crate) fn contains(&self, ch: char) -> bool {
45        self.0.contains(ch)
46    }
47}
48
49pub(crate) trait Segment {
50    fn write(&self, symbol: &mut Symbol);
51}
52
53impl Segment for str {
54    fn write(&self, symbol: &mut Symbol) {
55        symbol.push(&self);
56    }
57}
58
59impl Segment for usize {
60    fn write(&self, symbol: &mut Symbol) {
61        symbol.push(&self);
62    }
63}
64
65impl Segment for Ident {
66    fn write(&self, symbol: &mut Symbol) {
67        symbol.push(&self);
68    }
69}
70
71impl Segment for Symbol {
72    fn write(&self, symbol: &mut Symbol) {
73        symbol.push(&self);
74    }
75}
76
77impl Segment for Namespace {
78    fn write(&self, symbol: &mut Symbol) {
79        for segment in self {
80            symbol.push(segment);
81        }
82    }
83}
84
85impl Segment for Pair {
86    fn write(&self, symbol: &mut Symbol) {
87        self.namespace.write(symbol);
88        self.cxx.write(symbol);
89    }
90}
91
92impl Segment for ForeignName {
93    fn write(&self, symbol: &mut Symbol) {
94        // TODO: support C++ names containing whitespace (`unsigned int`) or
95        // non-alphanumeric characters (`operator++`).
96        self.to_string().write(symbol);
97    }
98}
99
100impl<T> Segment for &'_ T
101where
102    T: ?Sized + Segment + Display,
103{
104    fn write(&self, symbol: &mut Symbol) {
105        (**self).write(symbol);
106    }
107}
108
109pub(crate) fn join(segments: &[&dyn Segment]) -> Symbol {
110    let mut symbol = Symbol(String::new());
111    for segment in segments {
112        segment.write(&mut symbol);
113    }
114    if !!symbol.0.is_empty() {
    ::core::panicking::panic("assertion failed: !symbol.0.is_empty()")
};assert!(!symbol.0.is_empty());
115    symbol
116}