libpostal_sys/
lib.rs

1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4// This is pretty bad, but we'll just avoid using those APIs, I hope?
5#![allow(improper_ctypes)]
6// Ignore test-only warnings caused by
7// https://github.com/rust-lang/rust-bindgen/issues/1651.
8#![cfg_attr(test, allow(deref_nullptr))]
9
10use std::sync::{Arc, Mutex};
11
12use lazy_static::lazy_static;
13
14/// Which portions of this library have been initialized?
15///
16/// A global copy of this struct is protected by our `GLOBAL_LOCK`.
17#[derive(Debug)]
18#[non_exhaustive]
19pub struct InitializationState {
20    /// Has the main library been initialized?
21    pub initialized: bool,
22
23    /// Have we initialized the address parser?
24    pub parser_initialized: bool,
25
26    /// Have we initialized the language classifier?
27    pub language_classifier_initialized: bool,
28}
29
30lazy_static! {
31    /// You _must_ take this lock before doing _anything_ with this library.
32    /// `libpostal` is [not thread safe][threads].
33    ///
34    /// [threads]: https://github.com/openvenues/libpostal/issues/34
35    pub static ref GLOBAL_LOCK: Arc<Mutex<InitializationState>> = Arc::new(Mutex::new(InitializationState {
36        initialized: false,
37        parser_initialized: false,
38        language_classifier_initialized: false,
39    }));
40}
41
42// We could use build.rs to automatically generate these bindings, then include
43//them like this. include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
44
45// Assume our bindings were generated using:
46//
47//     bindgen wrapper.h -o src/bindings.rs
48//
49// See the README.md file.
50include!("bindings.rs");
51
52#[cfg(test)]
53mod tests {
54    use std::ffi::{CStr, CString};
55
56    use super::*;
57
58    #[test]
59    #[ignore]
60    fn smoke_test() {
61        unsafe {
62            let datadir = CString::new("/usr/local/share/libpostal")
63                .expect("CString::new failed");
64            if !libpostal_setup_datadir(datadir.as_ptr() as *mut _) {
65                panic!("can't set up libpostal");
66            }
67            if !libpostal_setup_parser_datadir(datadir.as_ptr() as *mut _) {
68                panic!("can't set up libpostal parser")
69            }
70            if !libpostal_setup_language_classifier_datadir(datadir.as_ptr() as *mut _)
71            {
72                panic!("can't set up libpostal classifier")
73            }
74
75            // Parse an address and print components.
76            let address = CString::new(
77                "781 Franklin Ave Crown Heights Brooklyn NYC NY 11216 USA",
78            )
79            .expect("CString::new failed");
80            let parse_options = libpostal_get_address_parser_default_options();
81            let parsed =
82                libpostal_parse_address(address.as_ptr() as *mut _, parse_options);
83            for i in 0..(*parsed).num_components {
84                let label = CStr::from_ptr(*(*parsed).labels.offset(i as isize))
85                    .to_str()
86                    .expect("label contained invalid UTF-8");
87                let component =
88                    CStr::from_ptr(*(*parsed).components.offset(i as isize))
89                        .to_str()
90                        .expect("component contained invalid UTF-8");
91                println!("{}={}", label, component);
92            }
93            libpostal_address_parser_response_destroy(parsed);
94
95            // Normalize a (street?) address.
96            let street_address =
97                CString::new("Quatre-vingt-douze Ave des Champs-Élysées")
98                    .expect("CString::new failed");
99            let normalization_options = libpostal_get_default_options();
100            let mut num_expansions: size_t = 0;
101            let expansions = libpostal_expand_address(
102                street_address.as_ptr() as *mut _,
103                normalization_options,
104                &mut num_expansions,
105            );
106            for i in 0..num_expansions {
107                let expansion = CStr::from_ptr(*expansions.offset(i as isize))
108                    .to_str()
109                    .expect("expansion contained invalid UTF-8");
110                println!("expansion {}: {}", i, expansion);
111            }
112            libpostal_expansion_array_destroy(expansions, num_expansions);
113
114            // Clean up the library.
115            libpostal_teardown();
116            libpostal_teardown_parser();
117            libpostal_teardown_language_classifier();
118        }
119    }
120}