blob: a40baaf975bc3e5fc1a9721e094c86a88007a285 [file] [log] [blame]
David Tolnay5ea922a2020-04-19 21:58:06 -07001use crate::syntax::namespace::Namespace;
2use proc_macro2::{Ident, TokenStream};
3use quote::ToTokens;
4use std::fmt::{self, Display, Write};
5
6// A mangled symbol consisting of segments separated by '$'.
7// For example: cxxbridge02$string$new
8pub struct Symbol(String);
9
10impl Display for Symbol {
11 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
12 Display::fmt(&self.0, formatter)
13 }
14}
15
16impl ToTokens for Symbol {
17 fn to_tokens(&self, tokens: &mut TokenStream) {
18 ToTokens::to_tokens(&self.0, tokens);
19 }
20}
21
22impl Symbol {
23 fn push(&mut self, segment: &dyn Display) {
24 let len_before = self.0.len();
25 if !self.0.is_empty() {
26 self.0.push('$');
27 }
28 self.0.write_fmt(format_args!("{}", segment)).unwrap();
29 assert!(self.0.len() > len_before);
30 }
31}
32
33pub trait Segment: Display {
34 fn write(&self, symbol: &mut Symbol) {
35 symbol.push(&self);
36 }
37}
38
39impl Segment for str {}
40impl Segment for Ident {}
41
42impl Segment for Namespace {
43 fn write(&self, symbol: &mut Symbol) {
44 for segment in self {
45 symbol.push(segment);
46 }
47 }
48}
49
50impl<T> Segment for &'_ T
51where
52 T: ?Sized + Segment,
53{
54 fn write(&self, symbol: &mut Symbol) {
55 (**self).write(symbol);
56 }
57}
58
59pub fn join(segments: &[&dyn Segment]) -> Symbol {
60 let mut symbol = Symbol(String::new());
61 for segment in segments {
62 segment.write(&mut symbol);
63 }
64 assert!(!symbol.0.is_empty());
65 symbol
66}