<commit_before>extern crate winapi;
extern crate kernel32;

use util::{CowCString, CStringAsRef};

use std::ffi::{OsStr, OsString};
use std::{fmt, io, marker, mem, ptr};
use std::os::windows::ffi::{OsStrExt, OsStringExt};
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};

/// A platform-specific equivalent of the cross-platform `Library`.
pub struct Library(winapi::HMODULE);

unsafe impl ::std::marker::Send for Library {}
// This probably could implement Sync. At least I found no reason not to so far.

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Corresponds to `LoadLibraryW(filename)`.
    #[inline]
    pub fn new<P: AsRef<OsStr>>(filename: P) -> ::Result<Library> {
        let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
        let _guard = ErrorModeGuard::new();

        let ret = with_get_last_error(|| {
            // Make sure no winapi calls as a result of drop happen inside this closure, because
            // otherwise that might change the return value of the GetLastError.
            let handle = unsafe { kernel32::LoadLibraryW(wide_filename.as_ptr()) };
            if handle.is_null()  {
                None
            } else {
                Some(Library(handle))
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("LoadLibraryW failed but GetLastError did not report the error")
        ));

        drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
                             // inside the closure by mistake. See comment inside the closure.
        ret
    }

    /// Get a pointer to function or static variable by symbol name.
    ///
    /// The `symbol` may not contain any null bytes, with an exception of last byte. A null
    /// terminated `symbol` may avoid a string allocation in some cases.
    ///
    /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
    /// most likely invalid.
    ///
    /// ## Unsafety
    ///
    /// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
    /// undefined.
    pub unsafe fn get<T>(&self, symbol: &[u8]) -> ::Result<Symbol<T>> {
        let symbol = try!(CowCString::from_bytes(symbol));
        with_get_last_error(|| {
            let symbol = kernel32::GetProcAddress(self.0, symbol.cstring_ref());
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("GetProcAddress failed but GetLastError did not report the error")
        ))
    }

    /// Get a pointer to function or static variable by ordinal number.
    pub unsafe fn get_ordinal<T>(&self, ordinal: winapi::WORD) -> ::Result<Symbol<T>> {
        with_get_last_error(|| {
            let ordinal = ordinal as usize as *mut _;
            let symbol = kernel32::GetProcAddress(self.0, ordinal);
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("GetProcAddress failed but GetLastError did not report the error")
        ))
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        with_get_last_error(|| {
            if unsafe { kernel32::FreeLibrary(self.0) == 0 } {
                None
            } else {
                Some(())
            }
        }).unwrap()
    }
}

impl fmt::Debug for Library {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        unsafe {
            let mut buf: [winapi::WCHAR; 1024] = mem::uninitialized();
            let len = kernel32::GetModuleFileNameW(self.0,
                                                   (&mut buf[..]).as_mut_ptr(), 1024) as usize;
            if len == 0 {
                f.write_str(&format!("Library@{:p}", self.0))
            } else {
                let string: OsString = OsString::from_wide(&buf[..len]);
                f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
            }
        }
    }
}

/// Symbol from a library.
///
/// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
/// `Symbol` does not outlive `Library` it comes from.
#[derive(Clone)]
pub struct Symbol<T> {
    pointer: winapi::FARPROC,
    pd: marker::PhantomData<T>
}

impl<T> ::std::ops::Deref for Symbol<T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe {
            // Additional reference level for a dereference on `deref` return value.
            mem::transmute(&self.pointer)
        }
    }
}

impl<T> fmt::Debug for Symbol<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&format!("Symbol@{:p}", self.pointer))
    }
}

static USE_ERRORMODE: AtomicBool = ATOMIC_BOOL_INIT;
struct ErrorModeGuard(winapi::DWORD);

impl ErrorModeGuard {
    fn new() -> ErrorModeGuard {
        let mut ret = ErrorModeGuard(0);

        if !USE_ERRORMODE.load(Ordering::Acquire) {
            if unsafe { kernel32::SetThreadErrorMode(1, &mut ret.0) == 0
                        && kernel32::GetLastError() == winapi::ERROR_CALL_NOT_IMPLEMENTED } {
                USE_ERRORMODE.store(true, Ordering::Release);
            } else {
                return ret;
            }
        }
        ret.0 = unsafe { kernel32::SetErrorMode(1) };
        ret
    }
}

impl Drop for ErrorModeGuard {
    fn drop(&mut self) {
        unsafe {
            if !USE_ERRORMODE.load(Ordering::Relaxed) {
                kernel32::SetThreadErrorMode(self.0, ptr::null_mut());
            } else {
                kernel32::SetErrorMode(self.0);
            }
        }
    }
}

fn with_get_last_error<T, F>(closure: F) -> Result<T, Option<io::Error>>
where F: FnOnce() -> Option<T> {
    closure().ok_or_else(|| {
        let error = unsafe { kernel32::GetLastError() };
        if error == 0 {
            None
        } else {
            Some(io::Error::from_raw_os_error(error as i32))
        }
    })
}

#[test]
fn works_getlasterror() {
    let lib = Library::new("kernel32.dll").unwrap();
    let gle: Symbol<unsafe extern "system" fn() -> winapi::DWORD> = unsafe {
        lib.get(b"GetLastError").unwrap()
    };
    unsafe {
        kernel32::SetLastError(42);
        assert_eq!(kernel32::GetLastError(), gle())
    }
}

#[test]
fn works_getlasterror0() {
    let lib = Library::new("kernel32.dll").unwrap();
    let gle: Symbol<unsafe extern "system" fn() -> winapi::DWORD> = unsafe {
        lib.get(b"GetLastError\0").unwrap()
    };
    unsafe {
        kernel32::SetLastError(42);
        assert_eq!(kernel32::GetLastError(), gle())
    }
}
<commit_msg>Improve os::windows::Library::get_ordinal docs in a minor way<commit_after>extern crate winapi;
extern crate kernel32;

use util::{CowCString, CStringAsRef};

use std::ffi::{OsStr, OsString};
use std::{fmt, io, marker, mem, ptr};
use std::os::windows::ffi::{OsStrExt, OsStringExt};
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};

/// A platform-specific equivalent of the cross-platform `Library`.
pub struct Library(winapi::HMODULE);

unsafe impl ::std::marker::Send for Library {}
// This probably could implement Sync. At least I found no reason not to so far.

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Corresponds to `LoadLibraryW(filename)`.
    #[inline]
    pub fn new<P: AsRef<OsStr>>(filename: P) -> ::Result<Library> {
        let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
        let _guard = ErrorModeGuard::new();

        let ret = with_get_last_error(|| {
            // Make sure no winapi calls as a result of drop happen inside this closure, because
            // otherwise that might change the return value of the GetLastError.
            let handle = unsafe { kernel32::LoadLibraryW(wide_filename.as_ptr()) };
            if handle.is_null()  {
                None
            } else {
                Some(Library(handle))
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("LoadLibraryW failed but GetLastError did not report the error")
        ));

        drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
                             // inside the closure by mistake. See comment inside the closure.
        ret
    }

    /// Get a pointer to function or static variable by symbol name.
    ///
    /// The `symbol` may not contain any null bytes, with an exception of last byte. A null
    /// terminated `symbol` may avoid a string allocation in some cases.
    ///
    /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
    /// most likely invalid.
    ///
    /// ## Unsafety
    ///
    /// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
    /// undefined.
    pub unsafe fn get<T>(&self, symbol: &[u8]) -> ::Result<Symbol<T>> {
        let symbol = try!(CowCString::from_bytes(symbol));
        with_get_last_error(|| {
            let symbol = kernel32::GetProcAddress(self.0, symbol.cstring_ref());
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("GetProcAddress failed but GetLastError did not report the error")
        ))
    }

    /// Get a pointer to function or static variable by ordinal number.
    ///
    /// ## Unsafety
    ///
    /// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
    /// undefined.
    pub unsafe fn get_ordinal<T>(&self, ordinal: winapi::WORD) -> ::Result<Symbol<T>> {
        with_get_last_error(|| {
            let ordinal = ordinal as usize as *mut _;
            let symbol = kernel32::GetProcAddress(self.0, ordinal);
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("GetProcAddress failed but GetLastError did not report the error")
        ))
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        with_get_last_error(|| {
            if unsafe { kernel32::FreeLibrary(self.0) == 0 } {
                None
            } else {
                Some(())
            }
        }).unwrap()
    }
}

impl fmt::Debug for Library {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        unsafe {
            let mut buf: [winapi::WCHAR; 1024] = mem::uninitialized();
            let len = kernel32::GetModuleFileNameW(self.0,
                                                   (&mut buf[..]).as_mut_ptr(), 1024) as usize;
            if len == 0 {
                f.write_str(&format!("Library@{:p}", self.0))
            } else {
                let string: OsString = OsString::from_wide(&buf[..len]);
                f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
            }
        }
    }
}

/// Symbol from a library.
///
/// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
/// `Symbol` does not outlive `Library` it comes from.
#[derive(Clone)]
pub struct Symbol<T> {
    pointer: winapi::FARPROC,
    pd: marker::PhantomData<T>
}

impl<T> ::std::ops::Deref for Symbol<T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe {
            // Additional reference level for a dereference on `deref` return value.
            mem::transmute(&self.pointer)
        }
    }
}

impl<T> fmt::Debug for Symbol<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&format!("Symbol@{:p}", self.pointer))
    }
}

static USE_ERRORMODE: AtomicBool = ATOMIC_BOOL_INIT;
struct ErrorModeGuard(winapi::DWORD);

impl ErrorModeGuard {
    fn new() -> ErrorModeGuard {
        let mut ret = ErrorModeGuard(0);

        if !USE_ERRORMODE.load(Ordering::Acquire) {
            if unsafe { kernel32::SetThreadErrorMode(1, &mut ret.0) == 0
                        && kernel32::GetLastError() == winapi::ERROR_CALL_NOT_IMPLEMENTED } {
                USE_ERRORMODE.store(true, Ordering::Release);
            } else {
                return ret;
            }
        }
        ret.0 = unsafe { kernel32::SetErrorMode(1) };
        ret
    }
}

impl Drop for ErrorModeGuard {
    fn drop(&mut self) {
        unsafe {
            if !USE_ERRORMODE.load(Ordering::Relaxed) {
                kernel32::SetThreadErrorMode(self.0, ptr::null_mut());
            } else {
                kernel32::SetErrorMode(self.0);
            }
        }
    }
}

fn with_get_last_error<T, F>(closure: F) -> Result<T, Option<io::Error>>
where F: FnOnce() -> Option<T> {
    closure().ok_or_else(|| {
        let error = unsafe { kernel32::GetLastError() };
        if error == 0 {
            None
        } else {
            Some(io::Error::from_raw_os_error(error as i32))
        }
    })
}

#[test]
fn works_getlasterror() {
    let lib = Library::new("kernel32.dll").unwrap();
    let gle: Symbol<unsafe extern "system" fn() -> winapi::DWORD> = unsafe {
        lib.get(b"GetLastError").unwrap()
    };
    unsafe {
        kernel32::SetLastError(42);
        assert_eq!(kernel32::GetLastError(), gle())
    }
}

