<commit_before>use libc::c_void;
use std::ffi::CString;
use std::path::Path;

use merger;
use mtbl_sys;
use reader::{Read, Iter};

/// Options for opening an MTBL fileset.
///
/// # Examples
///
/// ```
/// FilesetOptions::new().reload_interval_seconds(10).open_from_path("/tmp/data-fileset")
/// ```
#[derive(Clone,Copy)]
pub struct FilesetOptions {
    /// How often, in seconds, to reload the fileset description file to look for new file entries.
    /// The mtbl default is 60 seconds.
    pub reload_interval_seconds: Option<u32>,
}

impl FilesetOptions {
    /// Create a `FilesetOptions` with only defaults.
    pub fn new() -> FilesetOptions {
        FilesetOptions { reload_interval_seconds: None }
    }

    /// Create a modified `FilesetOptions` with reload_interval_seconds set.
    pub fn reload_interval_seconds(self: &Self, reload_interval_seconds: u32) -> FilesetOptions {
        FilesetOptions { reload_interval_seconds: Some(reload_interval_seconds), ..*self }
    }

    /// Open a `Fileset` with these options from the specified setfile. Note that you must include
    /// a `MergeFn` to combine colliding entries that have the same key.
    pub fn open_from_path<T: AsRef<Path>>(self: &Self,
                                          setfile: T,
                                          merge_fn: Box<merger::MergeFn>)
                                          -> Fileset {
        let mut merge_fn = Box::new(merge_fn);
        unsafe {
            let mut opts = mtbl_sys::mtbl_fileset_options_init();
            mtbl_sys::mtbl_fileset_options_set_merge_func(
                // Wacky casting to get a void pointer for the C lib.
                opts, merger::_merge_cb_shim, &mut (*merge_fn) as *mut _ as *mut c_void);
            if let Some(reload_interval_seconds) = self.reload_interval_seconds {
                mtbl_sys::mtbl_fileset_options_set_reload_interval(opts, reload_interval_seconds);
            }
            let c_path = CString::new(setfile.as_ref().to_str().unwrap().as_bytes()).unwrap();
            let mtbl_fileset = mtbl_sys::mtbl_fileset_init(c_path.as_ptr(), opts);
            let fileset = Fileset {
                options: *self,
                mtbl_fileset: mtbl_fileset,
                mtbl_source: mtbl_sys::mtbl_fileset_source(mtbl_fileset),
                _merge_fn: merge_fn,
            };
            mtbl_sys::mtbl_fileset_options_destroy(&mut opts);
            fileset
        }
    }
}

/// An MTBL reader that watches a "setfile" containing a list of MTBL files to
/// read from.
///
/// It acts like a [`Merger`](type.Merger.html) that watches that setfile for
/// updates to a list of MTBL files. Note that paths in the setfile are
/// *relative* paths from the directory of the setfile.
///
/// `Fileset`s are not thread-safe because reloading, which happens
/// automatically when reading, is not thread-safe--so only one thread can read
/// from a `Fileset`.
///
/// To create a Fileset with non-default options, see
/// [FilesetOptions](struct.FilesetOptions.html).
///
/// # Examples
///
/// ```
/// $ cp my-data.mtbl /tmp/my-data.mtbl
/// $ echo 'my-data.mtbl' >> /tmp/fs.mtbl-fileset
/// ...<commit_msg>Fix quotes so cargo doc works<commit_after>use libc::c_void;
use std::ffi::CString;
use std::path::Path;

use merger;
use mtbl_sys;
use reader::{Read, Iter};

/// Options for opening an MTBL fileset.
///
/// # Examples
///
/// ```
/// FilesetOptions::new().reload_interval_seconds(10).open_from_path("/tmp/data-fileset")
/// ```
#[derive(Clone,Copy)]
pub struct FilesetOptions {
    /// How often, in seconds, to reload the fileset description file to look for new file entries.
    /// The mtbl default is 60 seconds.
    pub reload_interval_seconds: Option<u32>,
}

impl FilesetOptions {
    /// Create a `FilesetOptions` with only defaults.
    pub fn new() -> FilesetOptions {
        FilesetOptions { reload_interval_seconds: None }
    }

    /// Create a modified `FilesetOptions` with reload_interval_seconds set.
    pub fn reload_interval_seconds(self: &Self, reload_interval_seconds: u32) -> FilesetOptions {
        FilesetOptions { reload_interval_seconds: Some(reload_interval_seconds), ..*self }
    }

    /// Open a `Fileset` with these options from the specified setfile. Note that you must include
    /// a `MergeFn` to combine colliding entries that have the same key.
    pub fn open_from_path<T: AsRef<Path>>(self: &Self,
                                          setfile: T,
                                          merge_fn: Box<merger::MergeFn>)
                                          -> Fileset {
        let mut merge_fn = Box::new(merge_fn);
        unsafe {
            let mut opts = mtbl_sys::mtbl_fileset_options_init();
            mtbl_sys::mtbl_fileset_options_set_merge_func(
                // Wacky casting to get a void pointer for the C lib.
                opts, merger::_merge_cb_shim, &mut (*merge_fn) as *mut _ as *mut c_void);
            if let Some(reload_interval_seconds) = self.reload_interval_seconds {
                mtbl_sys::mtbl_fileset_options_set_reload_interval(opts, reload_interval_seconds);
            }
            let c_path = CString::new(setfile.as_ref().to_str().unwrap().as_bytes()).unwrap();
            let mtbl_fileset = mtbl_sys::mtbl_fileset_init(c_path.as_ptr(), opts);
            let fileset = Fileset {
                options: *self,
                mtbl_fileset: mtbl_fileset,
                mtbl_source: mtbl_sys::mtbl_fileset_source(mtbl_fileset),
                _merge_fn: merge_fn,
            };
            mtbl_sys::mtbl_fileset_options_destroy(&mut opts);
            fileset
        }
    }
}

/// An MTBL reader that watches a "setfile" containing a list of MTBL files to
/// read from.
///
/// It acts like a [`Merger`](type.Merger.html) that watches that setfile for
/// updates to a list of MTBL files. Note that paths in the setfile are
/// *relative* paths from the directory of the setfile.
///
/// `Fileset`s are not thread-safe because reloading, which happens
/// automatically when reading, is not thread-safe--so only one thread can read
/// from a `Fileset`.
///
/// To create a Fileset with non-default options, see
/// [FilesetOptions](struct.FilesetOptions.html).
///
/// # Examples
///
/// ```
/// $ cp my-data.mtbl /tmp/my-data.mtbl
/// $ echo "my-data.mtbl" >> /tmp/fs.mtbl-fileset
/// ...
{'fraction_non_alphanumeric': 0.11983729662077597, 'fraction_numerical': 0.0025031289111389237, 'mean_word_length': 2.3718354430379747, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3461091', 'n_tokens_mistral': 1922, 'n_tokens_neox': 1891, 'n_words': 529}