blob: 0b79d5f9d8001370d767ebb2ff854de9a6b47cc5 [file] [log] [blame]
David Tolnay5ea922a2020-04-19 21:58:06 -07001use crate::syntax::namespace::Namespace;
Adrian Taylorc8713432020-10-21 18:20:55 -07002use crate::syntax::CppName;
David Tolnay5ea922a2020-04-19 21:58:06 -07003use proc_macro2::{Ident, TokenStream};
4use quote::ToTokens;
5use std::fmt::{self, Display, Write};
6
7// A mangled symbol consisting of segments separated by '$'.
David Tolnay8f16ae72020-10-08 18:21:13 -07008// For example: cxxbridge05$string$new
David Tolnay5ea922a2020-04-19 21:58:06 -07009pub struct Symbol(String);
10
11impl Display for Symbol {
12 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
13 Display::fmt(&self.0, formatter)
14 }
15}
16
17impl ToTokens for Symbol {
18 fn to_tokens(&self, tokens: &mut TokenStream) {
19 ToTokens::to_tokens(&self.0, tokens);
20 }
21}
22
23impl Symbol {
24 fn push(&mut self, segment: &dyn Display) {
25 let len_before = self.0.len();
26 if !self.0.is_empty() {
27 self.0.push('$');
28 }
29 self.0.write_fmt(format_args!("{}", segment)).unwrap();
30 assert!(self.0.len() > len_before);
31 }
Adrian Taylorc8713432020-10-21 18:20:55 -070032
33 pub fn from_idents<'a, T: Iterator<Item = &'a Ident>>(it: T) -> Self {
34 let mut symbol = Symbol(String::new());
35 for segment in it {
36 segment.write(&mut symbol);
37 }
38 assert!(!symbol.0.is_empty());
39 symbol
40 }
41
42 /// For example, for taking a symbol and then making a new symbol
43 /// for a vec of that symbol.
44 pub fn prefix_with(&self, prefix: &str) -> Symbol {
45 Symbol(format!("{}{}", prefix, self.to_string()))
46 }
David Tolnay5ea922a2020-04-19 21:58:06 -070047}
48
Adrian Taylorc8713432020-10-21 18:20:55 -070049pub trait Segment {
50 fn write(&self, symbol: &mut Symbol);
51}
52
53impl Segment for str {
David Tolnay5ea922a2020-04-19 21:58:06 -070054 fn write(&self, symbol: &mut Symbol) {
55 symbol.push(&self);
56 }
57}
Adrian Taylorc8713432020-10-21 18:20:55 -070058impl Segment for usize {
59 fn write(&self, symbol: &mut Symbol) {
60 symbol.push(&self);
61 }
62}
63impl Segment for Ident {
64 fn write(&self, symbol: &mut Symbol) {
65 symbol.push(&self);
66 }
67}
68impl Segment for Symbol {
69 fn write(&self, symbol: &mut Symbol) {
70 symbol.push(&self);
71 }
72}
David Tolnay5ea922a2020-04-19 21:58:06 -070073
74impl Segment for Namespace {
75 fn write(&self, symbol: &mut Symbol) {
76 for segment in self {
77 symbol.push(segment);
78 }
79 }
80}
81
Adrian Taylorc8713432020-10-21 18:20:55 -070082impl Segment for CppName {
83 fn write(&self, symbol: &mut Symbol) {
84 self.ns.write(symbol);
85 self.ident.write(symbol);
86 }
87}
88
David Tolnay5ea922a2020-04-19 21:58:06 -070089impl<T> Segment for &'_ T
90where
Adrian Taylorc8713432020-10-21 18:20:55 -070091 T: ?Sized + Segment + Display,
David Tolnay5ea922a2020-04-19 21:58:06 -070092{
93 fn write(&self, symbol: &mut Symbol) {
94 (**self).write(symbol);
95 }
96}
97
98pub fn join(segments: &[&dyn Segment]) -> Symbol {
99 let mut symbol = Symbol(String::new());
100 for segment in segments {
101 segment.write(&mut symbol);
102 }
103 assert!(!symbol.0.is_empty());
104 symbol
105}