#[test]
fn works_getlasterror0() {
    let lib = Library::new("kernel32.dll").unwrap();
    let gle: Symbol<unsafe extern "system" fn() -> winapi::DWORD> = unsafe {
        lib.get(b"GetLastError\0").unwrap()
    };
    unsafe {
        kernel32::SetLastError(42);
        assert_eq!(kernel32::GetLastError(), gle())
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate rusqlite;
#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;
extern crate rustc_serialize;
extern crate serde_yaml;
extern crate uuid;

mod loader;
mod db;
mod db_fs_dir_type;
mod db_fs_dir;
mod db_fs_file;
mod db_provider;
mod db_job;
mod db_job_provide;
mod db_job_depend;
mod db_variable_name;
mod db_job_require_variable;
mod db_variable_pair;
mod db_job_require_variable_pair;
mod json_loader_elephant;
mod cli_clap;
mod jobs_load;
mod elephant;
mod db_session;
mod db_enviroment;
mod autoconf;
mod clap_actions;
mod actions_process;
mod actions_process_list_provides;
mod clap_fern;

use uuid::Uuid;

fn main() {
    let some_value = 10;
    let clap_matches = cli_clap::cli_clap(&some_value);
    let actions = clap_actions::actions_get(&clap_matches);
    clap_fern::log_setup(&clap_matches);
    let session_uuid = Uuid::new_v4();
    let session_uuid_string = session_uuid.hyphenated().to_string();
    trace!("session_uuid_string:{}", session_uuid_string);
    let conn = db::connect_deligate(&clap_matches);
    db::create_tables(&conn);
    loader::deligate(&conn, &actions, &clap_matches);
    let pk_session = elephant::elephant_session(&conn, &session_uuid_string);
    loader::enviroment(&conn, pk_session, &clap_matches);
    jobs_load::load(&conn);
    actions_process::process(&conn, &actions)
}
<commit_msg>Apply rustfmt to main.rs<commit_after>extern crate clap;
extern crate rusqlite;
#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;
extern crate rustc_serialize;
extern crate serde_yaml;
extern crate uuid;

mod actions_process;
mod actions_process_list_provides;
mod autoconf;
mod clap_actions;
mod clap_fern;
mod cli_clap;
mod db;
mod db_enviroment;
mod db_fs_dir;
mod db_fs_dir_type;
mod db_fs_file;
mod db_job;
mod db_job_depend;
mod db_job_provide;
mod db_job_require_variable;
mod db_job_require_variable_pair;
mod db_provider;
mod db_session;
mod db_variable_name;
mod db_variable_pair;
mod elephant;
mod jobs_load;
mod json_loader_elephant;
mod loader;
use uuid::Uuid;

fn main() {
    let some_value = 10;
    let clap_matches = cli_clap::cli_clap(&some_value);
    let actions = clap_actions::actions_get(&clap_matches);
    clap_fern::log_setup(&clap_matches);
    let session_uuid = Uuid::new_v4();
    let session_uuid_string = session_uuid.hyphenated().to_string();
    trace!("session_uuid_string:{}", session_uuid_string);
    let conn = db::connect_deligate(&clap_matches);
    db::create_tables(&conn);
    loader::deligate(&conn, &actions, &clap_matches);
    let pk_session = elephant::elephant_session(&conn, &session_uuid_string);
    loader::enviroment(&conn, pk_session, &clap_matches);
    jobs_load::load(&conn);
    actions_process::process(&conn, &actions)
}
<|endoftext|>


<commit_before>//! Scan positions and their consituant parts.

use {CameraCalibration, Error, MountCalibration, Project, Result};
use nalgebra::Projective3;
use std::collections::HashMap;
use std::path::{Path, PathBuf};

/// A scan position
#[derive(Clone, Debug, Serialize, PartialEq)]
pub struct ScanPosition {
    /// The name of the scan position.
    pub name: String,
    /// The scan position images.
    pub images: HashMap<String, Image>,
    /// The scanner's own position.
    pub sop: Projective3<f64>,
    /// The scans taken at this position.
    pub scans: HashMap<String, Scan>,
}

/// A scan.
#[derive(Clone, Debug, Serialize, PartialEq)]
pub struct Scan {
    /// The name of the scan.
    pub name: String,
    /// The file name of the scan.
    pub file: String,
    /// The number of measurements in the phi direction.
    pub phi_count: usize,
    /// The number of measurements in the theta direction.
    pub theta_count: usize,
}

/// A scan position image.
#[derive(Clone, Debug, Serialize, PartialEq)]
pub struct Image {
    /// The name of the image.
    pub name: String,
    /// The camera's own position when taking the image.
    pub cop: Projective3<f64>,
    /// The name of the image's camera calibration.
    pub camera_calibration_name: String,
    /// The name of the image's mount calibration.
    pub mount_calibration_name: String,
}

impl ScanPosition {
    /// Returns a scan position image, as determined by the path.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Project;
    /// let project = Project::from_path("data/project.RiSCAN").unwrap();
    /// let scan_position = project.scan_positions.get("SP01").unwrap();
    /// let image1 = scan_position.images.get("SP01 - Image001").unwrap();
    /// let path = "data/project.RiSCAN/SCANS/SP01/SCANPOSIMAGES/SP01 - Image001.csv";
    /// let image2 = scan_position.image_from_path(path).unwrap();
    /// assert_eq!(image1, image2);
    /// ```
    pub fn image_from_path<P: AsRef<Path>>(&self, path: P) -> Result<&Image> {
        use Error;
        path.as_ref()
            .file_stem()
            .map(|file_stem| file_stem.to_string_lossy())
            .and_then(|file_stem| self.images.get(file_stem.as_ref()))
            .ok_or_else(|| Error::ImageFromPath(path.as_ref().to_path_buf()))
    }

    /// Returns a vector of all paths to rxps in the singlescan directory.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Project;
    /// let project = Project::from_path("data/project.RiSCAN").unwrap();
    /// let scan_position = project
    ///     .scan_positions
    ///     .get("SP01")
    ///     .unwrap();
    /// let paths = scan_position.singlescan_rxp_paths(&project);
    /// assert_eq!(4, paths.len());
    /// ```
    pub fn singlescan_rxp_paths(&self, project: &Project) -> Vec<PathBuf> {
        let mut path = project
            .path
            .parent()
            .expect("Project path should always have a parent")
            .to_path_buf();
        path.push("SCANS");
        path.push(&self.name);
        path.push("SINGLESCANS");
        self.scans
            .values()
            .map(|scan| {
                let mut path = path.clone();
                path.push(&scan.file);
                path
            })
            .collect()
    }
}

impl Image {
    /// Finds and returns this image's camera calibration.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Project;
    /// let project = Project::from_path("data/project.RiSCAN").unwrap();
    /// let mut image = project.scan_positions
    ///     .get("SP01")
    ///     .unwrap()
    ///     .images
    ///     .get("SP01 - Image001")
    ///     .unwrap()
    ///     .clone();
    /// image.camera_calibration(&project).unwrap();
    /// image.camera_calibration_name = "Not a camera calibration".to_string();
    /// assert!(image.camera_calibration(&project).is_err());
    /// ```
    pub fn camera_calibration<'a>(&self, project: &'a Project) -> Result<&'a CameraCalibration> {
        project
            .camera_calibrations
            .get(&self.camera_calibration_name)
            .ok_or_else(|| {
                Error::MissingCameraCalibration(self.camera_calibration_name.clone())
            })
    }

    /// Finds and returns this image's mount calibration.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Project;
    /// let project = Project::from_path("data/project.RiSCAN").unwrap();
    /// let mut image = project.scan_positions
    ///     .get("SP01")
    ///     .unwrap()
    ///     .images
    ///     .get("SP01 - Image001")
    ///     .unwrap()
    ///     .clone();
    /// image.mount_calibration(&project).unwrap();
    /// image.mount_calibration_name = "Not a mount calibration".to_string();
    /// assert!(image.mount_calibration(&project).is_err());
    /// ```
    pub fn mount_calibration<'a>(&self, project: &'a Project) -> Result<&'a MountCalibration> {
        project
            .mount_calibrations
            .get(&self.mount_calibration_name)
            .ok_or_else(|| {
                Error::MissingMountCalibration(self.mount_calibration_name.clone())
            })
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn scan_position_singlescan_rxp_paths() {
        let project = Project::from_path("data/project.RiSCAN").unwrap();
        let scan_position = project.scan_positions.get("SP01").unwrap();
        let paths = scan_position.singlescan_rxp_paths(&project);
        assert_eq!(4, paths.len());
    }
}
<commit_msg>Add images method to scan position<commit_after>//! Scan positions and their consituant parts.

use {CameraCalibration, Error, MountCalibration, Project, Result};
use nalgebra::Projective3;
use std::collections::HashMap;
use std::path::{Path, PathBuf};

/// A scan position
#[derive(Clone, Debug, Serialize, PartialEq)]
pub struct ScanPosition {
    /// The name of the scan position.
    pub name: String,
    /// The scan position images.
    pub images: HashMap<String, Image>,
    /// The scanner's own position.
    pub sop: Projective3<f64>,
    /// The scans taken at this position.
    pub scans: HashMap<String, Scan>,
}

/// A scan.
#[derive(Clone, Debug, Serialize, PartialEq)]
pub struct Scan {
    /// The name of the scan.
    pub name: String,
    /// The file name of the scan.
    pub file: String,
    /// The number of measurements in the phi direction.
    pub phi_count: usize,
    /// The number of measurements in the theta direction.
    pub theta_count: usize,
}

/// A scan position image.
#[derive(Clone, Debug, Serialize, PartialEq)]
pub struct Image {
    /// The name of the image.
    pub name: String,
    /// The camera's own position when taking the image.
    pub cop: Projective3<f64>,
    /// The name of the image's camera calibration.
    pub camera_calibration_name: String,
    /// The name of the image's mount calibration.
    pub mount_calibration_name: String,
}

impl ScanPosition {
    /// Returns a scan position image, as determined by the path.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Project;
    /// let project = Project::from_path("data/project.RiSCAN").unwrap();
    /// let scan_position = project.scan_positions.get("SP01").unwrap();
    /// let image1 = scan_position.images.get("SP01 - Image001").unwrap();
    /// let path = "data/project.RiSCAN/SCANS/SP01/SCANPOSIMAGES/SP01 - Image001.csv";
    /// let image2 = scan_position.image_from_path(path).unwrap();
    /// assert_eq!(image1, image2);
    /// ```
    pub fn image_from_path<P: AsRef<Path>>(&self, path: P) -> Result<&Image> {
        use Error;
        path.as_ref()
            .file_stem()
            .map(|file_stem| file_stem.to_string_lossy())
            .and_then(|file_stem| self.images.get(file_stem.as_ref()))
            .ok_or_else(|| Error::ImageFromPath(path.as_ref().to_path_buf()))
    }

    /// Returns a vector of all paths to rxps in the singlescan directory.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Project;
    /// let project = Project::from_path("data/project.RiSCAN").unwrap();
    /// let scan_position = project
    ///     .scan_positions
    ///     .get("SP01")
    ///     .unwrap();
    /// let paths = scan_position.singlescan_rxp_paths(&project);
    /// assert_eq!(4, paths.len());
    /// ```
    pub fn singlescan_rxp_paths(&self, project: &Project) -> Vec<PathBuf> {
        let mut path = project
            .path
            .parent()
            .expect("Project path should always have a parent")
            .to_path_buf();
        path.push("SCANS");
        path.push(&self.name);
        path.push("SINGLESCANS");
        self.scans
            .values()
            .map(|scan| {
                let mut path = path.clone();
                path.push(&scan.file);
                path
            })
            .collect()
    }

    /// Returns a vector of all of the images.
    ///
    /// The vector is sorted by name.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Project;
    /// let project = Project::from_path("data/project.RiSCAN").unwrap();
    /// let scan_position = &project.scan_positions["SP01"];
    /// let images = scan_position.images();
    /// assert_eq!(6, images.len());
    /// ```
    pub fn images(&self) -> Vec<&Image> {
        let mut images: Vec<_> = self.images.values().collect();
        images.sort_by_key(|i| &i.name);
        images
    }
}

impl Image {
    /// Finds and returns this image's camera calibration.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Project;
    /// let project = Project::from_path("data/project.RiSCAN").unwrap();
    /// let mut image = project.scan_positions
    ///     .get("SP01")
    ///     .unwrap()
    ///     .images
    ///     .get("SP01 - Image001")
    ///     .unwrap()
    ///     .clone();
    /// image.camera_calibration(&project).unwrap();
    /// image.camera_calibration_name = "Not a camera calibration".to_string();
    /// assert!(image.camera_calibration(&project).is_err());
    /// ```
    pub fn camera_calibration<'a>(&self, project: &'a Project) -> Result<&'a CameraCalibration> {
        project
            .camera_calibrations
            .get(&self.camera_calibration_name)
            .ok_or_else(|| {
                Error::MissingCameraCalibration(self.camera_calibration_name.clone())
            })
    }

    /// Finds and returns this image's mount calibration.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Project;
    /// let project = Project::from_path("data/project.RiSCAN").unwrap();
    /// let mut image = project.scan_positions
    ///     .get("SP01")
    ///     .unwrap()
    ///     .images
    ///     .get("SP01 - Image001")
    ///     .unwrap()
    ///     .clone();
    /// image.mount_calibration(&project).unwrap();
    /// image.mount_calibration_name = "Not a mount calibration".to_string();
    /// assert!(image.mount_calibration(&project).is_err());
    /// ```
    pub fn mount_calibration<'a>(&self, project: &'a Project) -> Result<&'a MountCalibration> {
        project
            .mount_calibrations
            .get(&self.mount_calibration_name)
            .ok_or_else(|| {
                Error::MissingMountCalibration(self.mount_calibration_name.clone())
            })
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn scan_position_singlescan_rxp_paths() {
        let project = Project::from_path("data/project.RiSCAN").unwrap();
        let scan_position = project.scan_positions.get("SP01").unwrap();
        let paths = scan_position.singlescan_rxp_paths(&project);
        assert_eq!(4, paths.len());
    }
}
<|endoftext|>


