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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/*!
![names](https://img.shields.io/badge/RDFtk-names-BD1B89?logo=data:image/png;base64,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)
This crate provides a set of modules that contain the `IRI`s and `QName` strings for commonly used vocabularies. It also provides macro support for defining new namespaces in the same style as this library.

The vocabularies supported can be found [below](#modules).

# Macro Example

The following example replicates the `geo` module using the `namespace!` macro. Note that as this
macro uses `paste::item` the client will need to have a dependency on the
[paste crate](https://crates.io/crates/paste).


```rust,ignore
#[macro_use]
extern crate paste;

#[macro_use]
extern crate rdftk_names;

use rdftk_names::Vocabulary;

namespace! {
    GeoSpatialVocabulary,
    "geo",
    "http://www.w3.org/2003/01/geo/wgs84_pos#",
    {
        spatial_thing, "SpatialThing",
        temporal_thing, "TemporalThing",
        event, "Event",
        point, "Point",
        lat, "lat",
        location, "location",
        long, "long",
        alt, "alt",
        lat_long, "lat_long"
    }
}
```

*/

#![warn(
    // ---------- Stylistic
    future_incompatible,
    nonstandard_style,
    rust_2018_idioms,
    trivial_casts,
    trivial_numeric_casts,
    // ---------- Public
    missing_debug_implementations,
    missing_docs,
    unreachable_pub,
    // ---------- Unsafe
    unsafe_code,
    // ---------- Unused
    unused_extern_crates,
    unused_import_braces,
    unused_qualifications,
    unused_results,
)]

#[allow(unused_imports)]
#[macro_use]
extern crate lazy_static;

#[allow(unused_imports)]
#[macro_use]
extern crate paste;

// ------------------------------------------------------------------------------------------------
// Macros
// ------------------------------------------------------------------------------------------------

///
/// This macro produces the constants and functions to describe a vocabulary. It creates the
/// following items.
///
/// 1. An identifier for the vocabulary struct.
/// 1. A constant, `PREFIX` that contains the string passed in the `$prefix` parameter.
/// 1. A constant, `NAMESPACE` that contains the string passed in the `namespace` parameter.
/// 1. For each pair of `$fn_name`, `$name` (assuming `foo` and `"Foo"`):
///    1. create a function `fn foo() -> IRI` that returns the name as a full IRI. This concatenates
///       `NAMESPACE` and `$name`.
///    1. create a function `fn foo_qname() -> String` that returns a qualified name String. This
///       concatenates the `PREFIX`, `":"`, and `$name`.
///
/// # Example
///
/// Given the following namespace invocation,
///
/// ```rust,ignore
/// #[macro_use]
/// extern crate rdftk_names;
///
/// namespace!(FooBarVocab, "fb", "http://example.com/schema/FooBar#", { foo, "Foo" } );
/// ```
///
/// The following would be generated.
///
/// ```rust, ignore
/// use rdftk_iri::IRI;
/// use std::str::FromStr;
///
/// pub struct FooBarVocab { ... }
///
/// impl Default for FooBarVocab { ... }
///
/// impl Vocabulary for FooBarVocab { ... }
///
/// impl FooBarVocab {
///     pub fn foo(&self) -> &Arc<IRI> { ... }
///     pub foo_qname(&self) -> &String { ... }
/// }
/// ```
///
#[macro_export]
macro_rules! namespace {
    ($prefix:expr, $namespace:expr, { $($fn_name:ident, $name:expr),* }) => {
        use rdftk_iri::{IRI, IRIRef};
        use std::str::FromStr;
        use std::collections::HashMap;

        const PREFIX: &str = $prefix;

        const NAMESPACE: &str = $namespace;

        lazy_static! {
            static ref NS_IRI: IRIRef = IRIRef::new(NAMESPACE.parse().unwrap());
            static ref NS_CACHE: HashMap<String, (IRIRef, String)> = make_cache();
        }

        fn make_cache() -> HashMap<String, (IRIRef, String)> {
            let mut cache: HashMap<String, (IRIRef, String)> = Default::default();
            $(
            let _ = cache.insert($name.to_string(), (
                IRIRef::new(IRI::from_str(&format!("{}{}", NAMESPACE, $name)).unwrap()),
                format!("{}:{}", PREFIX, $name),
                )
            );
            )*
            cache
        }

        #[inline]
        #[doc = "Returns the commonly used prefix for this namespace."]
        pub fn default_prefix() -> &'static str { PREFIX }

        #[inline]
        #[doc = "Returns the IRI, as a string, for this namespace."]
        pub fn namespace_str() -> &'static str { NAMESPACE }

        #[inline]
        #[doc = "Returns the IRI for this namespace."]
        pub fn namespace_iri() -> &'static IRIRef { &NS_IRI }

        $(
            nsname!($fn_name, $name);
        )*
    };
}

///
/// This macro *should only* called by the `namespace!` macro. It takes an identifier and a
/// string and produces:
///
/// 1. a function with the same identifier which returns a complete IRI using the
///    value of `NAMESPACE` in the current scope, and
/// 1. a function with the same identifier, but the suffix `_qname` which returns a qualified name
///    using the value of `PREFIX` in the current scope.
///

#[macro_export]
macro_rules! nsname {
    ($fn_name:ident, $name:expr) => {
        #[inline]
        #[doc = "Returns the IRI for this namespace member."]
        pub fn $fn_name() -> &'static IRIRef {
            &NS_CACHE.get($name).unwrap().0
        }

        paste::item! {
            #[inline]
            #[doc = "Returns a qname, using the default prefix, for this namespace member."]
            pub fn [<$fn_name _qname>]() -> &'static String {
                &NS_CACHE.get($name).unwrap().1
            }
        }
    };
}

// ------------------------------------------------------------------------------------------------
// Modules
// ------------------------------------------------------------------------------------------------

pub mod dc;

pub mod foaf;

pub mod geo;

pub mod owl;

pub mod rdf;

pub mod rdfs;

pub mod xsd;

// ------------------------------------------------------------------------------------------------
// Unit Tests
// ------------------------------------------------------------------------------------------------

#[cfg(test)]
mod tests {
    #![allow(unreachable_pub)]

    use super::*;

    namespace!("p", "heep://schema/com/p#", { foo, "Foo", bar, "Bar" } );

    #[test]
    fn test_expansion() {
        assert_eq!(default_prefix(), "p".to_string());

        assert_eq!(namespace_str(), "heep://schema/com/p#");
        assert_eq!(
            namespace_iri(),
            &IRIRef::new(IRI::from_str("heep://schema/com/p#").unwrap())
        );

        assert_eq!(foo().to_string(), "heep://schema/com/p#Foo");
        assert_eq!(foo_qname(), "p:Foo");

        assert_eq!(bar().to_string(), "heep://schema/com/p#Bar");
        assert_eq!(bar_qname(), "p:Bar");
    }
}