ipset 0.9.0

A wrapper for libipset
Documentation
use std::ffi::CStr;

use crate::binding;
use crate::types::Error;

/// Wrapper for ipset instance in c.
pub struct IPSet {
    pub(crate) set: *mut binding::ipset,
    pub(crate) session: *mut binding::ipset_session,
}

impl IPSet {
    /// Create a new IPSet instance.
    pub fn new() -> IPSet {
        unsafe {
            binding::ipset_load_types();
            let set = binding::ipset_init();
            let session = binding::ipset_session(set);
            IPSet { set, session }
        }
    }

    /// get the error message and type.
    pub(crate) fn error(&self) -> (String, binding::ipset_err_type) {
        unsafe {
            let err = binding::ipset_session_report_msg(self.session);
            let err = CStr::from_ptr(err).to_string_lossy().to_string();
            let typ = binding::ipset_session_report_type(self.session);
            binding::ipset_session_report_reset(self.session);
            (err, typ)
        }
    }

    /// Restore a set from a file.
    pub fn restore(&self, filename: String) -> Result<(), Error> {
        unsafe {
            let filename = std::ffi::CString::new(filename).unwrap();
            let ret = binding::ipset_session_io_normal(
                self.session,
                filename.as_ptr(),
                binding::ipset_io_type_IPSET_IO_INPUT,
            );
            if ret < 0 {
                return Err(Error::SaveRestore(self.error().0));
            }

            let file = binding::ipset_session_io_stream(
                self.session,
                binding::ipset_io_type_IPSET_IO_INPUT,
            );
            let ret = binding::ipset_parse_stream(self.set, file);
            if ret < 0 {
                Err(Error::SaveRestore(self.error().0))
            } else {
                Ok(())
            }
        }
    }
}

impl Drop for IPSet {
    fn drop(&mut self) {
        unsafe {
            binding::ipset_fini(self.set);
        }
    }
}