<commit_before>use base64;
use serde::de::DeserializeOwned;
use serde::ser::Serialize;
use serde_json::{from_str, to_string, Value};
use serde_json::map::Map;

use errors::{Result};
use header::Header;

/// The return type of a successful call to decode
#[derive(Debug)]
pub struct TokenData<T: DeserializeOwned> {
    pub header: Header,
    pub claims: T
}

/// Serializes to JSON and encodes to base64
pub fn to_jwt_part<T: Serialize>(input: &T) -> Result<String> {
    let encoded = to_string(input)?;
    Ok(base64::encode_config(encoded.as_bytes(), base64::URL_SAFE_NO_PAD))
}

/// Decodes from base64 and deserializes from JSON to a struct
pub fn from_jwt_part<B: AsRef<str>, T: DeserializeOwned>(encoded: B) -> Result<T> {
    let decoded = base64::decode_config(encoded.as_ref(), base64::URL_SAFE_NO_PAD)?;
    let s = String::from_utf8(decoded)?;

    Ok(from_str(&s)?)
}

/// Decodes from base64 and deserializes from JSON to a struct AND a hashmap
pub fn from_jwt_part_claims<B: AsRef<str>, T: DeserializeOwned>(encoded: B) -> Result<(T, Map<String, Value>)> {
    let decoded = base64::decode_config(encoded.as_ref(), base64::URL_SAFE_NO_PAD)?;
    let s = String::from_utf8(decoded)?;

    let claims: T = from_str(&s)?;
    let map: Map<_,_> = from_str(&s)?;
    Ok((claims, map))
}
<commit_msg>Remove trait from `TokenData` struct<commit_after>use base64;
use serde::de::DeserializeOwned;
use serde::ser::Serialize;
use serde_json::{from_str, to_string, Value};
use serde_json::map::Map;

use errors::{Result};
use header::Header;

/// The return type of a successful call to decode
#[derive(Debug)]
pub struct TokenData<T> {
    pub header: Header,
    pub claims: T
}

/// Serializes to JSON and encodes to base64
pub fn to_jwt_part<T: Serialize>(input: &T) -> Result<String> {
    let encoded = to_string(input)?;
    Ok(base64::encode_config(encoded.as_bytes(), base64::URL_SAFE_NO_PAD))
}

/// Decodes from base64 and deserializes from JSON to a struct
pub fn from_jwt_part<B: AsRef<str>, T: DeserializeOwned>(encoded: B) -> Result<T> {
    let decoded = base64::decode_config(encoded.as_ref(), base64::URL_SAFE_NO_PAD)?;
    let s = String::from_utf8(decoded)?;

    Ok(from_str(&s)?)
}

/// Decodes from base64 and deserializes from JSON to a struct AND a hashmap
pub fn from_jwt_part_claims<B: AsRef<str>, T: DeserializeOwned>(encoded: B) -> Result<(T, Map<String, Value>)> {
    let decoded = base64::decode_config(encoded.as_ref(), base64::URL_SAFE_NO_PAD)?;
    let s = String::from_utf8(decoded)?;

    let claims: T = from_str(&s)?;
    let map: Map<_,_> = from_str(&s)?;
    Ok((claims, map))
}
<|endoftext|>


<commit_before>#[cfg(feature = "trace_log")]
extern crate env_logger;

extern crate radeco_lib;
extern crate r2pipe;
extern crate r2api;
extern crate base64;
extern crate rustyline;

use r2pipe::{R2, R2Pipe};
use radeco_lib::analysis::cse::cse::CSE;
use radeco_lib::analysis::interproc::fixcall::CallFixer;
use radeco_lib::analysis::sccp;
use radeco_lib::backend::lang_c::c_cfg::CCFGVerifier;
use radeco_lib::backend::lang_c::c_cfg::ctrl_flow_struct;
use radeco_lib::backend::lang_c::c_cfg_builder;
use radeco_lib::frontend::radeco_containers::*;
use radeco_lib::middle::{dce, dot};
use radeco_lib::middle::ir_writer;
use radeco_lib::middle::regfile::SubRegisterFile;
use radeco_lib::middle::ssa::ssastorage::SSAStorage;
use radeco_lib::middle::ssa::verifier;
use rustyline::Editor;

use rustyline::error::ReadlineError;
use std::cell::RefCell;

use std::collections::HashMap;
use std::process;
use std::rc::Rc;
use std::str;
use std::sync::Arc;

// On unix platforms you can use ANSI escape sequences
#[cfg(unix)]
const PROMPT: &'static str = "\x1b[1;32m>>\x1b[0m ";

// Windows consoles typically don't support ANSI escape sequences out
// of the box
#[cfg(windows)]
const PROMPT: &'static str = ">> ";

fn main() {
    let mut rl = Editor::<()>::new();
    let mut proj = None;
    loop {
        let readline = rl.readline(PROMPT);
        match readline {
            Ok(line) => {
                let mut terms = line.split_whitespace();
                let o1 = terms.next();
                let o2 = terms.next();
                cmd(o1, o2, &mut proj);
            }
            Err(ReadlineError::Interrupted) |
            Err(ReadlineError::Eof) => break,
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }
        }
    }
}

mod command {
    pub const LOAD: &'static str = "load";
    pub const CONNECT: &'static str = "connect";
    pub const FNLIST: &'static str = "fn_list";
    pub const ANALYZE: &'static str = "analyze";
    pub const DOT: &'static str = "dot";
    pub const IR: &'static str = "ir";
    pub const DECOMPILE: &'static str = "decompile";
}

fn cmd(op1: Option<&str>, op2: Option<&str>, proj_opt: &mut Option<RadecoProject>) {
    match (op1, op2) {
        (Some(command::LOAD), Some(path)) => {
            *proj_opt = Some(load_proj_by_path(path));
            return;
        }
        (Some(command::CONNECT), Some(url)) => {
            let p_opt = if url.starts_with("http://") {
                load_proj_http(&url[7..])
            } else {
                load_proj_tcp(&url[6..])
            };
            match p_opt {
                Ok(proj) => *proj_opt = Some(proj),
                Err(msg) => println!("{}", msg),
            }
            return;
        }
        _ => {}
    };
    let mut proj = match proj_opt {
        Some(proj) => proj,
        None => {
            println!("Load a project first");
            return;
        }
    };
    match (op1, op2) {
        (Some(command::ANALYZE), Some("*")) => {
            let rfns = proj.iter_mut().map(|i| i.module).flat_map(|rmod| {
                rmod.functions.values_mut()
            });
            for rfn in rfns {
                analyze(rfn);
            }
        }
        (Some(command::FNLIST), _) => {
            let funcs = fn_list(&proj);
            println!("{}", funcs.join("\n"));
        }
        // TODO Show list of dependency information of analyses
        // TODO Add command for individual analyses
        (Some(command::ANALYZE), Some(f)) => {
            if let Some(rfn) = get_function_mut(f, &mut proj) {
                analyze(rfn);
            } else {
                println!("{} is not found", f);
            }
        }
        (Some(command::DOT), Some(f)) => {
            if let Some(rfn) = get_function(f, &proj) {
                println!("{}", emit_dot(rfn.ssa()));
            } else {
                println!("{} is not found", f);
            }
        }
        (Some(command::IR), Some(f)) => {
            if let Some(rfn) = get_function(f, &proj) {
                println!("{}", emit_ir(rfn));
            } else {
                println!("{} is not found", f);
            }
        }
        (Some(command::DECOMPILE), Some(f)) => {
            if let Some(rfn) = get_function(f, &proj) {
                let rmod = proj.iter().map(|i| i.module).next().unwrap();
                let func_name_map = rmod.functions
                    .iter()
                    .map(|(&addr, f)| (addr, f.name.to_string()))
                    .collect();
                let strings = rmod.strings()
                    .iter()
                    .filter(|ref s| s.vaddr.is_some() && s.string.is_some())
                    .cloned()
                    .map(|s| {
                        let (addr, _s) = (s.vaddr.unwrap(), s.string.unwrap());
                        let bytes = base64::decode(&_s).unwrap_or(Vec::new());
                        let ret_string = match str::from_utf8(bytes.as_slice()) {
                            Ok(v) => v.to_string(),
                            Err(_e) => _s,
                        };
                        (addr, ret_string)
                    })
                    .collect();
                println!("{}", decompile(rfn, &func_name_map, &strings));
            } else {
                println!("{} is not found", f);
            }
        }
        _ => {}
    }
}

fn load_proj_by_path(path: &str) -> RadecoProject {
    let mut p = ProjectLoader::new().path(path).load();
    let regfile = p.regfile().clone();
    for mut xy in p.iter_mut() {
        analyze_mod(regfile.clone(), xy.module);
    }
    p
}

fn load_proj_tcp(url: &str) -> Result<RadecoProject, &'static str> {
    let r2p = R2Pipe::tcp(url)?;
    Ok(load_project_by_r2pipe(r2p))
}

fn load_proj_http(url: &str) -> Result<RadecoProject, &'static str> {
    let r2p = R2Pipe::http(url)?;
    Ok(load_project_by_r2pipe(r2p))
}

fn load_project_by_r2pipe(r2p: R2Pipe) -> RadecoProject {
    let r2 = R2::from(r2p);
    let r2w = Rc::new(RefCell::new(r2));
    let mut p = ProjectLoader::new().source(Rc::new(r2w)).load();
    let regfile = p.regfile().clone();
    for mut xy in p.iter_mut() {
        analyze_mod(regfile.clone(), xy.module);
    }
    p
}

fn fn_list(proj: &RadecoProject) -> Vec<String> {
    proj.iter()
        .map(|i| i.module)
        .flat_map(|rmod| rmod.functions.values())
        .map(|s| s.name.to_string())
        .collect()
}

fn get_function<'a>(name: &str, proj: &'a RadecoProject) -> Option<&'a RadecoFunction> {
    proj.iter()
        .map(|i| i.module)
        .flat_map(|rmod| rmod.functions.values())
        .filter(|rfn| rfn.name == name)
        .next()
}

fn get_function_mut<'a>(name: &str, proj: &'a mut RadecoProject) -> Option<&'a mut RadecoFunction> {
    proj.iter_mut()
        .map(|i| i.module)
        .flat_map(|rmod| rmod.functions.values_mut())
        .filter(|rfn| rfn.name == name)
        .next()
}

fn analyze_mod(regfile: Arc<SubRegisterFile>, rmod: &mut RadecoModule) {
    // Analyze preserved for all functions.
    {
        println!("[*] Fixing Callee Information");
        let bp_name = regfile.get_name_by_alias(&"BP".to_string());
        let bp_name = bp_name.map(|s| s.to_owned());
        let sp_name = regfile.get_name_by_alias(&"SP".to_string());
        let sp_name = sp_name.map(|s| s.to_owned());
        let mut callfixer = CallFixer::new(rmod, bp_name, sp_name);
        callfixer.rounded_analysis();
    }

    // Fix call sites
    radeco_lib::analysis::functions::fix_ssa_opcalls::go(rmod);

    // Infer calling conventions
    radeco_lib::analysis::functions::infer_regusage::run(rmod, &*regfile);
}

fn analyze(rfn: &mut RadecoFunction) {
    println!("[+] Analyzing: {} @ {:#x}", rfn.name, rfn.offset);
    {
        println!("  [*] Eliminating Dead Code");
        dce::collect(rfn.ssa_mut());
    }
    let mut ssa = {
        // Constant Propagation (sccp)
        println!("  [*] Propagating Constants");
        let mut analyzer = sccp::Analyzer::new(rfn.ssa_mut());
        analyzer.analyze();
        analyzer.emit_ssa()
    };
    {
        println!("  [*] Eliminating More DeadCode");
        dce::collect(&mut ssa);
    }
    *rfn.ssa_mut() = ssa;
    {
        // Common SubExpression Elimination (cse)
        println!("  [*] Eliminating Common SubExpressions");
        let mut cse = CSE::new(rfn.ssa_mut());
        cse.run();
    }
    {
        // Verify SSA
        println!("  [*] Verifying SSA's Validity");
        match verifier::verify(rfn.ssa()) {
            Err(e) => {
                println!("  [*] Found Error: {}", e);
                process::exit(255);
            }
            Ok(_) => {}
        }
    }
}

