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
//! Rust bindings for [libfprint](https://gitlab.freedesktop.org/libfprint/libfprint)
//!
//! This crate provides a wrapper around the libfprint library, which allows you to use fingerprint scanners in your Rust applications.
//!
//! ## Enrolling a new fingerprint
//! ```rust
//! use libfprint_rs::{FpContext, FpPrint, GError};
//!
//! let context = FpContext::new();
//! let devices = context.get_devices();
//!
//! let dev = devices.iter().next().unwrap();
//! dev.open()?;
//!
//! let template = FpPrint::new(&dev);
//! template.set_username("Bruce Banner");
//!
//! dev.enroll(template, None, None::<()>)?;
//! ```
//! ## Verifying a fingerprint
//! ```rust
//! use libfprint_rs::{FpContext, FpPrint, GError};
//! let context = FpContext::new();
//! let devices = context.get_devices();
//!
//! let dev = devices.iter().next().unwrap();
//! dev.open()?;
//!
//! let enrolled_print = load_print_from_file();
//!
//! dev.verify(enrolled_print, None, None::<()>, None)?;
//! ```
mod context;
mod device;
mod error;
mod finger;
mod image;
mod print;
pub(crate) mod utils;

pub use crate::{
    context::FpContext,
    // import all from device mod
    device::*,
    error::{GError, GErrorSource},
    finger::{Finger, FpFingerStatusFlags},
    image::{FpImage, FpImageData},
    print::{FpPrint, SerializedPrint},
};

#[cfg(test)]
mod tests {

    use std::{cell::RefCell, rc::Rc};

    use crate::{context::FpContext, device::FpDevice, error::GError, print::FpPrint};
    struct UserData {
        _count: u32,
        _name: String,
    }
    fn generate_print<'a>(dev: &'a FpDevice) -> FpPrint<'a> {
        let user_data = UserData {
            _count: 304,
            _name: "Donda".into(),
        };

        let user_data = Rc::new(RefCell::new(user_data));

        let template = FpPrint::new(&dev);
        let print1 = dev
            .enroll(template, Some(callback_fn), Some(user_data.clone()))
            .unwrap();
        println!("{}", user_data.borrow()._count);

        return print1;
    }

    fn callback_fn(
        device: &FpDevice,
        completed_stages: i32,
        _print: FpPrint,
        _error: Option<GError>,
        _user_data: &Option<Rc<RefCell<UserData>>>,
    ) {
        if let Some(user_data) = _user_data {
            user_data.borrow_mut()._count += 1;
            // Mutate the user data
        }
        println!(
            "Enrolling: {} of {}",
            completed_stages,
            device.get_nr_enroll_stages()
        );
    }

    fn match_cb_function(
        _device: &FpDevice,                         // The fingerprint scanner device
        matched_print: Option<FpPrint>,             // The matched print, if any.
        _new_print: FpPrint,                        // New print scanned.
        _error: Option<GError>,                     // Optinal error in case of an error.
        match_data: &Option<Rc<RefCell<UserData>>>, // User data can be any data type.
    ) {
        if let Some(user_data) = match_data {
            user_data.borrow_mut()._count += 1;
            user_data.borrow_mut()._name = "Kanye".into();
        }
        if matched_print.is_some() {
            println!("Found matched print!");
        }
    }
    #[test]
    fn ident_test() {
        let ctx = FpContext::new();
        let dev = match ctx.get_devices().iter().next() {
            Some(dev) => dev,
            None => {
                return;
            }
        }; // Throws errors if no device is connected
        let f = dev.get_features();
        println!("{:?}", f);

        dev.open().unwrap(); // Open the device

        let prints = vec![generate_print(&dev), generate_print(&dev)];

        let mut matched_print = FpPrint::new(&dev);
        matched_print.set_username("Some username should be here");
        let mut new_print = FpPrint::new(&dev);

        dev.identify(
            prints,
            Some(match_cb_function),
            None,
            Some(&mut matched_print),
            Some(&mut new_print),
        )
        .unwrap();
    }
}