133d722a9Sopenharmony_ciuse crate::syntax::namespace::Namespace; 233d722a9Sopenharmony_ciuse crate::syntax::{ForeignName, Pair}; 333d722a9Sopenharmony_ciuse proc_macro2::{Ident, TokenStream}; 433d722a9Sopenharmony_ciuse quote::ToTokens; 533d722a9Sopenharmony_ciuse std::fmt::{self, Display, Write}; 633d722a9Sopenharmony_ci 733d722a9Sopenharmony_ci// A mangled symbol consisting of segments separated by '$'. 833d722a9Sopenharmony_ci// For example: cxxbridge1$string$new 933d722a9Sopenharmony_cipub struct Symbol(String); 1033d722a9Sopenharmony_ci 1133d722a9Sopenharmony_ciimpl Display for Symbol { 1233d722a9Sopenharmony_ci fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 1333d722a9Sopenharmony_ci Display::fmt(&self.0, formatter) 1433d722a9Sopenharmony_ci } 1533d722a9Sopenharmony_ci} 1633d722a9Sopenharmony_ci 1733d722a9Sopenharmony_ciimpl ToTokens for Symbol { 1833d722a9Sopenharmony_ci fn to_tokens(&self, tokens: &mut TokenStream) { 1933d722a9Sopenharmony_ci ToTokens::to_tokens(&self.0, tokens); 2033d722a9Sopenharmony_ci } 2133d722a9Sopenharmony_ci} 2233d722a9Sopenharmony_ci 2333d722a9Sopenharmony_ciimpl Symbol { 2433d722a9Sopenharmony_ci fn push(&mut self, segment: &dyn Display) { 2533d722a9Sopenharmony_ci let len_before = self.0.len(); 2633d722a9Sopenharmony_ci if !self.0.is_empty() { 2733d722a9Sopenharmony_ci self.0.push('$'); 2833d722a9Sopenharmony_ci } 2933d722a9Sopenharmony_ci self.0.write_fmt(format_args!("{}", segment)).unwrap(); 3033d722a9Sopenharmony_ci assert!(self.0.len() > len_before); 3133d722a9Sopenharmony_ci } 3233d722a9Sopenharmony_ci 3333d722a9Sopenharmony_ci pub fn from_idents<'a>(it: impl Iterator<Item = &'a dyn Segment>) -> Self { 3433d722a9Sopenharmony_ci let mut symbol = Symbol(String::new()); 3533d722a9Sopenharmony_ci for segment in it { 3633d722a9Sopenharmony_ci segment.write(&mut symbol); 3733d722a9Sopenharmony_ci } 3833d722a9Sopenharmony_ci assert!(!symbol.0.is_empty()); 3933d722a9Sopenharmony_ci symbol 4033d722a9Sopenharmony_ci } 4133d722a9Sopenharmony_ci} 4233d722a9Sopenharmony_ci 4333d722a9Sopenharmony_cipub trait Segment { 4433d722a9Sopenharmony_ci fn write(&self, symbol: &mut Symbol); 4533d722a9Sopenharmony_ci} 4633d722a9Sopenharmony_ci 4733d722a9Sopenharmony_ciimpl Segment for str { 4833d722a9Sopenharmony_ci fn write(&self, symbol: &mut Symbol) { 4933d722a9Sopenharmony_ci symbol.push(&self); 5033d722a9Sopenharmony_ci } 5133d722a9Sopenharmony_ci} 5233d722a9Sopenharmony_ci 5333d722a9Sopenharmony_ciimpl Segment for usize { 5433d722a9Sopenharmony_ci fn write(&self, symbol: &mut Symbol) { 5533d722a9Sopenharmony_ci symbol.push(&self); 5633d722a9Sopenharmony_ci } 5733d722a9Sopenharmony_ci} 5833d722a9Sopenharmony_ci 5933d722a9Sopenharmony_ciimpl Segment for Ident { 6033d722a9Sopenharmony_ci fn write(&self, symbol: &mut Symbol) { 6133d722a9Sopenharmony_ci symbol.push(&self); 6233d722a9Sopenharmony_ci } 6333d722a9Sopenharmony_ci} 6433d722a9Sopenharmony_ci 6533d722a9Sopenharmony_ciimpl Segment for Symbol { 6633d722a9Sopenharmony_ci fn write(&self, symbol: &mut Symbol) { 6733d722a9Sopenharmony_ci symbol.push(&self); 6833d722a9Sopenharmony_ci } 6933d722a9Sopenharmony_ci} 7033d722a9Sopenharmony_ci 7133d722a9Sopenharmony_ciimpl Segment for Namespace { 7233d722a9Sopenharmony_ci fn write(&self, symbol: &mut Symbol) { 7333d722a9Sopenharmony_ci for segment in self { 7433d722a9Sopenharmony_ci symbol.push(segment); 7533d722a9Sopenharmony_ci } 7633d722a9Sopenharmony_ci } 7733d722a9Sopenharmony_ci} 7833d722a9Sopenharmony_ci 7933d722a9Sopenharmony_ciimpl Segment for Pair { 8033d722a9Sopenharmony_ci fn write(&self, symbol: &mut Symbol) { 8133d722a9Sopenharmony_ci self.namespace.write(symbol); 8233d722a9Sopenharmony_ci self.cxx.write(symbol); 8333d722a9Sopenharmony_ci } 8433d722a9Sopenharmony_ci} 8533d722a9Sopenharmony_ci 8633d722a9Sopenharmony_ciimpl Segment for ForeignName { 8733d722a9Sopenharmony_ci fn write(&self, symbol: &mut Symbol) { 8833d722a9Sopenharmony_ci // TODO: support C++ names containing whitespace (`unsigned int`) or 8933d722a9Sopenharmony_ci // non-alphanumeric characters (`operator++`). 9033d722a9Sopenharmony_ci self.to_string().write(symbol); 9133d722a9Sopenharmony_ci } 9233d722a9Sopenharmony_ci} 9333d722a9Sopenharmony_ci 9433d722a9Sopenharmony_ciimpl<T> Segment for &'_ T 9533d722a9Sopenharmony_ciwhere 9633d722a9Sopenharmony_ci T: ?Sized + Segment + Display, 9733d722a9Sopenharmony_ci{ 9833d722a9Sopenharmony_ci fn write(&self, symbol: &mut Symbol) { 9933d722a9Sopenharmony_ci (**self).write(symbol); 10033d722a9Sopenharmony_ci } 10133d722a9Sopenharmony_ci} 10233d722a9Sopenharmony_ci 10333d722a9Sopenharmony_cipub fn join(segments: &[&dyn Segment]) -> Symbol { 10433d722a9Sopenharmony_ci let mut symbol = Symbol(String::new()); 10533d722a9Sopenharmony_ci for segment in segments { 10633d722a9Sopenharmony_ci segment.write(&mut symbol); 10733d722a9Sopenharmony_ci } 10833d722a9Sopenharmony_ci assert!(!symbol.0.is_empty()); 10933d722a9Sopenharmony_ci symbol 11033d722a9Sopenharmony_ci} 111