fn emit_ir(rfn: &RadecoFunction) -> String {
    println!("  [*] Writing out IR");
    let mut res = String::new();
    ir_writer::emit_il(&mut res, Some(rfn.name.to_string()), rfn.ssa()).unwrap();
    res
}

fn emit_dot(ssa: &SSAStorage) -> String {
    dot::emit_dot(ssa)
}

fn decompile(
    rfn: &RadecoFunction,
    func_name_map: &HashMap<u64, String>,
    strings: &HashMap<u64, String>,
) -> String {
    let c_cfg = c_cfg_builder::recover_c_cfg(rfn, func_name_map, strings);
    if let Err(err) = CCFGVerifier::verify(&c_cfg) {
        println!("CCFG verification failed");
        println!("{}", err);
    }
    ctrl_flow_struct::structure_and_convert(c_cfg)
        .unwrap()
        .print()
}
<commit_msg>Load a file if command line argument is given<commit_after>#[cfg(feature = "trace_log")]
extern crate env_logger;

extern crate radeco_lib;
extern crate r2pipe;
extern crate r2api;
extern crate base64;
extern crate rustyline;

use r2pipe::{R2, R2Pipe};
use radeco_lib::analysis::cse::cse::CSE;
use radeco_lib::analysis::interproc::fixcall::CallFixer;
use radeco_lib::analysis::sccp;
use radeco_lib::backend::lang_c::c_cfg::CCFGVerifier;
use radeco_lib::backend::lang_c::c_cfg::ctrl_flow_struct;
use radeco_lib::backend::lang_c::c_cfg_builder;
use radeco_lib::frontend::radeco_containers::*;
use radeco_lib::middle::{dce, dot};
use radeco_lib::middle::ir_writer;
use radeco_lib::middle::regfile::SubRegisterFile;
use radeco_lib::middle::ssa::ssastorage::SSAStorage;
use radeco_lib::middle::ssa::verifier;
use rustyline::Editor;

use rustyline::error::ReadlineError;
use std::cell::RefCell;
use std::collections::HashMap;
use std::env;

use std::fs;
use std::process;
use std::rc::Rc;
use std::str;
use std::sync::Arc;

mod scheme {
    pub const HTTP: &'static str = "http://";
    pub const TCP: &'static str = "tcp://";
}

// On unix platforms you can use ANSI escape sequences
#[cfg(unix)]
const PROMPT: &'static str = "\x1b[1;32m>>\x1b[0m ";

// Windows consoles typically don't support ANSI escape sequences out
// of the box
#[cfg(windows)]
const PROMPT: &'static str = ">> ";

fn main() {
    let mut rl = Editor::<()>::new();
    let mut proj = env::args().nth(1).and_then(|ref s| {
        if is_http(s) {
            load_proj_http(&s[scheme::HTTP.len()..])
        } else if is_tcp(s) {
            load_proj_tcp(&s[scheme::TCP.len()..])
        } else if is_file(s) {
            Ok(load_proj_by_path(s))
        } else {
            Err("Invalid argument")
        }.ok()
    });
    loop {
        let readline = rl.readline(PROMPT);
        match readline {
            Ok(line) => {
                let mut terms = line.split_whitespace();
                let o1 = terms.next();
                let o2 = terms.next();
                cmd(o1, o2, &mut proj);
            }
            Err(ReadlineError::Interrupted) |
            Err(ReadlineError::Eof) => break,
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }
        }
    }
}

mod command {
    pub const LOAD: &'static str = "load";
    pub const CONNECT: &'static str = "connect";
    pub const FNLIST: &'static str = "fn_list";
    pub const ANALYZE: &'static str = "analyze";
    pub const DOT: &'static str = "dot";
    pub const IR: &'static str = "ir";
    pub const DECOMPILE: &'static str = "decompile";
}

fn cmd(op1: Option<&str>, op2: Option<&str>, proj_opt: &mut Option<RadecoProject>) {
    match (op1, op2) {
        (Some(command::LOAD), Some(path)) => {
            *proj_opt = Some(load_proj_by_path(path));
            return;
        }
        (Some(command::CONNECT), Some(url)) => {
            let p_opt = if url.starts_with("http://") {
                load_proj_http(&url[7..])
            } else {
                load_proj_tcp(&url[6..])
            };
            match p_opt {
                Ok(proj) => *proj_opt = Some(proj),
                Err(msg) => println!("{}", msg),
            }
            return;
        }
        _ => {}
    };
    let mut proj = match proj_opt {
        Some(proj) => proj,
        None => {
            println!("Load a project first");
            return;
        }
    };
    match (op1, op2) {
        (Some(command::ANALYZE), Some("*")) => {
            let rfns = proj.iter_mut().map(|i| i.module).flat_map(|rmod| {
                rmod.functions.values_mut()
            });
            for rfn in rfns {
                analyze(rfn);
            }
        }
        (Some(command::FNLIST), _) => {
            let funcs = fn_list(&proj);
            println!("{}", funcs.join("\n"));
        }
        // TODO Show list of dependency information of analyses
        // TODO Add command for individual analyses
        (Some(command::ANALYZE), Some(f)) => {
            if let Some(rfn) = get_function_mut(f, &mut proj) {
                analyze(rfn);
            } else {
                println!("{} is not found", f);
            }
        }
        (Some(command::DOT), Some(f)) => {
            if let Some(rfn) = get_function(f, &proj) {
                println!("{}", emit_dot(rfn.ssa()));
            } else {
                println!("{} is not found", f);
            }
        }
        (Some(command::IR), Some(f)) => {
            if let Some(rfn) = get_function(f, &proj) {
                println!("{}", emit_ir(rfn));
            } else {
                println!("{} is not found", f);
            }
        }
        (Some(command::DECOMPILE), Some(f)) => {
            if let Some(rfn) = get_function(f, &proj) {
                let rmod = proj.iter().map(|i| i.module).next().unwrap();
                let func_name_map = rmod.functions
                    .iter()
                    .map(|(&addr, f)| (addr, f.name.to_string()))
                    .collect();
                let strings = rmod.strings()
                    .iter()
                    .filter(|ref s| s.vaddr.is_some() && s.string.is_some())
                    .cloned()
                    .map(|s| {
                        let (addr, _s) = (s.vaddr.unwrap(), s.string.unwrap());
                        let bytes = base64::decode(&_s).unwrap_or(Vec::new());
                        let ret_string = match str::from_utf8(bytes.as_slice()) {
                            Ok(v) => v.to_string(),
                            Err(_e) => _s,
                        };
                        (addr, ret_string)
                    })
                    .collect();
                println!("{}", decompile(rfn, &func_name_map, &strings));
            } else {
                println!("{} is not found", f);
            }
        }
        _ => {}
    }
}

fn load_proj_by_path(path: &str) -> RadecoProject {
    let mut p = ProjectLoader::new().path(path).load();
    let regfile = p.regfile().clone();
    for mut xy in p.iter_mut() {
        analyze_mod(regfile.clone(), xy.module);
    }
    p
}

fn load_proj_tcp(url: &str) -> Result<RadecoProject, &'static str> {
    let r2p = R2Pipe::tcp(url)?;
    Ok(load_project_by_r2pipe(r2p))
}

fn load_proj_http(url: &str) -> Result<RadecoProject, &'static str> {
    let r2p = R2Pipe::http(url)?;
    Ok(load_project_by_r2pipe(r2p))
}

fn load_project_by_r2pipe(r2p: R2Pipe) -> RadecoProject {
    let r2 = R2::from(r2p);
    let r2w = Rc::new(RefCell::new(r2));
    let mut p = ProjectLoader::new().source(Rc::new(r2w)).load();
    let regfile = p.regfile().clone();
    for mut xy in p.iter_mut() {
        analyze_mod(regfile.clone(), xy.module);
    }
    p
}

fn fn_list(proj: &RadecoProject) -> Vec<String> {
    proj.iter()
        .map(|i| i.module)
        .flat_map(|rmod| rmod.functions.values())
        .map(|s| s.name.to_string())
        .collect()
}

fn get_function<'a>(name: &str, proj: &'a RadecoProject) -> Option<&'a RadecoFunction> {
    proj.iter()
        .map(|i| i.module)
        .flat_map(|rmod| rmod.functions.values())
        .filter(|rfn| rfn.name == name)
        .next()
}

fn get_function_mut<'a>(name: &str, proj: &'a mut RadecoProject) -> Option<&'a mut RadecoFunction> {
    proj.iter_mut()
        .map(|i| i.module)
        .flat_map(|rmod| rmod.functions.values_mut())
        .filter(|rfn| rfn.name == name)
        .next()
}

fn analyze_mod(regfile: Arc<SubRegisterFile>, rmod: &mut RadecoModule) {
    // Analyze preserved for all functions.
    {
        println!("[*] Fixing Callee Information");
        let bp_name = regfile.get_name_by_alias(&"BP".to_string());
        let bp_name = bp_name.map(|s| s.to_owned());
        let sp_name = regfile.get_name_by_alias(&"SP".to_string());
        let sp_name = sp_name.map(|s| s.to_owned());
        let mut callfixer = CallFixer::new(rmod, bp_name, sp_name);
        callfixer.rounded_analysis();
    }

    // Fix call sites
    radeco_lib::analysis::functions::fix_ssa_opcalls::go(rmod);

    // Infer calling conventions
    radeco_lib::analysis::functions::infer_regusage::run(rmod, &*regfile);
}

fn analyze(rfn: &mut RadecoFunction) {
    println!("[+] Analyzing: {} @ {:#x}", rfn.name, rfn.offset);
    {
        println!("  [*] Eliminating Dead Code");
        dce::collect(rfn.ssa_mut());
    }
    let mut ssa = {
        // Constant Propagation (sccp)
        println!("  [*] Propagating Constants");
        let mut analyzer = sccp::Analyzer::new(rfn.ssa_mut());
        analyzer.analyze();
        analyzer.emit_ssa()
    };
    {
        println!("  [*] Eliminating More DeadCode");
        dce::collect(&mut ssa);
    }
    *rfn.ssa_mut() = ssa;
    {
        // Common SubExpression Elimination (cse)
        println!("  [*] Eliminating Common SubExpressions");
        let mut cse = CSE::new(rfn.ssa_mut());
        cse.run();
    }
    {
        // Verify SSA
        println!("  [*] Verifying SSA's Validity");
        match verifier::verify(rfn.ssa()) {
            Err(e) => {
                println!("  [*] Found Error: {}", e);
                process::exit(255);
            }
            Ok(_) => {}
        }
    }
}

fn emit_ir(rfn: &RadecoFunction) -> String {
    println!("  [*] Writing out IR");
    let mut res = String::new();
    ir_writer::emit_il(&mut res, Some(rfn.name.to_string()), rfn.ssa()).unwrap();
    res
}

fn emit_dot(ssa: &SSAStorage) -> String {
    dot::emit_dot(ssa)
}

fn decompile(
    rfn: &RadecoFunction,
    func_name_map: &HashMap<u64, String>,
    strings: &HashMap<u64, String>,
) -> String {
    let c_cfg = c_cfg_builder::recover_c_cfg(rfn, func_name_map, strings);
    if let Err(err) = CCFGVerifier::verify(&c_cfg) {
        println!("CCFG verification failed");
        println!("{}", err);
    }
    ctrl_flow_struct::structure_and_convert(c_cfg)
        .unwrap()
        .print()
}

fn is_file(path: &str) -> bool {
    fs::metadata(path).map(|f| f.is_file()).unwrap_or(false)
}

fn is_http(url: &str) -> bool {
    url.starts_with(scheme::HTTP)
}

fn is_tcp(url: &str) -> bool {
    url.starts_with(scheme::TCP)
}
<|endoftext|>


<commit_before>// Copyright 2016 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

use std::collections::{BTreeSet, BTreeMap, LinkedList};
use std::cmp::{Ordering, Ord, PartialOrd};
use std::fmt::{Display, Formatter};

use symbols;
use num::BigInt;
use ordered_float::OrderedFloat;

