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::ext::IdentExt; 7 use syn::parse::{Error, Parser, Result}; 8 use syn::punctuated::Punctuated; 9 10 #[derive(Clone)] 11 pub struct ForeignName { 12 text: String, 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 } 25 26 impl NamedType { new(rust: Ident) -> Self27 pub fn new(rust: Ident) -> Self { 28 let generics = Lifetimes { 29 lt_token: None, 30 lifetimes: Punctuated::new(), 31 gt_token: None, 32 }; 33 NamedType { rust, generics } 34 } 35 span(&self) -> Span36 pub fn span(&self) -> Span { 37 self.rust.span() 38 } 39 } 40 41 impl ForeignName { parse(text: &str, span: Span) -> Result<Self>42 pub fn parse(text: &str, span: Span) -> Result<Self> { 43 // TODO: support C++ names containing whitespace (`unsigned int`) or 44 // non-alphanumeric characters (`operator++`). 45 match Ident::parse_any.parse_str(text) { 46 Ok(ident) => { 47 let text = ident.to_string(); 48 Ok(ForeignName { text }) 49 } 50 Err(err) => Err(Error::new(span, err)), 51 } 52 } 53 } 54 55 impl Display for ForeignName { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result56 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 57 formatter.write_str(&self.text) 58 } 59 } 60 61 impl PartialEq<str> for ForeignName { eq(&self, rhs: &str) -> bool62 fn eq(&self, rhs: &str) -> bool { 63 self.text == rhs 64 } 65 } 66