133d722a9Sopenharmony_ciuse crate::syntax::symbol::Segment;
233d722a9Sopenharmony_ciuse crate::syntax::{Lifetimes, NamedType, Pair, Symbol};
333d722a9Sopenharmony_ciuse proc_macro2::{Ident, Span};
433d722a9Sopenharmony_ciuse std::fmt::{self, Display};
533d722a9Sopenharmony_ciuse std::iter;
633d722a9Sopenharmony_ciuse syn::ext::IdentExt;
733d722a9Sopenharmony_ciuse syn::parse::{Error, Parser, Result};
833d722a9Sopenharmony_ciuse syn::punctuated::Punctuated;
933d722a9Sopenharmony_ci
1033d722a9Sopenharmony_ci#[derive(Clone)]
1133d722a9Sopenharmony_cipub struct ForeignName {
1233d722a9Sopenharmony_ci    text: String,
1333d722a9Sopenharmony_ci}
1433d722a9Sopenharmony_ci
1533d722a9Sopenharmony_ciimpl Pair {
1633d722a9Sopenharmony_ci    pub fn to_symbol(&self) -> Symbol {
1733d722a9Sopenharmony_ci        let segments = self
1833d722a9Sopenharmony_ci            .namespace
1933d722a9Sopenharmony_ci            .iter()
2033d722a9Sopenharmony_ci            .map(|ident| ident as &dyn Segment)
2133d722a9Sopenharmony_ci            .chain(iter::once(&self.cxx as &dyn Segment));
2233d722a9Sopenharmony_ci        Symbol::from_idents(segments)
2333d722a9Sopenharmony_ci    }
2433d722a9Sopenharmony_ci}
2533d722a9Sopenharmony_ci
2633d722a9Sopenharmony_ciimpl NamedType {
2733d722a9Sopenharmony_ci    pub fn new(rust: Ident) -> Self {
2833d722a9Sopenharmony_ci        let generics = Lifetimes {
2933d722a9Sopenharmony_ci            lt_token: None,
3033d722a9Sopenharmony_ci            lifetimes: Punctuated::new(),
3133d722a9Sopenharmony_ci            gt_token: None,
3233d722a9Sopenharmony_ci        };
3333d722a9Sopenharmony_ci        NamedType { rust, generics }
3433d722a9Sopenharmony_ci    }
3533d722a9Sopenharmony_ci
3633d722a9Sopenharmony_ci    pub fn span(&self) -> Span {
3733d722a9Sopenharmony_ci        self.rust.span()
3833d722a9Sopenharmony_ci    }
3933d722a9Sopenharmony_ci}
4033d722a9Sopenharmony_ci
4133d722a9Sopenharmony_ciimpl ForeignName {
4233d722a9Sopenharmony_ci    pub fn parse(text: &str, span: Span) -> Result<Self> {
4333d722a9Sopenharmony_ci        // TODO: support C++ names containing whitespace (`unsigned int`) or
4433d722a9Sopenharmony_ci        // non-alphanumeric characters (`operator++`).
4533d722a9Sopenharmony_ci        match Ident::parse_any.parse_str(text) {
4633d722a9Sopenharmony_ci            Ok(ident) => {
4733d722a9Sopenharmony_ci                let text = ident.to_string();
4833d722a9Sopenharmony_ci                Ok(ForeignName { text })
4933d722a9Sopenharmony_ci            }
5033d722a9Sopenharmony_ci            Err(err) => Err(Error::new(span, err)),
5133d722a9Sopenharmony_ci        }
5233d722a9Sopenharmony_ci    }
5333d722a9Sopenharmony_ci}
5433d722a9Sopenharmony_ci
5533d722a9Sopenharmony_ciimpl Display for ForeignName {
5633d722a9Sopenharmony_ci    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
5733d722a9Sopenharmony_ci        formatter.write_str(&self.text)
5833d722a9Sopenharmony_ci    }
5933d722a9Sopenharmony_ci}
6033d722a9Sopenharmony_ci
6133d722a9Sopenharmony_ciimpl PartialEq<str> for ForeignName {
6233d722a9Sopenharmony_ci    fn eq(&self, rhs: &str) -> bool {
6333d722a9Sopenharmony_ci        self.text == rhs
6433d722a9Sopenharmony_ci    }
6533d722a9Sopenharmony_ci}
66