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 span: Span, 13 } 14 15 impl Pair { to_symbol(&self) -> Symbol16 pub fn to_symbol(&self) -> Symbol { 17 let segments = self 18 .namespace 19 .iter() 20 .map(|ident| ident as &dyn Segment) 21 .chain(iter::once(&self.cxx as &dyn Segment)); 22 Symbol::from_idents(segments) 23 } 24 to_fully_qualified(&self) -> String25 pub fn to_fully_qualified(&self) -> String { 26 let mut fully_qualified = String::new(); 27 for segment in &self.namespace { 28 fully_qualified += "::"; 29 fully_qualified += &segment.to_string(); 30 } 31 fully_qualified += "::"; 32 fully_qualified += &self.cxx.to_string(); 33 fully_qualified 34 } 35 } 36 37 impl NamedType { new(rust: Ident) -> Self38 pub fn new(rust: Ident) -> Self { 39 let generics = Lifetimes { 40 lt_token: None, 41 lifetimes: Punctuated::new(), 42 gt_token: None, 43 }; 44 NamedType { rust, generics } 45 } 46 span(&self) -> Span47 pub fn span(&self) -> Span { 48 self.rust.span() 49 } 50 } 51 52 impl ForeignName { parse(text: &str, span: Span) -> Result<Self>53 pub fn parse(text: &str, span: Span) -> Result<Self> { 54 // TODO: support C++ names containing whitespace (`unsigned int`) or 55 // non-alphanumeric characters (`operator++`). 56 match syn::parse_str::<Ident>(text) { 57 Ok(ident) => { 58 let text = ident.to_string(); 59 Ok(ForeignName { text, span }) 60 } 61 Err(err) => Err(Error::new(span, err)), 62 } 63 } 64 } 65 66 impl Display for ForeignName { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result67 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 68 formatter.write_str(&self.text) 69 } 70 } 71