sphinx_inv 0.4.0

A rust library to parse Sphinx `objects.inv` files
Documentation
use std::{fmt::Display, str::FromStr};

use winnow::{
    ModalResult, Parser,
    error::{ContextError, StrContext},
    stream::AsChar,
    token::take_till,
};

use crate::roles::SphinxType;

/// SIP is a tool for automatically generating Python bindings for C and C++ libraries. [see more](https://python-sip.readthedocs.io/en/stable/introduction.html)
#[derive(Debug, PartialEq, Clone)]
pub enum SipRole {
    /// an SIP method declaration. [see more](https://python-sip.readthedocs.io/en/stable/directives.html#methodcode)
    Method,

    /// an SIP method declaration on an associated class. [see more](https://python-sip.readthedocs.io/en/stable/directives.html#methodcode)
    Member,

    /// A SIP class definition. [see more](https://python-sip.readthedocs.io/en/stable/annotations.html#class-annotations)
    Class,

    /// an SIP defined attribute [see more](https://python-sip.readthedocs.io/en/stable/other_topics.html#lazy-type-attributes)
    Attribute,

    /// A SIP enum. [see more](https://python-sip.readthedocs.io/en/stable/annotations.html#ref-enum-annos)
    Enum,

    /// A SIP module. [see more](https://python-sip.readthedocs.io/en/stable/directives.html#module)
    Module,

    /// A QT signal used in a SIP module. [see more](https://doc.qt.io/qt-6/signalsandslots.html)
    Signal,
}
impl Display for SipRole {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str(match self {
            SipRole::Method => "method",
            SipRole::Member => "member",
            SipRole::Class => "class",
            SipRole::Signal => "signal",
            SipRole::Module => "module",
            SipRole::Attribute => "attribute",
            SipRole::Enum => "enum",
        })
    }
}

impl FromStr for SipRole {
    type Err = ContextError;

    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
        match s {
            "method" => Ok(SipRole::Method),
            "member" => Ok(SipRole::Member),
            "class" => Ok(SipRole::Class),
            "signal" => Ok(SipRole::Signal),
            "module" => Ok(SipRole::Module),
            "attribute" => Ok(SipRole::Attribute),
            "enum" => Ok(SipRole::Enum),

            // this is only really necessary to communicate with the parser
            // so we don't have to communicate more than "it failed"
            // as this should never happen
            _ => Err(ContextError::new()),
        }
    }
}

/// may not contain whitespace but may contain other colons
pub(crate) fn sip_role(input: &mut &str) -> ModalResult<SphinxType> {
    let role = take_till(1.., AsChar::is_space)
        .context(StrContext::Label("sip role"))
        .parse_to()
        .parse_next(input)?;
    Ok(SphinxType::Sip(role))
}

#[cfg(test)]
mod test {

    use crate::roles::sip_role::{SipRole, sip_role};
    use winnow::ModalResult;

    use crate::roles::SphinxType;

    #[test]
    fn invalid_sip_role() {
        let mut input = "asdfasdf";

        let result = sip_role(&mut input);
        assert!(result.is_err());
    }
    #[test]
    fn c_role_enum() -> ModalResult<()> {
        let mut input = "method";

        let role = sip_role(&mut input)?;

        assert_eq!(role, SphinxType::Sip(SipRole::Method));
        Ok(())
    }
}