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// For example: cxxbridge1$string$new 9pub 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 } 32 33 pub fn from_idents<'a>(it: impl Iterator<Item = &'a dyn Segment>) -> 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 43pub trait Segment { 44 fn write(&self, symbol: &mut Symbol); 45} 46 47impl Segment for str { 48 fn write(&self, symbol: &mut Symbol) { 49 symbol.push(&self); 50 } 51} 52 53impl Segment for usize { 54 fn write(&self, symbol: &mut Symbol) { 55 symbol.push(&self); 56 } 57} 58 59impl Segment for Ident { 60 fn write(&self, symbol: &mut Symbol) { 61 symbol.push(&self); 62 } 63} 64 65impl Segment for Symbol { 66 fn write(&self, symbol: &mut Symbol) { 67 symbol.push(&self); 68 } 69} 70 71impl Segment for Namespace { 72 fn write(&self, symbol: &mut Symbol) { 73 for segment in self { 74 symbol.push(segment); 75 } 76 } 77} 78 79impl Segment for Pair { 80 fn write(&self, symbol: &mut Symbol) { 81 self.namespace.write(symbol); 82 self.cxx.write(symbol); 83 } 84} 85 86impl Segment for ForeignName { 87 fn write(&self, symbol: &mut Symbol) { 88 // TODO: support C++ names containing whitespace (`unsigned int`) or 89 // non-alphanumeric characters (`operator++`). 90 self.to_string().write(symbol); 91 } 92} 93 94impl<T> Segment for &'_ T 95where 96 T: ?Sized + Segment + Display, 97{ 98 fn write(&self, symbol: &mut Symbol) { 99 (**self).write(symbol); 100 } 101} 102 103pub fn join(segments: &[&dyn Segment]) -> Symbol { 104 let mut symbol = Symbol(String::new()); 105 for segment in segments { 106 segment.write(&mut symbol); 107 } 108 assert!(!symbol.0.is_empty()); 109 symbol 110} 111