1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use crate::ast::*;
use crate::error::SyntaxError;
use crate::parser::Cache;
use crate::parser::FromPair;
use crate::syntax::pest::iterators::Pair;
use crate::syntax::Rule;

macro_rules! ident_subclass {
    (#[doc = $docstring:literal] $rule:expr => pub struct $name:ident) => {
        #[derive(Clone, Debug, PartialEq, Hash, Eq, PartialOrd, Ord)]
        #[doc=$docstring]
        pub struct $name {
            id: Ident,
        }

        impl $name {
            pub fn new(id: Ident) -> Self {
                Self { id }
            }

            pub fn as_id(&self) -> &Ident {
                &self.id
            }

            pub fn as_id_mut(&mut self) -> &mut Ident {
                &mut self.id
            }
        }

        impl AsRef<Ident> for $name {
            fn as_ref(&self) -> &Ident {
                &self.id
            }
        }

        impl AsMut<Ident> for $name {
            fn as_mut(&mut self) -> &mut Ident {
                &mut self.id
            }
        }

        impl ::std::fmt::Display for $name {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                self.id.fmt(f)
            }
        }

        impl From<Ident> for $name {
            fn from(id: Ident) -> Self {
                $name::new(id)
            }
        }

        impl From<UnprefixedIdent> for $name {
            fn from(id: UnprefixedIdent) -> Self {
                $name::new(Ident::from(id))
            }
        }

        impl From<PrefixedIdent> for $name {
            fn from(id: PrefixedIdent) -> Self {
                $name::new(Ident::from(id))
            }
        }

        impl From<Url> for $name {
            fn from(id: Url) -> Self {
                $name::new(Ident::from(id))
            }
        }

        impl From<$name> for Ident {
            fn from(id: $name) -> Self {
                id.id
            }
        }

        impl<'i> FromPair<'i> for $name {
            const RULE: Rule = $rule;
            unsafe fn from_pair_unchecked(
                pair: Pair<'i, Rule>,
                cache: &Cache,
            ) -> Result<Self, SyntaxError> {
                Ident::from_pair_unchecked(pair.into_inner().next().unwrap(), cache).map(From::from)
            }
        }

        impl ::std::str::FromStr for $name {
            type Err = $crate::error::SyntaxError;
            fn from_str(s: &str) -> Result<Self, Self::Err> {
                Ident::from_str(s).map(Self::from)
            }
        }
    };
}

macro_rules! ident_subclasses {
    ($(#[doc = $docstring:literal] $rule:expr => pub struct $name:ident;)*) => {
        $(ident_subclass!(#[doc = $docstring] $rule => pub struct $name);)*
    }
}

// NB(@althonos): All identifiers are defined as separate typedefs so that
//                `PartialEq` is not implemented and trying to compare a
//                `ClassId` with a `RelationId` would fail at compile-time.
ident_subclasses! {
    /// A unique identifier for a class (*i.e.* a term).
    Rule::ClassId => pub struct ClassIdent;

    /// A unique identifier for an instance.
    Rule::InstanceId => pub struct InstanceIdent;

    /// An OBO namespace identifier.
    Rule::NamespaceId => pub struct NamespaceIdent;

    /// A unique identifier for a typedef (*i.e.* a relation).
    Rule::RelationId => pub struct RelationIdent;

    /// A unique identifier for a subset
    Rule::SubsetId => pub struct SubsetIdent;

    /// A unique identifier for a synonym type.
    Rule::SynonymTypeId => pub struct SynonymTypeIdent;
}