/// Value represents one of the allowed values in an EDN string.
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum Value {
    Nil,
    Boolean(bool),
    Integer(i64),
    BigInteger(BigInt),
    // https://users.rust-lang.org/t/hashmap-key-cant-be-float-number-type-why/7892
    Float(OrderedFloat<f64>),
    Text(String),
    PlainSymbol(symbols::PlainSymbol),
    NamespacedSymbol(symbols::NamespacedSymbol),
    Keyword(symbols::Keyword),
    NamespacedKeyword(symbols::NamespacedKeyword),
    Vector(Vec<Value>),
    List(LinkedList<Value>),
    // We're using BTree{Set, Map} rather than Hash{Set, Map} because the BTree variants
    // implement Hash. The Hash variants don't in order to preserve O(n) hashing
    // time, which is hard given recursive data structures.
    // See https://internals.rust-lang.org/t/implementing-hash-for-hashset-hashmap/3817/1
    Set(BTreeSet<Value>),
    Map(BTreeMap<Value, Value>),
}

use self::Value::*;

impl Display for Value {
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        match *self {
            Keyword(ref v) => v.fmt(f),
            NamespacedKeyword(ref v) => v.fmt(f),
            PlainSymbol(ref v) => v.fmt(f),
            NamespacedSymbol(ref v) => v.fmt(f),

            Integer(v) => write!(f, "{}", v),
            BigInteger(ref v) => write!(f, "{}N", v),
            Float(OrderedFloat(v)) => write!(f, "{}", v),       // TODO: make sure float syntax is correct.
                                                                // TODO: NaN.
            Text(ref v) => write!(f, "{}", v),                  // TODO: EDN escaping.
            Vector(ref v) => {
                try!(write!(f, "["));
                for x in v {
                    try!(write!(f, " {}", x));
                }
                write!(f, " ]")
            }
            _ =>
                write!(f, "{}",
                       match *self {
                           Nil => "null",
                           Boolean(b) => if b { "true" } else { "false" },
                           _ => unimplemented!(),
                       }),
        }
    }
}

#[test]
fn test_print_edn() {
    assert_eq!("[ 1 2 [ 3.1 ] [ ] :five :six/seven eight nine/ten true ]",
               Value::Vector(vec!(Value::Integer(1),
               Value::Integer(2),
               Value::Vector(vec!(Value::Float(OrderedFloat(3.1)))),
               Value::Vector(vec!()),
               Value::Keyword(symbols::Keyword::new("five")),
               Value::NamespacedKeyword(symbols::NamespacedKeyword::new("six", "seven")),
               Value::PlainSymbol(symbols::PlainSymbol::new("eight")),
               Value::NamespacedSymbol(symbols::NamespacedSymbol::new("nine", "ten")),
               Value::Boolean(true))).to_string());
}

/// Creates `is_$TYPE` helper functions for Value, like
/// `is_big_integer()` or `is_text()`.
macro_rules! def_is {
    ($name: ident, $pat: pat) => {
        pub fn $name(&self) -> bool {
            match *self { $pat => true, _ => false }
        }
    }
}

/// Creates `as_$TYPE` helper functions for Value, like `as_big_integer()`,
/// which returns the underlying value representing this Value wrapped
/// in an Option, like `<Option<&BigInt>`.
macro_rules! def_as {
    ($name: ident, $kind: path, $t: ty) => {
        pub fn $name(&self) -> Option<&$t> {
            match *self { $kind(ref v) => Some(v), _ => None }
        }
    }
}

impl Value {
    def_is!(is_nil, Nil);
    def_is!(is_boolean, Boolean(_));
    def_is!(is_integer, Integer(_));
    def_is!(is_big_integer, BigInteger(_));
    def_is!(is_float, Float(_));
    def_is!(is_text, Text(_));
    def_is!(is_symbol, PlainSymbol(_));
    def_is!(is_namespaced_symbol, NamespacedSymbol(_));
    def_is!(is_keyword, Keyword(_));
    def_is!(is_namespaced_keyword, NamespacedKeyword(_));
    def_is!(is_vector, Vector(_));
    def_is!(is_list, List(_));
    def_is!(is_set, Set(_));
    def_is!(is_map, Map(_));

    /// `as_nil` does not use the macro as it does not have an underlying
    /// value, and returns `Option<()>`.
    pub fn as_nil(&self) -> Option<()> {
        match *self { Nil => Some(()), _ => None }
    }

    def_as!(as_boolean, Boolean, bool);
    def_as!(as_integer, Integer, i64);
    def_as!(as_big_integer, BigInteger, BigInt);
    def_as!(as_float, Float, OrderedFloat<f64>);
    def_as!(as_text, Text, String);
    def_as!(as_symbol, PlainSymbol, symbols::PlainSymbol);
    def_as!(as_namespaced_symbol, NamespacedSymbol, symbols::NamespacedSymbol);
    def_as!(as_keyword, Keyword, symbols::Keyword);
    def_as!(as_namespaced_keyword, NamespacedKeyword, symbols::NamespacedKeyword);
    def_as!(as_vector, Vector, Vec<Value>);
    def_as!(as_list, List, LinkedList<Value>);
    def_as!(as_set, Set, BTreeSet<Value>);
    def_as!(as_map, Map, BTreeMap<Value, Value>);
}

impl PartialOrd for Value {
    fn partial_cmp(&self, other: &Value) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

// TODO: Check we follow the equality rules at the bottom of https://github.com/edn-format/edn
impl Ord for Value {
    fn cmp(&self, other: &Value) -> Ordering {

        let ord_order = to_ord(self).cmp(&to_ord(other));
        match *self {
            Nil             => match *other { Nil             => Ordering::Equal, _ => ord_order },
            Boolean(bs)     => match *other { Boolean(bo)     => bo.cmp(&bs), _ => ord_order },
            BigInteger(ref bs) => match *other { BigInteger(ref bo) => bo.cmp(&bs), _ => ord_order },
            Integer(is)     => match *other { Integer(io)     => io.cmp(&is), _ => ord_order },
            Float(ref fs)   => match *other { Float(ref fo)   => fo.cmp(&fs), _ => ord_order },
            Text(ref ts)    => match *other { Text(ref to)    => to.cmp(&ts), _ => ord_order },
            PlainSymbol(ref ss)  => match *other { PlainSymbol(ref so)  => so.cmp(&ss), _ => ord_order },
            NamespacedSymbol(ref ss)
                => match *other { NamespacedSymbol(ref so)    => so.cmp(&ss), _ => ord_order },
            Keyword(ref ks) => match *other { Keyword(ref ko) => ko.cmp(&ks), _ => ord_order },
            NamespacedKeyword(ref ks)
                => match *other { NamespacedKeyword(ref ko)   => ko.cmp(&ks), _ => ord_order },
            Vector(ref vs)  => match *other { Vector(ref vo)  => vo.cmp(&vs), _ => ord_order },
            List(ref ls)    => match *other { List(ref lo)    => lo.cmp(&ls), _ => ord_order },
            Set(ref ss)     => match *other { Set(ref so)     => so.cmp(&ss), _ => ord_order },
            Map(ref ms)     => match *other { Map(ref mo)     => mo.cmp(&ms), _ => ord_order },
        }
    }
}

fn to_ord(value: &Value) -> i32 {
    match *value {
        Nil => 0,
        Boolean(_) => 1,
        Integer(_) => 2,
        BigInteger(_) => 3,
        Float(_) => 4,
        Text(_) => 5,
        PlainSymbol(_) => 6,
        NamespacedSymbol(_) => 7,
        Keyword(_) => 8,
        NamespacedKeyword(_) => 9,
        Vector(_) => 10,
        List(_) => 11,
        Set(_) => 12,
        Map(_) => 13,
    }
}

pub struct Pair(Value, Value);

pub fn to_symbol<'a, T: Into<Option<&'a str>>>(namespace: T, name: &str) -> Value {
    if let Some(ns) = namespace.into() {
        return Value::NamespacedSymbol(symbols::NamespacedSymbol::new(ns, name));
    }
    return Value::PlainSymbol(symbols::PlainSymbol::new(name));
}

pub fn to_keyword<'a, T: Into<Option<&'a str>>>(namespace: T, name: &str) -> Value {
    if let Some(ns) = namespace.into() {
        return Value::NamespacedKeyword(symbols::NamespacedKeyword::new(ns, name));
    }
    return Value::Keyword(symbols::Keyword::new(name));
}
<commit_msg>Add helper functions constructing OrderedFloat and BigInt to edn crate, r=ncalexan,rnewman. Fixes #198<commit_after>// Copyright 2016 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

#![allow(unused_imports)]

use std::collections::{BTreeSet, BTreeMap, LinkedList};
use std::cmp::{Ordering, Ord, PartialOrd};
use std::fmt::{Display, Formatter};

use symbols;
use num::bigint::{BigInt, ToBigInt, ParseBigIntError};
use ordered_float::OrderedFloat;

/// Value represents one of the allowed values in an EDN string.
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum Value {
    Nil,
    Boolean(bool),
    Integer(i64),
    BigInteger(BigInt),
    // https://users.rust-lang.org/t/hashmap-key-cant-be-float-number-type-why/7892
    Float(OrderedFloat<f64>),
    Text(String),
    PlainSymbol(symbols::PlainSymbol),
    NamespacedSymbol(symbols::NamespacedSymbol),
    Keyword(symbols::Keyword),
    NamespacedKeyword(symbols::NamespacedKeyword),
    Vector(Vec<Value>),
    List(LinkedList<Value>),
    // We're using BTree{Set, Map} rather than Hash{Set, Map} because the BTree variants
    // implement Hash. The Hash variants don't in order to preserve O(n) hashing
    // time, which is hard given recursive data structures.
    // See https://internals.rust-lang.org/t/implementing-hash-for-hashset-hashmap/3817/1
    Set(BTreeSet<Value>),
    Map(BTreeMap<Value, Value>),
}

use self::Value::*;

impl Display for Value {
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        match *self {
            Keyword(ref v) => v.fmt(f),
            NamespacedKeyword(ref v) => v.fmt(f),
            PlainSymbol(ref v) => v.fmt(f),
            NamespacedSymbol(ref v) => v.fmt(f),

            Integer(v) => write!(f, "{}", v),
            BigInteger(ref v) => write!(f, "{}N", v),
            Float(OrderedFloat(v)) => write!(f, "{}", v),       // TODO: make sure float syntax is correct.
                                                                // TODO: NaN.
            Text(ref v) => write!(f, "{}", v),                  // TODO: EDN escaping.
            Vector(ref v) => {
                try!(write!(f, "["));
                for x in v {
                    try!(write!(f, " {}", x));
                }
                write!(f, " ]")
            }
            _ =>
                write!(f, "{}",
                       match *self {
                           Nil => "null",
                           Boolean(b) => if b { "true" } else { "false" },
                           _ => unimplemented!(),
                       }),
        }
    }
}

#[test]
fn test_value_from() {
    assert_eq!(Value::from(42f64), Value::Float(OrderedFloat::from(42f64)));
    assert_eq!(Value::from_bigint("42").unwrap(), Value::BigInteger(42.to_bigint().unwrap()));
}

#[test]
fn test_print_edn() {
    assert_eq!("[ 1 2 [ 3.1 ] [ ] :five :six/seven eight nine/ten true ]",
               Value::Vector(vec!(Value::Integer(1),
               Value::Integer(2),
               Value::Vector(vec!(Value::Float(OrderedFloat(3.1)))),
               Value::Vector(vec!()),
               Value::Keyword(symbols::Keyword::new("five")),
               Value::NamespacedKeyword(symbols::NamespacedKeyword::new("six", "seven")),
               Value::PlainSymbol(symbols::PlainSymbol::new("eight")),
               Value::NamespacedSymbol(symbols::NamespacedSymbol::new("nine", "ten")),
               Value::Boolean(true))).to_string());
}

/// Creates `is_$TYPE` helper functions for Value, like
/// `is_big_integer()` or `is_text()`.
macro_rules! def_is {
    ($name: ident, $pat: pat) => {
        pub fn $name(&self) -> bool {
            match *self { $pat => true, _ => false }
        }
    }
}

/// Creates `as_$TYPE` helper functions for Value, like `as_big_integer()`,
/// which returns the underlying value representing this Value wrapped
/// in an Option, like `<Option<&BigInt>`.
macro_rules! def_as {
    ($name: ident, $kind: path, $t: ty) => {
        pub fn $name(&self) -> Option<&$t> {
            match *self { $kind(ref v) => Some(v), _ => None }
        }
    }
}

