1 use crate::syntax::symbol::Segment; 2 use crate::syntax::{Lifetimes, NamedType, Pair, Symbol}; 3 use proc_macro2::{Ident, Span}; 4 use std::fmt::{self, Display}; 5 use std::iter; 6 use syn::parse::{Error, Result}; 7 use syn::punctuated::Punctuated; 8 9 #[derive(Clone)] 10 pub struct ForeignName { 11 text: String, 12 } 13 14 impl Pair { to_symbol(&self) -> Symbol15 pub fn to_symbol(&self) -> Symbol { 16 let segments = self 17 .namespace 18 .iter() 19 .map(|ident| ident as &dyn Segment) 20 .chain(iter::once(&self.cxx as &dyn Segment)); 21 Symbol::from_idents(segments) 22 } 23 to_fully_qualified(&self) -> String24 pub fn to_fully_qualified(&self) -> String { 25 let mut fully_qualified = String::new(); 26 for segment in &self.namespace { 27 fully_qualified += "::"; 28 fully_qualified += &segment.to_string(); 29 } 30 fully_qualified += "::"; 31 fully_qualified += &self.cxx.to_string(); 32 fully_qualified 33 } 34 } 35 36 impl NamedType { new(rust: Ident) -> Self37 pub fn new(rust: Ident) -> Self { 38 let generics = Lifetimes { 39 lt_token: None, 40 lifetimes: Punctuated::new(), 41 gt_token: None, 42 }; 43 NamedType { rust, generics } 44 } 45 span(&self) -> Span46 pub fn span(&self) -> Span { 47 self.rust.span() 48 } 49 } 50 51 impl ForeignName { parse(text: &str, span: Span) -> Result<Self>52 pub fn parse(text: &str, span: Span) -> Result<Self> { 53 // TODO: support C++ names containing whitespace (`unsigned int`) or 54 // non-alphanumeric characters (`operator++`). 55 match syn::parse_str::<Ident>(text) { 56 Ok(ident) => { 57 let text = ident.to_string(); 58 Ok(ForeignName { text }) 59 } 60 Err(err) => Err(Error::new(span, err)), 61 } 62 } 63 } 64 65 impl Display for ForeignName { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result66 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 67 formatter.write_str(&self.text) 68 } 69 } 70 71 impl PartialEq<str> for ForeignName { eq(&self, rhs: &str) -> bool72 fn eq(&self, rhs: &str) -> bool { 73 self.text == rhs 74 } 75 } 76