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
use std::ffi::CStr;
use std::fmt;
use std::mem;
use std::str;

use libusb::*;

/// A structure that describes the version of the underlying `libusb` library.
pub struct LibraryVersion {
    inner: &'static libusb_version,
}

impl LibraryVersion {
    /// Library major version.
    pub fn major(&self) -> u16 {
        self.inner.major
    }

    /// Library minor version.
    pub fn minor(&self) -> u16 {
        self.inner.minor
    }

    /// Library micro version.
    pub fn micro(&self) -> u16 {
        self.inner.micro
    }

    /// Library nano version.
    pub fn nano(&self) -> u16 {
        self.inner.nano
    }

    /// Library release candidate suffix string, e.g., `"-rc4"`.
    pub fn rc(&self) -> Option<&'static str> {
        let cstr = unsafe { CStr::from_ptr(self.inner.rc) };

        match str::from_utf8(cstr.to_bytes()) {
            Ok(s) => {
                if s.len() > 0 {
                    Some(s)
                }
                else {
                    None
                }
            },
            Err(_) => {
                None
            },
        }
    }
}

impl fmt::Debug for LibraryVersion {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let mut debug = fmt.debug_struct("LibraryVersion");

        debug.field("major", &self.major());
        debug.field("minor", &self.minor());
        debug.field("micro", &self.micro());
        debug.field("nano", &self.nano());
        debug.field("rc", &self.rc());

        debug.finish()
    }
}

/// Returns a structure with the version of the running libusb library.
pub fn version() -> LibraryVersion {
    let version: &'static libusb_version = unsafe {
        mem::transmute(libusb_get_version())
    };

    LibraryVersion { inner: version }
}