impl Value {
    def_is!(is_nil, Nil);
    def_is!(is_boolean, Boolean(_));
    def_is!(is_integer, Integer(_));
    def_is!(is_big_integer, BigInteger(_));
    def_is!(is_float, Float(_));
    def_is!(is_text, Text(_));
    def_is!(is_symbol, PlainSymbol(_));
    def_is!(is_namespaced_symbol, NamespacedSymbol(_));
    def_is!(is_keyword, Keyword(_));
    def_is!(is_namespaced_keyword, NamespacedKeyword(_));
    def_is!(is_vector, Vector(_));
    def_is!(is_list, List(_));
    def_is!(is_set, Set(_));
    def_is!(is_map, Map(_));

    /// `as_nil` does not use the macro as it does not have an underlying
    /// value, and returns `Option<()>`.
    pub fn as_nil(&self) -> Option<()> {
        match *self { Nil => Some(()), _ => None }
    }

    def_as!(as_boolean, Boolean, bool);
    def_as!(as_integer, Integer, i64);
    def_as!(as_big_integer, BigInteger, BigInt);
    def_as!(as_float, Float, OrderedFloat<f64>);
    def_as!(as_text, Text, String);
    def_as!(as_symbol, PlainSymbol, symbols::PlainSymbol);
    def_as!(as_namespaced_symbol, NamespacedSymbol, symbols::NamespacedSymbol);
    def_as!(as_keyword, Keyword, symbols::Keyword);
    def_as!(as_namespaced_keyword, NamespacedKeyword, symbols::NamespacedKeyword);
    def_as!(as_vector, Vector, Vec<Value>);
    def_as!(as_list, List, LinkedList<Value>);
    def_as!(as_set, Set, BTreeSet<Value>);
    def_as!(as_map, Map, BTreeMap<Value, Value>);

    pub fn from_bigint(src: &str) -> Option<Value> {
        src.parse::<BigInt>().map(Value::BigInteger).ok()
    }
}

impl From<f64> for Value {
    fn from(src: f64) -> Value {
        Value::Float(OrderedFloat::from(src))
    }
}

impl PartialOrd for Value {
    fn partial_cmp(&self, other: &Value) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

// TODO: Check we follow the equality rules at the bottom of https://github.com/edn-format/edn
impl Ord for Value {
    fn cmp(&self, other: &Value) -> Ordering {

        let ord_order = to_ord(self).cmp(&to_ord(other));
        match *self {
            Nil             => match *other { Nil             => Ordering::Equal, _ => ord_order },
            Boolean(bs)     => match *other { Boolean(bo)     => bo.cmp(&bs), _ => ord_order },
            BigInteger(ref bs) => match *other { BigInteger(ref bo) => bo.cmp(&bs), _ => ord_order },
            Integer(is)     => match *other { Integer(io)     => io.cmp(&is), _ => ord_order },
            Float(ref fs)   => match *other { Float(ref fo)   => fo.cmp(&fs), _ => ord_order },
            Text(ref ts)    => match *other { Text(ref to)    => to.cmp(&ts), _ => ord_order },
            PlainSymbol(ref ss)  => match *other { PlainSymbol(ref so)  => so.cmp(&ss), _ => ord_order },
            NamespacedSymbol(ref ss)
                => match *other { NamespacedSymbol(ref so)    => so.cmp(&ss), _ => ord_order },
            Keyword(ref ks) => match *other { Keyword(ref ko) => ko.cmp(&ks), _ => ord_order },
            NamespacedKeyword(ref ks)
                => match *other { NamespacedKeyword(ref ko)   => ko.cmp(&ks), _ => ord_order },
            Vector(ref vs)  => match *other { Vector(ref vo)  => vo.cmp(&vs), _ => ord_order },
            List(ref ls)    => match *other { List(ref lo)    => lo.cmp(&ls), _ => ord_order },
            Set(ref ss)     => match *other { Set(ref so)     => so.cmp(&ss), _ => ord_order },
            Map(ref ms)     => match *other { Map(ref mo)     => mo.cmp(&ms), _ => ord_order },
        }
    }
}

fn to_ord(value: &Value) -> i32 {
    match *value {
        Nil => 0,
        Boolean(_) => 1,
        Integer(_) => 2,
        BigInteger(_) => 3,
        Float(_) => 4,
        Text(_) => 5,
        PlainSymbol(_) => 6,
        NamespacedSymbol(_) => 7,
        Keyword(_) => 8,
        NamespacedKeyword(_) => 9,
        Vector(_) => 10,
        List(_) => 11,
        Set(_) => 12,
        Map(_) => 13,
    }
}

pub struct Pair(Value, Value);

pub fn to_symbol<'a, T: Into<Option<&'a str>>>(namespace: T, name: &str) -> Value {
    if let Some(ns) = namespace.into() {
        return Value::NamespacedSymbol(symbols::NamespacedSymbol::new(ns, name));
    }
    return Value::PlainSymbol(symbols::PlainSymbol::new(name));
}

pub fn to_keyword<'a, T: Into<Option<&'a str>>>(namespace: T, name: &str) -> Value {
    if let Some(ns) = namespace.into() {
        return Value::NamespacedKeyword(symbols::NamespacedKeyword::new(ns, name));
    }
    return Value::Keyword(symbols::Keyword::new(name));
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::boxed::Box;
use std::result;
use std::error;

use bytes::{Buf, ByteBuf};
use mio::{self, Token};

use util::codec;

mod conn;
mod server;
mod run;
mod handler;
mod bench;

pub type Result<T> = result::Result<T, Box<error::Error + Send + Sync>>;

const SERVER_TOKEN: Token = Token(0);
const FIRST_CUSTOM_TOKEN: Token = Token(1024);

const DEFAULT_BASE_TICK_MS: u64 = 100;

#[derive(Clone, Debug)]
pub struct Config {
    pub addr: String,
}

pub struct ConnData {
    token: Token,
    msg_id: u64,
    data: ByteBuf,
}

pub enum TimerMsg {
    // None is just for test, we will remove this later.
    None,
}

pub struct TimerData {
    delay: u64,
    msg: TimerMsg,
}

impl ConnData {
    pub fn encode_to_buf(&self) -> ByteBuf {
        let mut buf = ByteBuf::mut_with_capacity(codec::MSG_HEADER_LEN + self.data.bytes().len());

        // Must ok here
        codec::encode_data(&mut buf, self.msg_id, self.data.bytes()).unwrap();

        buf.flip()
    }
}

pub enum Msg {
    // Quit event loop.
    Quit,
    // Read data from connection.
    ReadData(ConnData),
    // Write data to connection.
    WriteData(ConnData),
    // Tick is for base internal tick message.
    Tick,
    // Timer is for custom timeout message.
    Timer(TimerData),
}

#[derive(Debug)]
pub struct Sender {
    sender: mio::Sender<Msg>,
}

impl Clone for Sender {
    fn clone(&self) -> Sender {
        Sender { sender: self.sender.clone() }
    }
}

impl Sender {
    pub fn new(sender: mio::Sender<Msg>) -> Sender {
        Sender { sender: sender }
    }

    pub fn kill(&self) -> Result<()> {
        try!(self.sender.send(Msg::Quit));
        Ok(())
    }

    pub fn write_data(&self, data: ConnData) -> Result<()> {
        try!(self.sender.send(Msg::WriteData(data)));

        Ok(())
    }

    pub fn timeout_ms(&self, delay: u64, m: TimerMsg) -> Result<()> {
        try!(self.sender.send(Msg::Timer(TimerData {
            delay: delay,
            msg: m,
        })));

        Ok(())
    }
}
<commit_msg>raftserver: Address comment.<commit_after>#![allow(dead_code)]

use std::boxed::Box;
use std::result;
use std::error;

use bytes::{Buf, ByteBuf};
use mio::{self, Token};

use util::codec;

mod conn;
mod server;
mod run;
mod handler;
mod bench;

pub type Result<T> = result::Result<T, Box<error::Error + Send + Sync>>;

const SERVER_TOKEN: Token = Token(0);
const FIRST_CUSTOM_TOKEN: Token = Token(1024);

const DEFAULT_BASE_TICK_MS: u64 = 100;

#[derive(Clone, Debug)]
pub struct Config {
    pub addr: String,
}

pub struct ConnData {
    token: Token,
    msg_id: u64,
    data: ByteBuf,
}

impl ConnData {
    pub fn encode_to_buf(&self) -> ByteBuf {
        let mut buf = ByteBuf::mut_with_capacity(codec::MSG_HEADER_LEN + self.data.bytes().len());

        // Must ok here
        codec::encode_data(&mut buf, self.msg_id, self.data.bytes()).unwrap();

        buf.flip()
    }
}

pub enum TimerMsg {
    // None is just for test, we will remove this later.
    None,
}

pub struct TimerData {
    delay: u64,
    msg: TimerMsg,
}

pub enum Msg {
    // Quit event loop.
    Quit,
    // Read data from connection.
    ReadData(ConnData),
    // Write data to connection.
    WriteData(ConnData),
    // Tick is for base internal tick message.
    Tick,
    // Timer is for custom timeout message.
    Timer(TimerData),
}

#[derive(Debug)]
pub struct Sender {
    sender: mio::Sender<Msg>,
}

impl Clone for Sender {
    fn clone(&self) -> Sender {
        Sender { sender: self.sender.clone() }
    }
}

impl Sender {
    pub fn new(sender: mio::Sender<Msg>) -> Sender {
        Sender { sender: sender }
    }

    pub fn kill(&self) -> Result<()> {
        try!(self.sender.send(Msg::Quit));
        Ok(())
    }

    pub fn write_data(&self, data: ConnData) -> Result<()> {
        try!(self.sender.send(Msg::WriteData(data)));

        Ok(())
    }

    pub fn timeout_ms(&self, delay: u64, m: TimerMsg) -> Result<()> {
        try!(self.sender.send(Msg::Timer(TimerData {
            delay: delay,
            msg: m,
        })));

        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::os::raw::c_void;
use runtime::{objc_autoreleasePoolPush, objc_autoreleasePoolPop};

// we use a struct to ensure that objc_autoreleasePoolPop during unwinding.
struct AutoReleaseHelper {
    context: *mut c_void,
}

impl AutoReleaseHelper {
    unsafe fn new() -> Self {
        AutoReleaseHelper { context: objc_autoreleasePoolPush() }
    }
}

impl Drop for AutoReleaseHelper {
    fn drop(&mut self) {
        unsafe { objc_autoreleasePoolPop(self.context) }
    }
}

/**
Execute `f` in the context of a new autorelease pool. The pool is drained
after the execution of `f` completes.

This corresponds to `@autoreleasepool` blocks in Objective-C and Swift.
*/
pub fn autoreleasepool<F: FnOnce()>(f: F) {
    let _context = unsafe { AutoReleaseHelper::new() };
    f();
}
<commit_msg>Add a generic return type to autoreleasepool()<commit_after>use std::os::raw::c_void;
use runtime::{objc_autoreleasePoolPush, objc_autoreleasePoolPop};

// we use a struct to ensure that objc_autoreleasePoolPop during unwinding.
struct AutoReleaseHelper {
    context: *mut c_void,
}

impl AutoReleaseHelper {
    unsafe fn new() -> Self {
        AutoReleaseHelper { context: objc_autoreleasePoolPush() }
    }
}

impl Drop for AutoReleaseHelper {
    fn drop(&mut self) {
        unsafe { objc_autoreleasePoolPop(self.context) }
    }
}

/**
Execute `f` in the context of a new autorelease pool. The pool is drained
after the execution of `f` completes.

This corresponds to `@autoreleasepool` blocks in Objective-C and Swift.
*/
pub fn autoreleasepool<T, F: FnOnce() -> T>(f: F) -> T {
    let _context = unsafe { AutoReleaseHelper::new() };
    f()
}
<|endoftext|>


<commit_before>#[doc(
    brief = "Provides all access to AST-related, non-sendable info",
    desc =
    "Rustdoc is intended to be parallel, and the rustc AST is filled \
     with shared boxes. The AST service attempts to provide a single \
     place to query AST-related information, shielding the rest of \
     Rustdoc from its non-sendableness."
)];

import rustc::syntax::ast;
import rustc::middle::ast_map;

export ctxt;
export ctxt_handler;
export srv;
export mk_srv_from_str;
export mk_srv_from_file;
export exec;

type ctxt = {
    ast: @ast::crate,
    map: ast_map::map
};

type ctxt_handler<T> = fn~(ctxt: ctxt) -> T;

type srv = {
    ctxt: ctxt
};

fn mk_srv_from_str(source: str) -> srv {
    {
        ctxt: build_ctxt(parse::from_str(source))
    }
}

fn mk_srv_from_file(file: str) -> srv {
    {
        ctxt: build_ctxt(parse::from_file(file))
    }
}

fn build_ctxt(ast: @ast::crate) -> ctxt {
    {
        ast: ast,
        map: ast_map::map_crate(*ast)
    }
}

fn exec<T>(
    srv: srv,
    f: fn~(ctxt: ctxt) -> T
) -> T {
    f(srv.ctxt)
}

#[cfg(test)]
mod tests {

    #[test]
    fn srv_should_build_ast_map() {
        let source = "fn a() { }";
        let srv = mk_srv_from_str(source);
        exec(srv) {|ctxt|
            assert ctxt.map.size() != 0u
        };
    }

    #[test]
    fn srv_should_return_request_result() {
        let source = "fn a() { }";
        let srv = mk_srv_from_str(source);
        let result = exec(srv) {|_ctxt| 1000};
        assert result == 1000;
    }
}<commit_msg>rustdoc: Prune unconfigured items from AST<commit_after>#[doc(
    brief = "Provides all access to AST-related, non-sendable info",
    desc =
    "Rustdoc is intended to be parallel, and the rustc AST is filled \
     with shared boxes. The AST service attempts to provide a single \
     place to query AST-related information, shielding the rest of \
     Rustdoc from its non-sendableness."
)];

