blob: 7a125ae72ccdbe8b4d7e5ae7454b59fa96c033e7 [file] [log] [blame]
David Tolnayed6ba4a2021-01-01 14:59:40 -08001use crate::syntax::symbol::Segment;
David Tolnay77a5e752021-01-01 14:15:18 -08002use crate::syntax::{Lifetimes, NamedType, Pair, Symbol};
David Tolnay60e7aa62020-11-01 12:34:51 -08003use proc_macro2::{Ident, Span};
David Tolnayed6ba4a2021-01-01 14:59:40 -08004use std::fmt::{self, Display};
David Tolnay8faec772020-11-02 00:18:19 -08005use std::iter;
David Tolnay1d5ffbb2021-01-01 19:28:34 -08006use syn::parse::{Error, Result};
David Tolnay4a79b7f2020-12-30 19:48:42 -08007use syn::punctuated::Punctuated;
David Tolnay60e7aa62020-11-01 12:34:51 -08008
David Tolnayed6ba4a2021-01-01 14:59:40 -08009#[derive(Clone)]
10pub struct ForeignName {
11 text: String,
David Tolnayed6ba4a2021-01-01 14:59:40 -080012}
13
David Tolnay60e7aa62020-11-01 12:34:51 -080014impl Pair {
David Tolnay8faec772020-11-02 00:18:19 -080015 pub fn to_symbol(&self) -> Symbol {
David Tolnayed6ba4a2021-01-01 14:59:40 -080016 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)
David Tolnay8faec772020-11-02 00:18:19 -080022 }
23
24 pub fn to_fully_qualified(&self) -> String {
David Tolnaydee9fa32020-12-21 14:40:50 -080025 let mut fully_qualified = String::new();
David Tolnayed6ba4a2021-01-01 14:59:40 -080026 for segment in &self.namespace {
David Tolnaydee9fa32020-12-21 14:40:50 -080027 fully_qualified += "::";
28 fully_qualified += &segment.to_string();
29 }
David Tolnayed6ba4a2021-01-01 14:59:40 -080030 fully_qualified += "::";
31 fully_qualified += &self.cxx.to_string();
David Tolnaydee9fa32020-12-21 14:40:50 -080032 fully_qualified
David Tolnay8faec772020-11-02 00:18:19 -080033 }
David Tolnay60e7aa62020-11-01 12:34:51 -080034}
35
David Tolnay77a5e752021-01-01 14:15:18 -080036impl NamedType {
David Tolnay7cd9fec2020-12-21 15:03:18 -080037 pub fn new(rust: Ident) -> Self {
David Tolnay4a79b7f2020-12-30 19:48:42 -080038 let generics = Lifetimes {
39 lt_token: None,
40 lifetimes: Punctuated::new(),
41 gt_token: None,
42 };
David Tolnay77a5e752021-01-01 14:15:18 -080043 NamedType { rust, generics }
David Tolnay60e7aa62020-11-01 12:34:51 -080044 }
45
David Tolnay60e7aa62020-11-01 12:34:51 -080046 pub fn span(&self) -> Span {
47 self.rust.span()
48 }
David Tolnay60e7aa62020-11-01 12:34:51 -080049}
David Tolnayed6ba4a2021-01-01 14:59:40 -080050
51impl ForeignName {
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++`).
David Tolnay1d5ffbb2021-01-01 19:28:34 -080055 match syn::parse_str::<Ident>(text) {
56 Ok(ident) => {
57 let text = ident.to_string();
David Tolnayd9a561c2021-09-12 05:08:32 -070058 Ok(ForeignName { text })
David Tolnay1d5ffbb2021-01-01 19:28:34 -080059 }
60 Err(err) => Err(Error::new(span, err)),
61 }
David Tolnayed6ba4a2021-01-01 14:59:40 -080062 }
63}
64
65impl Display for ForeignName {
66 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
67 formatter.write_str(&self.text)
68 }
69}
David Tolnay8a893c72021-04-22 13:20:48 -070070
71impl PartialEq<str> for ForeignName {
72 fn eq(&self, rhs: &str) -> bool {
73 self.text == rhs
74 }
75}