import rustc::syntax::ast;
import rustc::middle::ast_map;

export ctxt;
export ctxt_handler;
export srv;
export mk_srv_from_str;
export mk_srv_from_file;
export exec;

type ctxt = {
    ast: @ast::crate,
    map: ast_map::map
};

type ctxt_handler<T> = fn~(ctxt: ctxt) -> T;

type srv = {
    ctxt: ctxt
};

fn mk_srv_from_str(source: str) -> srv {
    {
        ctxt: build_ctxt(parse::from_str(source))
    }
}

fn mk_srv_from_file(file: str) -> srv {
    {
        ctxt: build_ctxt(parse::from_file(file))
    }
}

fn build_ctxt(ast: @ast::crate) -> ctxt {

    import rustc::front::config;

    let ast = config::strip_unconfigured_items(ast);

    {
        ast: ast,
        map: ast_map::map_crate(*ast)
    }
}

#[test]
fn should_prune_unconfigured_items() {
    let source = "#[cfg(shut_up_and_leave_me_alone)]fn a() { }";
    let srv = mk_srv_from_str(source);
    exec(srv) {|ctxt|
        assert vec::is_empty(ctxt.ast.node.module.items);
    }
}

fn exec<T>(
    srv: srv,
    f: fn~(ctxt: ctxt) -> T
) -> T {
    f(srv.ctxt)
}

#[cfg(test)]
mod tests {

    #[test]
    fn srv_should_build_ast_map() {
        let source = "fn a() { }";
        let srv = mk_srv_from_str(source);
        exec(srv) {|ctxt|
            assert ctxt.map.size() != 0u
        };
    }

    #[test]
    fn srv_should_return_request_result() {
        let source = "fn a() { }";
        let srv = mk_srv_from_str(source);
        let result = exec(srv) {|_ctxt| 1000};
        assert result == 1000;
    }
}<|endoftext|>


<commit_before>use driver::ctxt::Context;
use error::msg::Msg;

use parser::ast::*;
use parser::ast::Stmt::*;
use parser::ast::visit::*;
use parser::lexer::position::Position;

use sym::*;

pub fn check(ctxt: &Context, ast: &Ast) {
    ReturnCheck::new(ctxt).visit_ast(ast);
}

struct ReturnCheck<'a, 'ast: 'a> {
    ctxt: &'a Context<'a, 'ast>,
}

impl<'a, 'ast> ReturnCheck<'a, 'ast> {
    fn new(ctxt: &'a Context<'a, 'ast>) -> ReturnCheck<'a, 'ast> {
        ReturnCheck {
            ctxt: ctxt,
        }
    }
}

impl<'a, 'ast> Visitor<'ast> for ReturnCheck<'a, 'ast> {
    fn visit_fct(&mut self, f: &'ast Function) {
        let types = self.ctxt.types.borrow();
        let return_type = *types.get(&f.id).unwrap();

        if return_type != BuiltinType::Unit {
            if let Err(pos) = returns_value(&f.block) {
                self.ctxt.diag.borrow_mut().report(pos, Msg::NoReturnValue);
            }
        }
    }
}

fn returns_value(s: &Stmt) -> Result<(), Position> {
    match *s {
        StmtReturn(_) => Ok(()),
        StmtBlock(ref stmt) => block_returns_value(stmt),
        StmtIf(ref stmt) => if_returns_value(stmt),
        StmtLoop(ref stmt) => returns_value(&stmt.block),

        StmtWhile(ref stmt) => Err(stmt.pos),
        StmtBreak(ref stmt) => Err(stmt.pos),
        StmtContinue(ref stmt) => Err(stmt.pos),
        StmtVar(ref stmt) => Err(stmt.pos),
        StmtExpr(ref stmt) => Err(stmt.pos),
    }
}

fn if_returns_value(s: &StmtIfType) -> Result<(), Position> {
    try!(returns_value(&s.then_block));

    match s.else_block {
        Some(ref block) => returns_value(block),
        None => Err(s.pos)
    }
}

fn block_returns_value(s: &StmtBlockType) -> Result<(), Position> {
    let mut pos = s.pos;

    for stmt in &s.stmts {
        if let Ok(_) = returns_value(stmt) {
            return Ok(());
        }

        pos = stmt.pos();
    }

    Err(pos)
}

#[cfg(test)]
mod tests {
    use error::msg::Msg;
    use semck::tests::*;

    #[test]
    fn returns_unit() {
        ok("fn f() {}");
        ok("fn f() { if true { return; } }");
        ok("fn f() { while true { return; } }");
    }

    #[test]
    fn returns_int() {
        err("fn f() -> int { }", pos(1, 15), Msg::NoReturnValue);
        err("fn f() -> int { if true { return 1; } }", pos(1, 17), Msg::NoReturnValue);
        err("fn f() -> int { if true { } else { return 1; } }", pos(1, 17), Msg::NoReturnValue);
        err("fn f() -> int { while true { return 1; } }", pos(1, 17), Msg::NoReturnValue);
        ok("fn f() -> int { loop { return 1; } }");
        ok("fn f() -> int { if true { return 1; } else { return 2; } }");
        ok("fn f() -> int { return 1; 1+2; }");
    }
}
<commit_msg>returnck: better position for errors<commit_after>use driver::ctxt::Context;
use error::msg::Msg;

use parser::ast::*;
use parser::ast::Stmt::*;
use parser::ast::visit::*;
use parser::lexer::position::Position;

use sym::*;

pub fn check(ctxt: &Context, ast: &Ast) {
    ReturnCheck::new(ctxt).visit_ast(ast);
}

struct ReturnCheck<'a, 'ast: 'a> {
    ctxt: &'a Context<'a, 'ast>,
}

impl<'a, 'ast> ReturnCheck<'a, 'ast> {
    fn new(ctxt: &'a Context<'a, 'ast>) -> ReturnCheck<'a, 'ast> {
        ReturnCheck {
            ctxt: ctxt,
        }
    }
}

impl<'a, 'ast> Visitor<'ast> for ReturnCheck<'a, 'ast> {
    fn visit_fct(&mut self, f: &'ast Function) {
        let types = self.ctxt.types.borrow();
        let return_type = *types.get(&f.id).unwrap();

        if return_type != BuiltinType::Unit {
            if let Err(pos) = returns_value(&f.block) {
                self.ctxt.diag.borrow_mut().report(pos, Msg::NoReturnValue);
            }
        }
    }
}

fn returns_value(s: &Stmt) -> Result<(), Position> {
    match *s {
        StmtReturn(_) => Ok(()),
        StmtBlock(ref stmt) => block_returns_value(stmt),
        StmtIf(ref stmt) => if_returns_value(stmt),
        StmtLoop(ref stmt) => returns_value(&stmt.block),

        StmtWhile(ref stmt) => Err(stmt.pos),
        StmtBreak(ref stmt) => Err(stmt.pos),
        StmtContinue(ref stmt) => Err(stmt.pos),
        StmtVar(ref stmt) => Err(stmt.pos),
        StmtExpr(ref stmt) => Err(stmt.pos),
    }
}

fn if_returns_value(s: &StmtIfType) -> Result<(), Position> {
    try!(returns_value(&s.then_block));

    match s.else_block {
        Some(ref block) => returns_value(block),
        None => Err(s.pos)
    }
}

fn block_returns_value(s: &StmtBlockType) -> Result<(), Position> {
    let mut pos = s.pos;

    for stmt in &s.stmts {
        match returns_value(stmt) {
            Ok(_) => return Ok(()),
            Err(err_pos) => pos = err_pos
        }
    }

    Err(pos)
}

#[cfg(test)]
mod tests {
    use error::msg::Msg;
    use semck::tests::*;

    #[test]
    fn returns_unit() {
        ok("fn f() {}");
        ok("fn f() { if true { return; } }");
        ok("fn f() { while true { return; } }");
        ok("fn f() { loop { return; } }");
    }

    #[test]
    fn returns_int() {
        err("fn f() -> int { }", pos(1, 15), Msg::NoReturnValue);
        err("fn f() -> int { if true { return 1; } }", pos(1, 17), Msg::NoReturnValue);
        err("fn f() -> int { if true { } else { return 1; } }", pos(1, 25), Msg::NoReturnValue);
        err("fn f() -> int { while true { return 1; } }", pos(1, 17), Msg::NoReturnValue);
        ok("fn f() -> int { loop { return 1; } }");
        ok("fn f() -> int { if true { return 1; } else { return 2; } }");
        ok("fn f() -> int { return 1; 1+2; }");
    }
}
<|endoftext|>


<commit_before>extern crate systemstat;

use std::thread;
use std::time::Duration;
use systemstat::{System, Platform};

fn main() {
    let sys = System::new();

    match sys.mounts() {
        Ok(mounts) => {
            println!("\nMounts:");
            for mount in mounts.iter() {
                println!("{} ---{}---> {} (available {} of {})",
                         mount.fs_mounted_from, mount.fs_type, mount.fs_mounted_on, mount.avail, mount.total);
            }
        }
        Err(x) => println!("\nMounts: error: {}", x)
    }

    match sys.networks() {
        Ok(netifs) => {
            println!("\nNetworks:");
            for netif in netifs.values() {
                println!("{} ({:?})", netif.name, netif.addrs);
            }
        }
        Err(x) => println!("\nNetworks: error: {}", x)
    }

    match sys.battery_life() {
        Ok(battery) =>
            print!("\nBattery: {}%, {}h{}m remaining",
                   battery.remaining_capacity*100.0,
                   battery.remaining_time.as_secs() / 3600,
                   battery.remaining_time.as_secs() % 60),
        Err(x) => print!("\nBattery: error: {}", x)
    }

    match sys.on_ac_power() {
        Ok(power) => println!(", AC power: {}", power),
        Err(x) => println!(", AC power: error: {}", x)
    }

    match sys.memory() {
        Ok(mem) => println!("\nMemory: {} used / {} ({} bytes) total ({:?})", mem.total - mem.free, mem.total, mem.total.as_usize(), mem.platform_memory),
        Err(x) => println!("\nMemory: error: {}", x)
    }

    match sys.load_average() {
        Ok(loadavg) => println!("\nLoad average: {} {} {}", loadavg.one, loadavg.five, loadavg.fifteen),
        Err(x) => println!("\nLoad average: error: {}", x)
    }

    match sys.uptime() {
        Ok(uptime) => println!("\nUptime: {:?}", uptime),
        Err(x) => println!("\nUptime: error: {}", x)
    }

    match sys.boot_time() {
        Ok(boot_time) => println!("\nBoot time: {}", boot_time),
        Err(x) => println!("\nBoot time: error: {}", x)
    }

    let cpu = sys.cpu_load_aggregate().unwrap();
    println!("\nMeasuring CPU load...");
    thread::sleep(Duration::from_secs(1));
    let cpu = cpu.done().unwrap();
    println!("CPU load: {}% user, {}% nice, {}% system, {}% intr, {}% idle ",
             cpu.user * 100.0, cpu.nice * 100.0, cpu.system * 100.0, cpu.interrupt * 100.0, cpu.idle * 100.0);

    match sys.cpu_temp() {
        Ok(cpu_temp) => println!("\nCPU temp: {}", cpu_temp),
        Err(x) => println!("\nCPU temp: {}", x)
    }
}
<commit_msg>Add example<commit_after>extern crate systemstat;

use std::thread;
use std::time::Duration;
use systemstat::{System, Platform};

fn main() {
    let sys = System::new();

    match sys.mounts() {
        Ok(mounts) => {
            println!("\nMounts:");
            for mount in mounts.iter() {
                println!("{} ---{}---> {} (available {} of {})",
                         mount.fs_mounted_from, mount.fs_type, mount.fs_mounted_on, mount.avail, mount.total);
            }
        }
        Err(x) => println!("\nMounts: error: {}", x)
    }

    match sys.block_device_statistics() {
        Ok(stats) => {
            for blkstats in stats.values() {
                println!("{}: {:?}", blkstats.name, blkstats);
            }
        }
        Err(x) => println!("Block statistics error: {}", x.to_string())
    }

    match sys.networks() {
        Ok(netifs) => {
            println!("\nNetworks:");
            for netif in netifs.values() {
                println!("{} ({:?})", netif.name, netif.addrs);
            }
        }
        Err(x) => println!("\nNetworks: error: {}", x)
    }

    match sys.battery_life() {
        Ok(battery) =>
            print!("\nBattery: {}%, {}h{}m remaining",
                   battery.remaining_capacity*100.0,
                   battery.remaining_time.as_secs() / 3600,
                   battery.remaining_time.as_secs() % 60),
        Err(x) => print!("\nBattery: error: {}", x)
    }

    match sys.on_ac_power() {
        Ok(power) => println!(", AC power: {}", power),
        Err(x) => println!(", AC power: error: {}", x)
    }

    match sys.memory() {
        Ok(mem) => println!("\nMemory: {} used / {} ({} bytes) total ({:?})", mem.total - mem.free, mem.total, mem.total.as_usize(), mem.platform_memory),
        Err(x) => println!("\nMemory: error: {}", x)
    }

    match sys.load_average() {
        Ok(loadavg) => println!("\nLoad average: {} {} {}", loadavg.one, loadavg.five, loadavg.fifteen),
        Err(x) => println!("\nLoad average: error: {}", x)
    }

    match sys.uptime() {
        Ok(uptime) => println!("\nUptime: {:?}", uptime),
        Err(x) => println!("\nUptime: error: {}", x)
    }

    match sys.boot_time() {
        Ok(boot_time) => println!("\nBoot time: {}", boot_time),
        Err(x) => println!("\nBoot time: error: {}", x)
    }

    let cpu = sys.cpu_load_aggregate().unwrap();
    println!("\nMeasuring CPU load...");
    thread::sleep(Duration::from_secs(1));
    let cpu = cpu.done().unwrap();
    println!("CPU load: {}% user, {}% nice, {}% system, {}% intr, {}% idle ",
             cpu.user * 100.0, cpu.nice * 100.0, cpu.system * 100.0, cpu.interrupt * 100.0, cpu.idle * 100.0);

    match sys.cpu_temp() {
        Ok(cpu_temp) => println!("\nCPU temp: {}", cpu_temp),
        Err(x) => println!("\nCPU temp: {}", x)
    }
}
<|endoftext|>


<commit_before>use nom::{be_u8,be_u16,IResult};

/// Hash algorithms, as defined in [RFC5246]
#[derive(Debug, PartialEq, Eq)]
pub struct HashAlgorithm(u8);

newtype_enum! {
impl display HashAlgorithm {
    None = 0,
    Md5 = 1,
    Sha1 = 2,
    Sha224 = 3,
    Sha256 = 4,
    Sha384 = 5,
    Sha512 = 6,
    Intrinsic = 8, // [RFC8422]
}
}

/// Signature algorithms, as defined in [RFC5246]
#[derive(Debug, PartialEq, Eq)]
pub struct SignAlgorithm(u8);

newtype_enum! {
impl display SignAlgorithm {
    Anonymous = 0,
    Rsa = 1,
    Dsa = 2,
    Ecdsa = 3,
    Ed25519 = 7, // [RFC8422]
    Ed448 = 8, // [RFC8422]
}
}

#[derive(PartialEq)]
pub struct SignatureAndHashAlgorithm {
    pub hash: HashAlgorithm,
    pub sign: SignAlgorithm,
}

/// Signature algorithms, as defined in [RFC8446] 4.2.3
#[derive(Debug, PartialEq, Eq)]
pub struct SignatureScheme(pub u16);

newtype_enum! {
impl display SignatureScheme {
    /* RSASSA-PKCS1-v1_5 algorithms */
    rsa_pkcs1_sha256 = 0x0401,
    rsa_pkcs1_sha384 = 0x0501,
    rsa_pkcs1_sha512 = 0x0601,

    /* ECDSA algorithms */
    ecdsa_secp256r1_sha256 = 0x0403,
    ecdsa_secp384r1_sha384 = 0x0503,
    ecdsa_secp521r1_sha512 = 0x0603,

    /* RSASSA-PSS algorithms with public key OID rsaEncryption */
    rsa_pss_rsae_sha256 = 0x0804,
    rsa_pss_rsae_sha384 = 0x0805,
    rsa_pss_rsae_sha512 = 0x0806,

    /* EdDSA algorithms */
    ed25519 = 0x0807,
    ed448 = 0x0808,

    /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */
    rsa_pss_pss_sha256 = 0x0809,
    rsa_pss_pss_sha384 = 0x080a,
    rsa_pss_pss_sha512 = 0x080b,

    /* Legacy algorithms */
    rsa_pkcs1_sha1 = 0x0201,
    ecdsa_sha1 = 0x0203,
}
}

impl SignatureScheme {
    pub fn is_reserved(&self) -> bool {
        self.0 >= 0xfe00 && self.0 < 0xff00
    }

    /// Get Hash algorithm (for tls <= 1.2) for legacy extension format
    pub fn hash_alg(&self) -> u8 {
        ((self.0 >> 8) & 0xff) as u8
    }

    /// Get Signature algorithm (for tls <= 1.2) for legacy extension format
    pub fn sign_alg(&self) -> u8 {
        (self.0 & 0xff) as u8
    }
}

/// DigitallySigned structure from [RFC2246] section 4.7
/// has no algorithm definition.
/// This should be deprecated in favor if
/// DigitallySigned structure from [RFC5246] section 4.7
#[derive(PartialEq)]
pub struct DigitallySigned<'a> {
    pub alg: Option<SignatureAndHashAlgorithm>,
    // pub alg: Option<u16>, // SignatureScheme
    pub data: &'a[u8],
}

named!(pub parse_digitally_signed_old<DigitallySigned>,
    map!(
        length_bytes!(be_u16),
        |d| { DigitallySigned{ alg:None, data:d } }
    )
);

named!(pub parse_digitally_signed<DigitallySigned>,
    do_parse!(
        h: be_u8 >>
        s: be_u8 >>
        d: length_bytes!(be_u16) >>
        ( DigitallySigned{
            alg: Some( SignatureAndHashAlgorithm{ hash:HashAlgorithm(h), sign:SignAlgorithm(s) } ),
            data: d,
        })
    )
);

/// Parse DigitallySigned object, depending on the `ext` parameter which should
/// be true if the TLS client has sent the `signature_algorithms` extension
pub fn parse_content_and_signature<'a,F,T:'a>(i: &'a[u8], fun: F, ext: bool) -> IResult<&'a[u8],(T,DigitallySigned)>
  where F: Fn(&'a[u8]) -> IResult<&[u8],T>
{
    if ext {
        pair!(i,fun,parse_digitally_signed)
    } else {
        pair!(i,fun,parse_digitally_signed_old)
    }
}
<commit_msg>Mark Hash and Sign fields as public<commit_after>use nom::{be_u8,be_u16,IResult};

/// Hash algorithms, as defined in [RFC5246]
#[derive(Debug, PartialEq, Eq)]
pub struct HashAlgorithm(pub u8);

newtype_enum! {
impl display HashAlgorithm {
    None = 0,
    Md5 = 1,
    Sha1 = 2,
    Sha224 = 3,
    Sha256 = 4,
    Sha384 = 5,
    Sha512 = 6,
    Intrinsic = 8, // [RFC8422]
}
}

/// Signature algorithms, as defined in [RFC5246]
#[derive(Debug, PartialEq, Eq)]
pub struct SignAlgorithm(pub u8);

newtype_enum! {
impl display SignAlgorithm {
    Anonymous = 0,
    Rsa = 1,
    Dsa = 2,
    Ecdsa = 3,
    Ed25519 = 7, // [RFC8422]
    Ed448 = 8, // [RFC8422]
}
}

#[derive(PartialEq)]
pub struct SignatureAndHashAlgorithm {
    pub hash: HashAlgorithm,
    pub sign: SignAlgorithm,
}

/// Signature algorithms, as defined in [RFC8446] 4.2.3
#[derive(Debug, PartialEq, Eq)]
pub struct SignatureScheme(pub u16);

newtype_enum! {
impl display SignatureScheme {
    /* RSASSA-PKCS1-v1_5 algorithms */
    rsa_pkcs1_sha256 = 0x0401,
    rsa_pkcs1_sha384 = 0x0501,
    rsa_pkcs1_sha512 = 0x0601,

    /* ECDSA algorithms */
    ecdsa_secp256r1_sha256 = 0x0403,
    ecdsa_secp384r1_sha384 = 0x0503,
    ecdsa_secp521r1_sha512 = 0x0603,

    /* RSASSA-PSS algorithms with public key OID rsaEncryption */
    rsa_pss_rsae_sha256 = 0x0804,
    rsa_pss_rsae_sha384 = 0x0805,
    rsa_pss_rsae_sha512 = 0x0806,

    /* EdDSA algorithms */
    ed25519 = 0x0807,
    ed448 = 0x0808,

    /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */
    rsa_pss_pss_sha256 = 0x0809,
    rsa_pss_pss_sha384 = 0x080a,
    rsa_pss_pss_sha512 = 0x080b,

    /* Legacy algorithms */
    rsa_pkcs1_sha1 = 0x0201,
    ecdsa_sha1 = 0x0203,
}
}

impl SignatureScheme {
    pub fn is_reserved(&self) -> bool {
        self.0 >= 0xfe00 && self.0 < 0xff00
    }

    /// Get Hash algorithm (for tls <= 1.2) for legacy extension format
    pub fn hash_alg(&self) -> u8 {
        ((self.0 >> 8) & 0xff) as u8
    }

    /// Get Signature algorithm (for tls <= 1.2) for legacy extension format
    pub fn sign_alg(&self) -> u8 {
        (self.0 & 0xff) as u8
    }
}

/// DigitallySigned structure from [RFC2246] section 4.7
/// has no algorithm definition.
/// This should be deprecated in favor if
/// DigitallySigned structure from [RFC5246] section 4.7
#[derive(PartialEq)]
pub struct DigitallySigned<'a> {
    pub alg: Option<SignatureAndHashAlgorithm>,
    // pub alg: Option<u16>, // SignatureScheme
    pub data: &'a[u8],
}

named!(pub parse_digitally_signed_old<DigitallySigned>,
    map!(
        length_bytes!(be_u16),
        |d| { DigitallySigned{ alg:None, data:d } }
    )
);

named!(pub parse_digitally_signed<DigitallySigned>,
    do_parse!(
        h: be_u8 >>
        s: be_u8 >>
        d: length_bytes!(be_u16) >>
        ( DigitallySigned{
            alg: Some( SignatureAndHashAlgorithm{ hash:HashAlgorithm(h), sign:SignAlgorithm(s) } ),
            data: d,
        })
    )
);

/// Parse DigitallySigned object, depending on the `ext` parameter which should
/// be true if the TLS client has sent the `signature_algorithms` extension
pub fn parse_content_and_signature<'a,F,T:'a>(i: &'a[u8], fun: F, ext: bool) -> IResult<&'a[u8],(T,DigitallySigned)>
  where F: Fn(&'a[u8]) -> IResult<&[u8],T>
{
    if ext {
        pair!(i,fun,parse_digitally_signed)
    } else {
        pair!(i,fun,parse_digitally_signed_old)
    }
}
<|endoftext|>