<commit_before>//! Storage Engine trait and several implementations
//!
//!

pub mod flatfile;

use self::flatfile::FlatFile;

use super::parse::ast::SqlType;

use std::mem;

use std::io;
use std::io::prelude::*;

use std::fs;
use std::fs::{OpenOptions, create_dir};

use std::convert::From;

use byteorder::Error;
use byteorder::{WriteBytesExt, ReadBytesExt, BigEndian};

use bincode::SizeLimit;
use bincode::rustc_serialize::{EncodingError,
    DecodingError, encode_into, decode_from};

/// constants
 const MAGIC_NUMBER: u64 = 0x6561742073686974; // secret
 const VERSION_NO: u8 = 1;

/// A database table
///
/// Through this type, you can retreive certain meta information about the
/// table (like column names, column types, storage engine, ...). It's `access`
/// method locks the table globally and returns a storage engine to access
/// the table data.
#[derive(Debug)]
pub enum DatabaseError {
    Io(io::Error),
    BinEn(EncodingError),
    BinDe(DecodingError),
    Byteorder(::byteorder::Error),
    WrongMagicNmbr,
    Engine, //cur not used
    LoadDataBase,
    RemoveColumn,
    AddColumn,
}

impl From<io::Error> for DatabaseError {
    fn from(err: io::Error) -> DatabaseError {
        DatabaseError::Io(err)
    }
}

impl  From<EncodingError> for DatabaseError {
    fn from(err: EncodingError) -> DatabaseError {
        DatabaseError::BinEn(err)
    }
}

impl From<DecodingError> for DatabaseError {
    fn from(err: DecodingError) -> DatabaseError {
        DatabaseError::BinDe(err)
    }
}

impl From< ::byteorder::Error> for DatabaseError {
    fn from(err: ::byteorder::Error) -> DatabaseError {
        DatabaseError::Byteorder(err)
    }
}

//---------------------------------------------------------------
// DataType
//---------------------------------------------------------------
/// A Enum for Datatypes (will be removed later)
#[repr(u8)]
#[derive(Clone,Copy,Debug,RustcDecodable, RustcEncodable)]
pub enum DataType { Integer = 1, Float = 2, }

impl DataType {
    pub fn value(&self) -> u8 {
       *self as u8
    }
}

//---------------------------------------------------------------
// Database
//---------------------------------------------------------------
#[derive(Debug)]
pub struct Database {
    name: String,
}

impl Database {
    /// Starts the process of creating a new Database
    /// Returns database or on fail DatabaseError
    pub fn create(name: &str) -> Result<Database, DatabaseError> {
        let d = Database{ name: name.to_string() };
        try!(d.save());
        info!("created new database {:?}",d);
        Ok(d)
    }

    /// Loads already existing Database
    /// returns DataBase Error when database does not exist else the loaded DB
    pub fn load(name: &str) -> Result<Database, DatabaseError> {
        if try!(fs::metadata(name)).is_dir() {
            info!("loaded Database {:?}", name.to_string());
            Ok(Database{ name: name.to_string() })
        } else {
            warn!("could not load database {:?}", name.to_string());
            return Err(DatabaseError::LoadDataBase)
        }
    }

    /// Creates a folder for the database
    fn save(&self) -> Result<(), DatabaseError> {
        info!("trying to create dir!");
        try!(create_dir(&self.name));
        info!("created dir");
        Ok(())
    }

    /// Creates a new table in the DB folder
    /// Returns with DatabaseError on fail else Table
    pub fn create_table(&self, name: &str, columns: Vec<Column>, engine_id: u8)
        -> Result<Table, DatabaseError>
    {

        let t = Table::new(&self, name, columns, engine_id);
        try!(t.save());
        info!("created new table {:?}", t);
        Ok(t)
    }

    /// calls load for table with the database path
    /// Returns with DatabaseError on fail else Table
    pub fn load_table(&self, name: &str) -> Result<Table, DatabaseError> {
        Table::load(&self, name)
    }
}

//---------------------------------------------------------------
// TableMetaData
//---------------------------------------------------------------

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct  TableMetaData {
    version_nmbr: u8,
    engine_id: u8,
    columns: Vec<Column>,
}

//---------------------------------------------------------------
// Table
//---------------------------------------------------------------

/// Table struct that contains the table information
#[derive(Debug)]
pub struct Table<'a> {
    database: &'a Database,
    name: String,
    meta_data: TableMetaData,
}

impl<'a> Table<'a> {
    /// Creates new table object
    /// Returns Table
    pub fn new<'b>(database: &'b Database, name: &str,
                   columns: Vec<Column>, engine_id: u8)
        -> Table<'b>
    {

        let meta_data = TableMetaData {
            version_nmbr: VERSION_NO,
            engine_id: engine_id,
            columns: columns,
        };
        info!("created meta data: {:?}", meta_data);

        Table {
            name: name.to_string(),
            database: database,
            meta_data: meta_data,
        }
    }

    /// Loads the table from the DB
    /// Returns with DatabaseError on fail else Table
    fn load<'b>(database: &'b Database, name: &str)
        -> Result<Table<'b>, DatabaseError>
    {
        // TODO: Read the .tbl file from disk and parse it

        let path_to_table = Table::get_path(&database.name, name, "tbl");
        info!("getting path and opening file: {:?}", path_to_table);
        let mut file = try!(OpenOptions::new()
            .read(true)
            .open(path_to_table));
        info!("reading file: {:?}", file);
        let n_size(mem::size_of_val(&MAGIC_NUMBER));
        let ma_nmbr = try!(file.read_uint::<BigEndian>(n_size));

        info!("checking magic number: {:?}",ma_nmbr);
        if ma_nmbr != MAGIC_NUMBER {
            println!("Magic Number not correct");
            return Err(DatabaseError::WrongMagicNmbr)
        }
        let meta_data: TableMetaData = try!(decode_from(&mut file, SizeLimit::Infinite));
        info!("getting meta data{:?}", meta_data);

        let table = Table::new(database, name, meta_data.columns, meta_data.engine_id);
        info!("returning table: {:?}", table);
        Ok(table)
    }

    /// Saves the table with a identification number in table file
    /// Returns DatabaseError on fail else Nothing
    pub fn save(&self) -> Result<(), DatabaseError> {
        // call for open file
        info!("opening file to write",);
        let mut file = try!(OpenOptions::new()
            .write(true)
            .create(true)
            .open(self.get_table_metadata_path()));
        info!("writing magic number in file: {:?}", file);
        try!(file.write_u64::<BigEndian>(MAGIC_NUMBER));//MAGIC_NUMBER
        info!("writing meta data in file: {:?}",file);
        try!(encode_into(&self.meta_data, &mut file,SizeLimit::Infinite));

        // debug message all okay
        info!("I Wrote my File");
        Ok(())
    }

    /// Returns columns of table as array
    pub fn columns(&self) -> &[Column] {
        &self.meta_data.columns
    }

    /// Adds a column to the tabel
    /// Returns name of Column or on fail DatabaseError
    pub fn add_column(&mut self, name: &str, sql_type: SqlType) -> Result<(), DatabaseError> {
        match self.meta_data.columns.iter().find(|x| x.name == name) {
            Some(_) => {
                warn!("Column {:?} already exists", name);
                return Err(DatabaseError::AddColumn)
            },
            None => {
                info!("Column {:?} was added", name);
            },
        }
        self.meta_data.columns.push(Column::create_new(name, sql_type));
        Ok(())
    }

    /// Removes a column from the table
    /// Returns name of Column or on fail DatabaseError
    pub fn remove_column(&mut self, name: &str) -> Result<(), DatabaseError> {
        let index = match self.meta_data.columns.iter().position(|x| x.name == name) {
            Some(x) => {
                info!("Column {:?} was removed" , self.name);
                x
            },
            None => {
                warn!("Column {:?} could not be found", self.name);
                return Err(DatabaseError::RemoveColumn)
            },
        };
        self.meta_data.columns.swap_remove(index);
        Ok(())
    }

    /// Creates an engine for Table
    /// Returns Box<Engine>
    pub fn create_engine(self) -> Box<Engine + 'a> {
        Box::new(FlatFile::new(self))
    }

    /// Returns the path for the metadata files
    fn get_table_metadata_path(&self) -> String {
        Self::get_path(&self.database.name, &self.name, "tbl")
    }

    /// Returns the path for the data files
    fn get_table_data_path(&self) -> String {
        Self::get_path(&self.database.name, &self.name, "dat")
    }

    /// Returns the path of the table
    fn get_path(database: &str, name: &str, ext: &str) -> String {
         format!("{}/{}.{}", database, name, ext)
    }
}

//---------------------------------------------------------------
// Column
//---------------------------------------------------------------

/// A table column. Has a name, a type, ...
#[derive(Debug,RustcDecodable, RustcEncodable,Clone)]
pub struct Column {
    pub name: String, //name of column
    pub sql_type: SqlType, //name of the data type that is contained in this column
}

impl Column {
    /// Creates a new column object
    /// Returns with Column
    pub fn create_new(name: &str, sql_type: SqlType) -> Column {
        Column {
            name: name.to_string(),
            sql_type: sql_type.clone()
        }
    }
}

//---------------------------------------------------------------
// Engine
//---------------------------------------------------------------

/// Storage Engine Interface.
///
/// A storage engine, like MyISAM and InnoDB, is responsible for reading and
/// writing data to disk, maintain and use indices, check for data corruption
/// and repair corrupt files.
///
/// Each table in a database may use a different storage engine.
pub trait Engine {
    fn create_table(&mut self) -> Result<(), DatabaseError>;
}

// # Some information for the `storage` working group:
//
// You work at the very bottom of the database: The thing that actually
// writes the data disk. Everything in this module is used only by the
// query execution module.
//
// The file layout may look like this:
// We have some `db_dir` where everything lives. In that directory, there are
// subdirectories for every database. In each of those subdirs is optionally
// a file `db.meta` that contains information about the database (such as
// permissions). The tables of each database are saved in *.tbl files that
// live inside the database directory.
//
// Your task is to provide types and method to:
// - read a specific table from a specific
//   database from file
// - create a new table in a database
// - query meta information about a table (columns for example)
// - lock a table for reading/writing it's data through a storage engine
//
// The other main task is to:
// - specify the storage engine interface
// - implement a simple storage engine (heap/flatfiles)
//
<commit_msg>Revert one change<commit_after>//! Storage Engine trait and several implementations
//!
//!

pub mod flatfile;

use self::flatfile::FlatFile;

use super::parse::ast::SqlType;

use std::mem;

use std::io;
use std::io::prelude::*;

use std::fs;
use std::fs::{OpenOptions, create_dir};

use std::convert::From;

use byteorder::Error;
use byteorder::{WriteBytesExt, ReadBytesExt, BigEndian};

use bincode::SizeLimit;
use bincode::rustc_serialize::{EncodingError,
    DecodingError, encode_into, decode_from};

/// constants
 const MAGIC_NUMBER: u64 = 0x6561742073686974; // secret
 const VERSION_NO: u8 = 1;

/// A database table
///
/// Through this type, you can retreive certain meta information about the
/// table (like column names, column types, storage engine, ...). It's `access`
/// method locks the table globally and returns a storage engine to access
/// the table data.
#[derive(Debug)]
pub enum DatabaseError {
    Io(io::Error),
    BinEn(EncodingError),
    BinDe(DecodingError),
    Byteorder(::byteorder::Error),
    WrongMagicNmbr,
    Engine, //cur not used
    LoadDataBase,
    RemoveColumn,
    AddColumn,
}

impl From<io::Error> for DatabaseError {
    fn from(err: io::Error) -> DatabaseError {
        DatabaseError::Io(err)
    }
}

impl  From<EncodingError> for DatabaseError {
    fn from(err: EncodingError) -> DatabaseError {
        DatabaseError::BinEn(err)
    }
}

impl From<DecodingError> for DatabaseError {
    fn from(err: DecodingError) -> DatabaseError {
        DatabaseError::BinDe(err)
    }
}

impl From< ::byteorder::Error> for DatabaseError {
    fn from(err: ::byteorder::Error) -> DatabaseError {
        DatabaseError::Byteorder(err)
    }
}

//---------------------------------------------------------------
// DataType
//---------------------------------------------------------------
/// A Enum for Datatypes (will be removed later)
#[repr(u8)]
#[derive(Clone,Copy,Debug,RustcDecodable, RustcEncodable)]
pub enum DataType { Integer = 1, Float = 2, }

impl DataType {
    pub fn value(&self) -> u8 {
       *self as u8
    }
}

//---------------------------------------------------------------
// Database
//---------------------------------------------------------------
#[derive(Debug)]
pub struct Database {
    name: String,
}

impl Database {
    /// Starts the process of creating a new Database
    /// Returns database or on fail DatabaseError
    pub fn create(name: &str) -> Result<Database, DatabaseError> {
        let d = Database{ name: name.to_string() };
        try!(d.save());
        info!("created new database {:?}",d);
        Ok(d)
    }

    /// Loads already existing Database
    /// returns DataBase Error when database does not exist else the loaded DB
    pub fn load(name: &str) -> Result<Database, DatabaseError> {
        if try!(fs::metadata(name)).is_dir() {
            info!("loaded Database {:?}", name.to_string());
            Ok(Database{ name: name.to_string() })
        } else {
            warn!("could not load database {:?}", name.to_string());
            return Err(DatabaseError::LoadDataBase)
        }
    }

    /// Creates a folder for the database
    fn save(&self) -> Result<(), DatabaseError> {
        info!("trying to create dir!");
        try!(create_dir(&self.name));
        info!("created dir");
        Ok(())
    }

    /// Creates a new table in the DB folder
    /// Returns with DatabaseError on fail else Table
    pub fn create_table(&self, name: &str, columns: Vec<Column>, engine_id: u8)
        -> Result<Table, DatabaseError>
    {

        let t = Table::new(&self, name, columns, engine_id);
        try!(t.save());
        info!("created new table {:?}", t);
        Ok(t)
    }

    /// calls load for table with the database path
    /// Returns with DatabaseError on fail else Table
    pub fn load_table(&self, name: &str) -> Result<Table, DatabaseError> {
        Table::load(&self, name)
    }
}

//---------------------------------------------------------------
// TableMetaData
//---------------------------------------------------------------

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct  TableMetaData {
    version_nmbr: u8,
    engine_id: u8,
    columns: Vec<Column>,
}

//---------------------------------------------------------------
// Table
//---------------------------------------------------------------

/// Table struct that contains the table information
#[derive(Debug)]
pub struct Table<'a> {
    database: &'a Database,
    name: String,
    meta_data: TableMetaData,
}

impl<'a> Table<'a> {
    /// Creates new table object
    /// Returns Table
    pub fn new<'b>(database: &'b Database, name: &str,
                   columns: Vec<Column>, engine_id: u8)
        -> Table<'b>
    {

        let meta_data = TableMetaData {
            version_nmbr: VERSION_NO,
            engine_id: engine_id,
            columns: columns,
        };
        info!("created meta data: {:?}", meta_data);

        Table {
            name: name.to_string(),
            database: database,
            meta_data: meta_data,
        }
    }

    /// Loads the table from the DB
    /// Returns with DatabaseError on fail else Table
    fn load<'b>(database: &'b Database, name: &str)
        -> Result<Table<'b>, DatabaseError>
    {
        // TODO: Read the .tbl file from disk and parse it

        let path_to_table = Table::get_path(&database.name, name, "tbl");
        info!("getting path and opening file: {:?}", path_to_table);
        let mut file = try!(OpenOptions::new()
            .read(true)
            .open(path_to_table));
        info!("reading file: {:?}", file);
        let ma_nmbr = try!(file.read_uint::<BigEndian>(mem::size_of_val(&MAGIC_NUMBER)));

        info!("checking magic number: {:?}",ma_nmbr);
        if ma_nmbr != MAGIC_NUMBER {
            println!("Magic Number not correct");
            return Err(DatabaseError::WrongMagicNmbr)
        }
        let meta_data: TableMetaData = try!(decode_from(&mut file, SizeLimit::Infinite));
        info!("getting meta data{:?}", meta_data);

        let table = Table::new(database, name, meta_data.columns, meta_data.engine_id);
        info!("returning table: {:?}", table);
        Ok(table)
    }

    /// Saves the table with a identification number in table file
    /// Returns DatabaseError on fail else Nothing
    pub fn save(&self) -> Result<(), DatabaseError> {
        // call for open file
        info!("opening file to write",);
        let mut file = try!(OpenOptions::new()
            .write(true)
            .create(true)
            .open(self.get_table_metadata_path()));
        info!("writing magic number in file: {:?}", file);
        try!(file.write_u64::<BigEndian>(MAGIC_NUMBER));//MAGIC_NUMBER
        info!("writing meta data in file: {:?}",file);
        try!(encode_into(&self.meta_data, &mut file,SizeLimit::Infinite));

        // debug message all okay
        info!("I Wrote my File");
        Ok(())
    }

    /// Returns columns of table as array
    pub fn columns(&self) -> &[Column] {
        &self.meta_data.columns
    }

    /// Adds a column to the tabel
    /// Returns name of Column or on fail DatabaseError
    pub fn add_column(&mut self, name: &str, sql_type: SqlType) -> Result<(), DatabaseError> {
        match self.meta_data.columns.iter().find(|x| x.name == name) {
            Some(_) => {
                warn!("Column {:?} already exists", name);
                return Err(DatabaseError::AddColumn)
            },
            None => {
                info!("Column {:?} was added", name);
            },
        }
        self.meta_data.columns.push(Column::create_new(name, sql_type));
        Ok(())
    }

    /// Removes a column from the table
    /// Returns name of Column or on fail DatabaseError
    pub fn remove_column(&mut self, name: &str) -> Result<(), DatabaseError> {
        let index = match self.meta_data.columns.iter().position(|x| x.name == name) {
            Some(x) => {
                info!("Column {:?} was removed" , self.name);
                x
            },
            None => {
                warn!("Column {:?} could not be found", self.name);
                return Err(DatabaseError::RemoveColumn)
            },
        };
        self.meta_data.columns.swap_remove(index);
        Ok(())
    }

    /// Creates an engine for Table
    /// Returns Box<Engine>
    pub fn create_engine(self) -> Box<Engine + 'a> {
        Box::new(FlatFile::new(self))
    }

    /// Returns the path for the metadata files
    fn get_table_metadata_path(&self) -> String {
        Self::get_path(&self.database.name, &self.name, "tbl")
    }

    /// Returns the path for the data files
    fn get_table_data_path(&self) -> String {
        Self::get_path(&self.database.name, &self.name, "dat")
    }

    /// Returns the path of the table
    fn get_path(database: &str, name: &str, ext: &str) -> String {
         format!("{}/{}.{}", database, name, ext)
    }
}

//---------------------------------------------------------------
// Column
//---------------------------------------------------------------

/// A table column. Has a name, a type, ...
#[derive(Debug,RustcDecodable, RustcEncodable,Clone)]
pub struct Column {
    pub name: String, //name of column
    pub sql_type: SqlType, //name of the data type that is contained in this column
}

impl Column {
    /// Creates a new column object
    /// Returns with Column
    pub fn create_new(name: &str, sql_type: SqlType) -> Column {
        Column {
            name: name.to_string(),
            sql_type: sql_type.clone()
        }
    }
}

//---------------------------------------------------------------
// Engine
//---------------------------------------------------------------

/// Storage Engine Interface.
///
/// A storage engine, like MyISAM and InnoDB, is responsible for reading and
/// writing data to disk, maintain and use indices, check for data corruption
/// and repair corrupt files.
///
/// Each table in a database may use a different storage engine.
pub trait Engine {
    fn create_table(&mut self) -> Result<(), DatabaseError>;
}

// # Some information for the `storage` working group:
//
// You work at the very bottom of the database: The thing that actually
// writes the data disk. Everything in this module is used only by the
// query execution module.
//
// The file layout may look like this:
// We have some `db_dir` where everything lives. In that directory, there are
// subdirectories for every database. In each of those subdirs is optionally
// a file `db.meta` that contains information about the database (such as
// permissions). The tables of each database are saved in *.tbl files that
// live inside the database directory.
//
// Your task is to provide types and method to:
// - read a specific table from a specific
//   database from file
// - create a new table in a database
// - query meta information about a table (columns for example)
// - lock a table for reading/writing it's data through a storage engine
//
// The other main task is to:
// - specify the storage engine interface
// - implement a simple storage engine (heap/flatfiles)
//
<|endoftext|>


<commit_before>// Take a look at the license at the top of the repository in the LICENSE file.

use crate::DiskType;

use crate::sys::disk::{new_disk, Disk};
use crate::sys::processor::{self, Processor, Query};

use std::ffi::OsStr;
use std::mem::{size_of, zeroed};

use winapi::{ctypes::c_void, um::winbase::DRIVE_REMOVABLE};

use winapi::shared::minwindef::{DWORD, MAX_PATH, TRUE};
use winapi::um::fileapi::{
    CreateFileW, GetDriveTypeW, GetLogicalDrives, GetVolumeInformationW, OPEN_EXISTING,
};
use winapi::um::handleapi::CloseHandle;
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::ioapiset::DeviceIoControl;
use winapi::um::sysinfoapi::{GetSystemInfo, SYSTEM_INFO};
use winapi::um::winbase::DRIVE_FIXED;
use winapi::um::winioctl::{
    DEVICE_TRIM_DESCRIPTOR, IOCTL_DISK_GET_PARTITION_INFO_EX, IOCTL_STORAGE_QUERY_PROPERTY,
    PARTITION_INFORMATION_EX, STORAGE_PROPERTY_QUERY,
};
use winapi::um::winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE, HANDLE};

pub(crate) struct KeyHandler {
    pub unique_id: String,
}

impl KeyHandler {
    pub fn new(unique_id: String) -> KeyHandler {
        KeyHandler { unique_id }
    }
}

pub(crate) fn init_processors() -> (Vec<Processor>, String, String) {
    unsafe {
        let mut sys_info: SYSTEM_INFO = zeroed();
        GetSystemInfo(&mut sys_info);
        let (vendor_id, brand) = processor::get_vendor_id_and_brand(&sys_info);
        let frequencies = processor::get_frequencies(sys_info.dwNumberOfProcessors as usize);
        let mut ret = Vec::with_capacity(sys_info.dwNumberOfProcessors as usize + 1);
        for nb in 0..sys_info.dwNumberOfProcessors {
            ret.push(Processor::new_with_values(
                &format!("CPU {}", nb + 1),
                vendor_id.clone(),
                brand.clone(),
                frequencies[nb as usize],
            ));
        }
        (ret, vendor_id, brand)
    }
}

pub unsafe fn open_drive(drive_name: &[u16], open_rights: DWORD) -> HANDLE {
    CreateFileW(
        drive_name.as_ptr(),
        open_rights,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        std::ptr::null_mut(),
        OPEN_EXISTING,
        0,
        std::ptr::null_mut(),
    )
}

pub unsafe fn get_drive_size(handle: HANDLE) -> u64 {
    let mut pdg: PARTITION_INFORMATION_EX = std::mem::zeroed();
    let mut junk = 0;
    let result = DeviceIoControl(
        handle,
        IOCTL_DISK_GET_PARTITION_INFO_EX,
        std::ptr::null_mut(),
        0,
        &mut pdg as *mut PARTITION_INFORMATION_EX as *mut c_void,
        size_of::<PARTITION_INFORMATION_EX>() as DWORD,
        &mut junk,
        std::ptr::null_mut(),
    );
    if result == TRUE {
        *pdg.PartitionLength.QuadPart() as u64
    } else {
        0
    }
}

pub unsafe fn get_disks() -> Vec<Disk> {
    let drives = GetLogicalDrives();
    if drives == 0 {
        return Vec::new();
    }

    #[cfg(feature = "multithread")]
    use rayon::iter::ParallelIterator;

    crate::utils::into_iter(0..size_of::<DWORD>() * 8)
        .filter_map(|x| {
            if (drives >> x) & 1 == 0 {
                return None;
            }
            let mount_point = [b'A' as u16 + x as u16, b':' as u16, b'\\' as u16, 0];

            let drive_type = GetDriveTypeW(mount_point.as_ptr());

            let is_removable = drive_type == DRIVE_REMOVABLE;

            if drive_type != DRIVE_FIXED && drive_type != DRIVE_REMOVABLE {
                return None;
            }
            let mut name = [0u16; MAX_PATH + 1];
            let mut file_system = [0u16; 32];
            if GetVolumeInformationW(
                mount_point.as_ptr(),
                name.as_mut_ptr(),
                name.len() as DWORD,
                std::ptr::null_mut(),
                std::ptr::null_mut(),
                std::ptr::null_mut(),
                file_system.as_mut_ptr(),
                file_system.len() as DWORD,
            ) == 0
            {
                return None;
            }
            let mut pos = 0;
            for x in name.iter() {
                if *x == 0 {
                    break;
                }
                pos += 1;
            }
            let name = String::from_utf16_lossy(&name[..pos]);
            let name = OsStr::new(&name);

            pos = 0;
            for x in file_system.iter() {
                if *x == 0 {
                    break;
                }
                pos += 1;
            }
            let file_system: Vec<u8> = file_system[..pos].iter().map(|x| *x as u8).collect();

            let drive_name = [
                b'\\' as u16,
                b'\\' as u16,
                b'.' as u16,
                b'\\' as u16,
                b'A' as u16 + x as u16,
                b':' as u16,
                0,
            ];
            let handle = open_drive(&drive_name, 0);
            if handle == INVALID_HANDLE_VALUE {
                CloseHandle(handle);
                return new_disk(
                    name,
                    &mount_point,
                    &file_system,
                    DiskType::Unknown(-1),
                    0,
                    is_removable,
                );
            }
            let disk_size = get_drive_size(handle);
            /*let mut spq_trim: STORAGE_PROPERTY_QUERY = std::mem::zeroed();
            spq_trim.PropertyId = StorageDeviceTrimProperty;
            spq_trim.QueryType = PropertyStandardQuery;
            let mut dtd: DEVICE_TRIM_DESCRIPTOR = std::mem::zeroed();*/
            let mut spq_trim = STORAGE_PROPERTY_QUERY {
                PropertyId: 8,
                QueryType: 0,
                AdditionalParameters: [0],
            };
            let mut dtd: DEVICE_TRIM_DESCRIPTOR = std::mem::zeroed();

            let mut dw_size = 0;
            if DeviceIoControl(
                handle,
                IOCTL_STORAGE_QUERY_PROPERTY,
                &mut spq_trim as *mut STORAGE_PROPERTY_QUERY as *mut c_void,
                size_of::<STORAGE_PROPERTY_QUERY>() as DWORD,
                &mut dtd as *mut DEVICE_TRIM_DESCRIPTOR as *mut c_void,
                size_of::<DEVICE_TRIM_DESCRIPTOR>() as DWORD,
                &mut dw_size,
                std::ptr::null_mut(),
            ) == 0
                || dw_size != size_of::<DEVICE_TRIM_DESCRIPTOR>() as DWORD
            {
                CloseHandle(handle);
                return new_disk(
                    name,
                    &mount_point,
                    &file_system,
                    DiskType::Unknown(-1),
                    disk_size,
                    is_removable,
                );
            }
            let is_ssd = dtd.TrimEnabled != 0;
            CloseHandle(handle);
            new_disk(
                name,
                &mount_point,
                &file_system,
                if is_ssd { DiskType::SSD } else { DiskType::HDD },
                disk_size,
                is_removable,
            )
        })
        .collect::<Vec<_>>()
}

pub(crate) fn add_english_counter(
    s: String,
    query: &mut Query,
    keys: &mut Option<KeyHandler>,
    counter_name: String,
) {
    let mut full = s.encode_utf16().collect::<Vec<_>>();
    full.push(0);
    if query.add_english_counter(&counter_name, full) {
        *keys = Some(KeyHandler::new(counter_name));
    }
}
<commit_msg>Fix new clippy lint<commit_after>// Take a look at the license at the top of the repository in the LICENSE file.

use crate::DiskType;

use crate::sys::disk::{new_disk, Disk};
use crate::sys::processor::{self, Processor, Query};

use std::ffi::OsStr;
use std::mem::{size_of, zeroed};

use winapi::{ctypes::c_void, um::winbase::DRIVE_REMOVABLE};

use winapi::shared::minwindef::{DWORD, MAX_PATH, TRUE};
use winapi::um::fileapi::{
    CreateFileW, GetDriveTypeW, GetLogicalDrives, GetVolumeInformationW, OPEN_EXISTING,
};
use winapi::um::handleapi::CloseHandle;
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::ioapiset::DeviceIoControl;
use winapi::um::sysinfoapi::{GetSystemInfo, SYSTEM_INFO};
use winapi::um::winbase::DRIVE_FIXED;
use winapi::um::winioctl::{
    DEVICE_TRIM_DESCRIPTOR, IOCTL_DISK_GET_PARTITION_INFO_EX, IOCTL_STORAGE_QUERY_PROPERTY,
    PARTITION_INFORMATION_EX, STORAGE_PROPERTY_QUERY,
};
use winapi::um::winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE, HANDLE};

pub(crate) struct KeyHandler {
    pub unique_id: String,
}

impl KeyHandler {
    pub fn new(unique_id: String) -> KeyHandler {
        KeyHandler { unique_id }
    }
}

pub(crate) fn init_processors() -> (Vec<Processor>, String, String) {
    unsafe {
        let mut sys_info: SYSTEM_INFO = zeroed();
        GetSystemInfo(&mut sys_info);
        let (vendor_id, brand) = processor::get_vendor_id_and_brand(&sys_info);
        let frequencies = processor::get_frequencies(sys_info.dwNumberOfProcessors as usize);
        let mut ret = Vec::with_capacity(sys_info.dwNumberOfProcessors as usize + 1);
        for nb in 0..sys_info.dwNumberOfProcessors {
            ret.push(Processor::new_with_values(
                &format!("CPU {}", nb + 1),
                vendor_id.clone(),
                brand.clone(),
                frequencies[nb as usize],
            ));
        }
        (ret, vendor_id, brand)
    }
}

pub unsafe fn open_drive(drive_name: &[u16], open_rights: DWORD) -> HANDLE {
    CreateFileW(
        drive_name.as_ptr(),
        open_rights,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        std::ptr::null_mut(),
        OPEN_EXISTING,
        0,
        std::ptr::null_mut(),
    )
}

pub unsafe fn get_drive_size(handle: HANDLE) -> u64 {
    let mut pdg: PARTITION_INFORMATION_EX = std::mem::zeroed();
    let mut junk = 0;
    let result = DeviceIoControl(
        handle,
        IOCTL_DISK_GET_PARTITION_INFO_EX,
        std::ptr::null_mut(),
        0,
        &mut pdg as *mut PARTITION_INFORMATION_EX as *mut c_void,
        size_of::<PARTITION_INFORMATION_EX>() as DWORD,
        &mut junk,
        std::ptr::null_mut(),
    );
    if result == TRUE {
        *pdg.PartitionLength.QuadPart() as u64
    } else {
        0
    }
}

pub unsafe fn get_disks() -> Vec<Disk> {
    let drives = GetLogicalDrives();
    if drives == 0 {
        return Vec::new();
    }

    #[cfg(feature = "multithread")]
    use rayon::iter::ParallelIterator;

    crate::utils::into_iter(0..DWORD::BITS)
        .filter_map(|x| {
            if (drives >> x) & 1 == 0 {
                return None;
            }
            let mount_point = [b'A' as u16 + x as u16, b':' as u16, b'\\' as u16, 0];

            let drive_type = GetDriveTypeW(mount_point.as_ptr());

            let is_removable = drive_type == DRIVE_REMOVABLE;

            if drive_type != DRIVE_FIXED && drive_type != DRIVE_REMOVABLE {
                return None;
            }
            let mut name = [0u16; MAX_PATH + 1];
            let mut file_system = [0u16; 32];
            if GetVolumeInformationW(
                mount_point.as_ptr(),
                name.as_mut_ptr(),
                name.len() as DWORD,
                std::ptr::null_mut(),
                std::ptr::null_mut(),
                std::ptr::null_mut(),
                file_system.as_mut_ptr(),
                file_system.len() as DWORD,
            ) == 0
            {
                return None;
            }
            let mut pos = 0;
            for x in name.iter() {
                if *x == 0 {
                    break;
                }
                pos += 1;
            }
            let name = String::from_utf16_lossy(&name[..pos]);
            let name = OsStr::new(&name);

            pos = 0;
            for x in file_system.iter() {
                if *x == 0 {
                    break;
                }
                pos += 1;
            }
            let file_system: Vec<u8> = file_system[..pos].iter().map(|x| *x as u8).collect();

            let drive_name = [
                b'\\' as u16,
                b'\\' as u16,
                b'.' as u16,
                b'\\' as u16,
                b'A' as u16 + x as u16,
                b':' as u16,
                0,
            ];
            let handle = open_drive(&drive_name, 0);
            if handle == INVALID_HANDLE_VALUE {
                CloseHandle(handle);
                return new_disk(
                    name,
                    &mount_point,
                    &file_system,
                    DiskType::Unknown(-1),
                    0,
                    is_removable,
                );
            }
            let disk_size = get_drive_size(handle);
            /*let mut spq_trim: STORAGE_PROPERTY_QUERY = std::mem::zeroed();
            spq_trim.PropertyId = StorageDeviceTrimProperty;
            spq_trim.QueryType = PropertyStandardQuery;
            let mut dtd: DEVICE_TRIM_DESCRIPTOR = std::mem::zeroed();*/
            let mut spq_trim = STORAGE_PROPERTY_QUERY {
                PropertyId: 8,
                QueryType: 0,
                AdditionalParameters: [0],
            };
            let mut dtd: DEVICE_TRIM_DESCRIPTOR = std::mem::zeroed();

            let mut dw_size = 0;
            if DeviceIoControl(
                handle,
                IOCTL_STORAGE_QUERY_PROPERTY,
                &mut spq_trim as *mut STORAGE_PROPERTY_QUERY as *mut c_void,
                size_of::<STORAGE_PROPERTY_QUERY>() as DWORD,
                &mut dtd as *mut DEVICE_TRIM_DESCRIPTOR as *mut c_void,
                size_of::<DEVICE_TRIM_DESCRIPTOR>() as DWORD,
                &mut dw_size,
                std::ptr::null_mut(),
            ) == 0
                || dw_size != size_of::<DEVICE_TRIM_DESCRIPTOR>() as DWORD
            {
                CloseHandle(handle);
                return new_disk(
                    name,
                    &mount_point,
                    &file_system,
                    DiskType::Unknown(-1),
                    disk_size,
                    is_removable,
                );
            }
            let is_ssd = dtd.TrimEnabled != 0;
            CloseHandle(handle);
            new_disk(
                name,
                &mount_point,
                &file_system,
                if is_ssd { DiskType::SSD } else { DiskType::HDD },
                disk_size,
                is_removable,
            )
        })
        .collect::<Vec<_>>()
}

pub(crate) fn add_english_counter(
    s: String,
    query: &mut Query,
    keys: &mut Option<KeyHandler>,
    counter_name: String,
) {
    let mut full = s.encode_utf16().collect::<Vec<_>>();
    full.push(0);
    if query.add_english_counter(&counter_name, full) {
        *keys = Some(KeyHandler::new(counter_name));
    }
}
<|endoftext|>


<commit_before>use super::*;

impl Editor {
    /// Get the position of the next char
    pub fn next_pos(&self) -> (usize, usize) {
        // TODO: Add numerals
        if self.x() == self.text[self.y()].len() {
            if self.y() < self.text.len() - 1 {
                (0, self.y() + 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() + 1, self.y())
        }
    }

    /// Get the position of previous char
    pub fn previous_pos(&self) -> (usize, usize) {
        if self.x() == 0 {
            if self.y() > 0 {
                (self.text[self.y() - 1].len(), self.y() - 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() - 1, self.y())
        }
    }

    /// Goto the next char
    pub fn goto_next(&mut self) {
        let (x, y) = self.next_pos();
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }
    /// Goto the previous char
    pub fn goto_previous(&mut self) {
        let (x, y) = self.previous_pos();
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

    /// Get the position of the right char
    pub fn right_pos(&self, n: usize) -> (usize, usize) {
        let x = self.x() + n;

        if x > self.text[self.y()].len() {
            (self.text[self.y()].len(), self.y())
        } else {
            (x, self.y())
        }
    }
    /// Goto the right char
    pub fn goto_right(&mut self, n: usize) {
        self.cursor_mut().x = self.right_pos(n).0;
    }

    /// Get the position of the left char
    pub fn left_pos(&self, n: usize) -> (usize, usize) {
        if n <= self.x() {
            (self.x() - n, self.y())
        } else {
            (0, self.y())
        }

    }
    /// Goto the left char
    pub fn goto_left(&mut self, n: usize) {
        self.cursor_mut().x = self.left_pos(n).0;
    }

    /// Get the position of the char above the cursor
    pub fn up_pos(&self, n: usize) -> (usize, usize) {
        if n <= self.y() {
            (self.cursor().x, self.y() - n)
        } else {
            (self.cursor().x, 0)
        }
    }
    /// Go a char up
    pub fn goto_up(&mut self, n: usize) {
        let (x, y) = self.up_pos(n);
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

    /// Get the position under the char
    pub fn down_pos(&self, n: usize) -> (usize, usize) {
        let y = self.y() + n;

        if y >= self.text.len() {
            (self.cursor().x, self.text.len() - 1)
        } else {
            (self.cursor().x, y)
        }
    }

    /// Go down
    pub fn goto_down(&mut self, n: usize) {
        let (x, y) = self.down_pos(n);
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

}
<commit_msg>Refactor into using a .goto method<commit_after>use super::*;

impl Editor {
    /// Goto a given position
    pub fn goto(&mut self, (x, y): (usize, usize)) {
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

    /// Get the position of the next char
    pub fn next_pos(&self) -> (usize, usize) {
        // TODO: Add numerals
        if self.x() == self.text[self.y()].len() {
            if self.y() < self.text.len() - 1 {
                (0, self.y() + 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() + 1, self.y())
        }
    }

    /// Get the position of previous char
    pub fn previous_pos(&self) -> (usize, usize) {
        if self.x() == 0 {
            if self.y() > 0 {
                (self.text[self.y() - 1].len(), self.y() - 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() - 1, self.y())
        }
    }

    /// Goto the next char
    pub fn goto_next(&mut self) {
        let p = self.next_pos();
        self.goto(p);
    }
    /// Goto the previous char
    pub fn goto_previous(&mut self) {
        let p = self.previous_pos();
        self.goto(p);
    }

    /// Get the position of the right char
    pub fn right_pos(&self, n: usize) -> (usize, usize) {
        let x = self.x() + n;

        if x > self.text[self.y()].len() {
            (self.text[self.y()].len(), self.y())
        } else {
            (x, self.y())
        }
    }
    /// Goto the right char
    pub fn goto_right(&mut self, n: usize) {
        self.cursor_mut().x = self.right_pos(n).0;
    }

    /// Get the position of the left char
    pub fn left_pos(&self, n: usize) -> (usize, usize) {
        if n <= self.x() {
            (self.x() - n, self.y())
        } else {
            (0, self.y())
        }

    }
    /// Goto the left char
    pub fn goto_left(&mut self, n: usize) {
        self.cursor_mut().x = self.left_pos(n).0;
    }

    /// Get the position of the char above the cursor
    pub fn up_pos(&self, n: usize) -> (usize, usize) {
        if n <= self.y() {
            (self.cursor().x, self.y() - n)
        } else {
            (self.cursor().x, 0)
        }
    }
    /// Go a char up
    pub fn goto_up(&mut self, n: usize) {
        let p = self.up_pos(n);
        self.goto(p);
    }

    /// Get the position under the char
    pub fn down_pos(&self, n: usize) -> (usize, usize) {
        let y = self.y() + n;

        if y >= self.text.len() {
            (self.cursor().x, self.text.len() - 1)
        } else {
            (self.cursor().x, y)
        }
    }

    /// Go down
    pub fn goto_down(&mut self, n: usize) {
        let p = self.down_pos(n);
        self.goto(p);
    }

}
<|endoftext|>


<commit_before>// Copyright 2015 The Gfx-rs Developers.
//
// 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.

#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

use gfx::traits::FactoryExt;
use gfx::Device;
use glutin::GlContext;

pub type ColorFormat = gfx::format::Rgba8;
pub type DepthFormat = gfx::format::DepthStencil;

gfx_defines!{
    vertex Vertex {
        pos: [f32; 2] = "a_Pos",
        color: [f32; 3] = "a_Color",
    }

    pipeline pipe {
        vbuf: gfx::VertexBuffer<Vertex> = (),
        out: gfx::RenderTarget<ColorFormat> = "Target0",
    }
}

const QUAD: [Vertex; 4] = [
    Vertex { pos: [ -0.5,  0.5 ], color: [0.0, 0.0, 0.0] },
    Vertex { pos: [ -0.5, -0.5 ], color: [0.0, 0.0, 0.0] },
    Vertex { pos: [  0.5, -0.5 ], color: [1.0, 1.0, 1.0] },
    Vertex { pos: [  0.5,  0.5 ], color: [1.0, 1.0, 1.0] }
];

const CLEAR_COLOR: [f32; 4] = [0.5, 0.5, 0.5, 1.0];

pub fn main() {
    let mut events_loop = glutin::EventsLoop::new();
    let window_builder = glutin::WindowBuilder::new()
        .with_title("Gamma example".to_string())
        .with_dimensions(1024, 768);
    let context = glutin::ContextBuilder::new()
        .with_vsync(true);
    let (window, mut device, mut factory, main_color, mut main_depth) =
        gfx_window_glutin::init::<ColorFormat, DepthFormat>(window_builder, context, &events_loop);
    let mut encoder: gfx::Encoder<_, _> = factory.create_command_buffer().into();
    let pso = factory.create_pipeline_simple(
        include_bytes!("shader/quad_150.glslv"),
        include_bytes!("shader/quad_150.glslf"),
        pipe::new()
    ).unwrap();
    let (vertex_buffer, slice) = factory.create_vertex_buffer_with_slice(&QUAD, &[0u16, 1, 2, 2, 3, 0] as &[u16]);
    let mut data = pipe::Data {
        vbuf: vertex_buffer,
        out: main_color
    };

    let mut running = true;
    while running {
        events_loop.poll_events(|event| {
            if let glutin::Event::WindowEvent { event, .. } = event {
                match event {
                    glutin::WindowEvent::KeyboardInput {
                        input: glutin::KeyboardInput {
                            virtual_keycode: Some(glutin::VirtualKeyCode::Escape),
                            .. },
                        ..
                    } | glutin::WindowEvent::Closed => running = false,
                    glutin::WindowEvent::Resized(width, height) => {
                        window.resize(width, height);
                        gfx_window_glutin::update_views(&window, &mut data.out, &mut main_depth);
                    },
                    _ => (),
                }
            }
        });

        // draw a frame
        encoder.clear(&data.out, CLEAR_COLOR);
        encoder.draw(&slice, &pso, &data);
        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}
<commit_msg>[ll] Update gamma example<commit_after>// Copyright 2015 The Gfx-rs Developers.
//
// 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.

#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

use gfx::format::Formatted;
use gfx::traits::FactoryExt;
use gfx::{Adapter, Device, Factory, FrameSync, GraphicsPoolExt,
          Surface, SwapChain, SwapChainExt, WindowExt};
use glutin::GlContext;

pub type ColorFormat = gfx::format::Rgba8;
pub type DepthFormat = gfx::format::DepthStencil;

gfx_defines!{
    vertex Vertex {
        pos: [f32; 2] = "a_Pos",
        color: [f32; 3] = "a_Color",
    }

    pipeline pipe {
        vbuf: gfx::VertexBuffer<Vertex> = (),
        out: gfx::RenderTarget<ColorFormat> = "Target0",
    }
}

const QUAD: [Vertex; 4] = [
    Vertex { pos: [ -0.5,  0.5 ], color: [0.0, 0.0, 0.0] },
    Vertex { pos: [ -0.5, -0.5 ], color: [0.0, 0.0, 0.0] },
    Vertex { pos: [  0.5, -0.5 ], color: [1.0, 1.0, 1.0] },
    Vertex { pos: [  0.5,  0.5 ], color: [1.0, 1.0, 1.0] }
];

const CLEAR_COLOR: [f32; 4] = [0.5, 0.5, 0.5, 1.0];

pub fn main() {
    let mut events_loop = glutin::EventsLoop::new();
    let window_builder = glutin::WindowBuilder::new()
        .with_title("Gamma example".to_string())
        .with_dimensions(1024, 768);
    let context = glutin::ContextBuilder::new()
        .with_vsync(true);
    let window = gfx_window_glutin::build(builder, &events_loop, ColorFormat::get_format(), DepthFormat::get_format());

    let (mut surface, adapters) = gfx_window_glutin::Window(&window).get_surface_and_adapters();
    let queue_descs = adapters[0].get_queue_families().iter()
                                 .filter(|family| surface.supports_queue(&family) )
                                 .map(|family| { (family, 1) })
                                 .collect::<Vec<_>>();

    // Open device (factory and queues)
    let gfx::Device { mut factory, mut general_queues, mut graphics_queues, .. } = adapters[0].open(&queue_descs);
    let mut graphics_queue = if let Some(queue) = general_queues.first_mut() {
        queue.as_mut().into()
    } else if let Some(queue) = graphics_queues.first_mut() {
        queue.as_mut()
    } else {
        panic!("Unable to find a matching general or graphics queue.");
    };

    // Create swapchain
    let config = gfx::SwapchainConfig::new()
                    .with_color::<ColorFormat>();
    let mut swap_chain = surface.build_swapchain(config, &graphics_queue);
    let views = swap_chain.create_color_views(&mut factory);

    let pso = factory.create_pipeline_simple(
        include_bytes!("shader/quad_150.glslv"),
        include_bytes!("shader/quad_150.glslf"),
        pipe::new()
    ).unwrap();
    let (vertex_buffer, slice) = factory.create_vertex_buffer_with_slice(&QUAD, &[0u16, 1, 2, 2, 3, 0] as &[u16]);
    let mut graphics_pool = graphics_queue.create_graphics_pool(1);
    let frame_semaphore = factory.create_semaphore();
    let draw_semaphore = factory.create_semaphore();

    let mut data = pipe::Data {
        vbuf: vertex_buffer,
        out: views[0].clone(),
    };

    let mut running = true;
    while running {
        events_loop.poll_events(|glutin::Event::WindowEvent{window_id: _, event}| {
            match event {
                glutin::WindowEvent::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape), _) |
                glutin::WindowEvent::Closed => running = false,
                glutin::WindowEvent::Resized(_width, _height) => {
                    // TODO
                },
                _ => {},
            }
        });

        // Get next frame
        let frame = swap_chain.acquire_frame(FrameSync::Semaphore(&frame_semaphore));
        data.out = views[frame.id()].clone();

        // Draw a frame
        let mut encoder = graphics_pool.acquire_graphics_encoder();
        encoder.clear(&data.out, CLEAR_COLOR);
        encoder.draw(&slice, &pso, &data);
        encoder.synced_flush(&mut graphics_queue, &[&frame_semaphore], &[&draw_semaphore], None);
        swap_chain.present(&mut graphics_queue, &[&draw_semaphore]);
        // factory.cleanup();
    }
}
<|endoftext|>


<commit_before>extern crate cc;
extern crate pkg_config;

use std::env;
use std::path::PathBuf;

fn main() {
    // Find and link OpenEXR and IlmBase
    let include_paths = {
        let mut include_paths = Vec::new();

        let suffix = if let Ok(v) = env::var("OPENEXR_LIB_SUFFIX") {
            format!("-{}", v)
        } else {
            "".into()
        };

        if let Ok(path) = env::var("OPENEXR_DIR") {
            // There's an environment variable, so let's use that
            println!("cargo:rustc-link-search=native={}/lib", path);
            println!("cargo:rustc-link-lib=static=IlmImf{}", suffix);
            println!("cargo:rustc-link-lib=static=IlmImfUtil{}", suffix);
            include_paths.push(PathBuf::from(&format!("{}/include/OpenEXR", path)));
        } else {
            // There's no enviroment variable, so use pkgconfig to find
            // the libs
            let paths = pkg_config::Config::new()
                .atleast_version("2.0.0")
                .probe("OpenEXR")
                .map(|openexr_cfg| openexr_cfg.include_paths.clone())
                .map_err(|err| {
                    panic!(
                        "couldn't find OpenEXR: environment variable \
                         OPENEXR_DIR is unset and pkg-config failed: {}",
                        err
                    )
                })
                .unwrap();

            include_paths.extend_from_slice(&paths);
        }

        if let Ok(path) = env::var("ILMBASE_DIR") {
            println!("cargo:rustc-link-search=native={}/lib", path);
            println!("cargo:rustc-link-lib=static=IexMath{}", suffix);
            println!("cargo:rustc-link-lib=static=Iex{}", suffix);
            println!("cargo:rustc-link-lib=static=Imath{}", suffix);
            println!("cargo:rustc-link-lib=static=IlmThread{}", suffix);
            println!("cargo:rustc-link-lib=static=Half");
            include_paths.push(PathBuf::from(&format!("{}/include/OpenEXR", path)));
        } else {
            let paths = pkg_config::Config::new()
                .atleast_version("2.0.0")
                .cargo_metadata(false) // OpenEXR already pulls in all the flags we need
                .probe("IlmBase")
                .map(|ilmbase_cfg| ilmbase_cfg.include_paths.clone())
                .map_err(|err| {
                    panic!(
                        "couldn't find IlmBase: environment variable \
                         ILMBASE_DIR is unset and pkg-config failed: {}",
                        err
                    )
                })
                .unwrap();
            include_paths.extend_from_slice(&paths);
        }

        include_paths
    };

    // Find and link zlib, needed for OpenEXR
    // Use environment variable if it exists, and otherwise use pkgconfig.
    if let Ok(path) = env::var("ZLIB_DIR") {
        println!("cargo:rustc-link-search=native={}/lib", path);
        println!("cargo:rustc-link-lib=static=zlibstatic");
    } else if let Err(err) = pkg_config::probe_library("zlib") {
        panic!(
            "couldn't find zlib: environment variable ZLIB_DIR is unset \
             and pkg-config failed: {}",
            err
        );
    }

    // Build C wrapper for OpenEXR
    let mut cc = cc::Build::new();
    cc.cpp(true).include("c_wrapper");
    #[cfg(target_env = "msvc")]
    cc.flag("/std:c++14");
    #[cfg(not(target_env = "msvc"))]
    cc.flag("-std=c++0x");
    for path in &include_paths {
        cc.include(path);
    }
    cc.file("c_wrapper/cexr.cpp")
        .file("c_wrapper/rust_istream.cpp")
        .file("c_wrapper/memory_istream.cpp")
        .file("c_wrapper/rust_ostream.cpp")
        .compile("libcexr.a");
}
<commit_msg>fix_pkg_config_file_name_issue<commit_after>extern crate cc;
extern crate pkg_config;

use std::env;
use std::path::PathBuf;

fn main() {
    // Find and link OpenEXR and IlmBase
    let include_paths = {
        let mut include_paths = Vec::new();

        let suffix = if let Ok(v) = env::var("OPENEXR_LIB_SUFFIX") {
            format!("-{}", v)
        } else {
            "".into()
        };

        if let Ok(path) = env::var("OPENEXR_DIR") {
            // There's an environment variable, so let's use that
            println!("cargo:rustc-link-search=native={}/lib", path);
            println!("cargo:rustc-link-lib=static=IlmImf{}", suffix);
            println!("cargo:rustc-link-lib=static=IlmImfUtil{}", suffix);
            include_paths.push(PathBuf::from(&format!("{}/include/OpenEXR", path)));
        } else {
            // There's no enviroment variable, so use pkgconfig to find
            // the libs
            // Note that if OpenEXR's version < 2.5.2, then the name of
            // pkgconfig file should be "IlmBase.pc", otherwise it will
            // be "OpenEXR.pc"
            let mut openexr_pkg_config = pkg_config::Config::new()
                .atleast_version("2.5.2")
                .probe("OpenEXR");

            if (!openexr_pkg_config.is_ok()) {
                openexr_pkg_config = pkg_config::Config::new()
                    .atleast_version("2.0.0")
                    .probe("IlmBase");
            }

            let openexr_library_paths = openexr_pkg_config
                .map(|openexr_cfg| openexr_cfg.include_paths.clone())
                .map_err(|err| {
                    panic!(
                        "couldn't find OpenEXR: environment variable \
                         OPENEXR_DIR is unset and pkg-config failed: {}",
                        err
                    )
                })
                .unwrap();

            include_paths.extend_from_slice(&openexr_library_paths);
        }

        if let Ok(path) = env::var("ILMBASE_DIR") {
            println!("cargo:rustc-link-search=native={}/lib", path);
            println!("cargo:rustc-link-lib=static=IexMath{}", suffix);
            println!("cargo:rustc-link-lib=static=Iex{}", suffix);
            println!("cargo:rustc-link-lib=static=Imath{}", suffix);
            println!("cargo:rustc-link-lib=static=IlmThread{}", suffix);
            println!("cargo:rustc-link-lib=static=Half");
            include_paths.push(PathBuf::from(&format!("{}/include/OpenEXR", path)));
        } else {
            let paths = pkg_config::Config::new()
                .atleast_version("2.0.0")
                .cargo_metadata(false) // OpenEXR already pulls in all the flags we need
                .probe("IlmBase")
                .map(|ilmbase_cfg| ilmbase_cfg.include_paths.clone())
                .map_err(|err| {
                    panic!(
                        "couldn't find IlmBase: environment variable \
                         ILMBASE_DIR is unset and pkg-config failed: {}",
                        err
                    )
                })
                .unwrap();
            include_paths.extend_from_slice(&paths);
        }

        include_paths
    };

    // Find and link zlib, needed for OpenEXR
    // Use environment variable if it exists, and otherwise use pkgconfig.
    if let Ok(path) = env::var("ZLIB_DIR") {
        println!("cargo:rustc-link-search=native={}/lib", path);
        println!("cargo:rustc-link-lib=static=zlibstatic");
    } else if let Err(err) = pkg_config::probe_library("zlib") {
        panic!(
            "couldn't find zlib: environment variable ZLIB_DIR is unset \
             and pkg-config failed: {}",
            err
        );
    }

    // Build C wrapper for OpenEXR
    let mut cc = cc::Build::new();
    cc.cpp(true).include("c_wrapper");
    #[cfg(target_env = "msvc")]
    cc.flag("/std:c++14");
    #[cfg(not(target_env = "msvc"))]
    cc.flag("-std=c++0x");
    for path in &include_paths {
        cc.include(path);
    }
    cc.file("c_wrapper/cexr.cpp")
        .file("c_wrapper/rust_istream.cpp")
        .file("c_wrapper/memory_istream.cpp")
        .file("c_wrapper/rust_ostream.cpp")
        .compile("libcexr.a");
}
<|endoftext|>


<commit_before>use std::io::{Write, ErrorKind};
use std::io::Read;

use mio::*;
use mio::tcp::TcpStream;
use mio::unix::UnixReady;
use sozu_command::buffer::Buffer;
use {
  SessionMetrics,
  SessionResult,
  Readiness,
  BackendConnectionStatus,
  protocol::{ProtocolResult, pipe::Pipe},
  socket::SocketHandler,
  pool::Checkout,
};

use super::header::*;

pub struct SendProxyProtocol<Front:SocketHandler> {
  pub header:         Option<Vec<u8>>,
  pub frontend:       Front,
  pub backend:        Option<TcpStream>,
  pub frontend_token: Token,
  pub backend_token:  Option<Token>,
  pub front_readiness:Readiness,
  pub back_readiness: Readiness,
  cursor_header:      usize,
}

impl <Front:SocketHandler + Read> SendProxyProtocol<Front> {
  pub fn new(frontend: Front, frontend_token: Token, backend: Option<TcpStream>) -> Self {
    SendProxyProtocol {
      header: None,
      frontend,
      backend,
      frontend_token,
      backend_token:  None,
      front_readiness: Readiness {
        interest: UnixReady::hup() | UnixReady::error(),
        event:    UnixReady::from(Ready::empty()),
      },
      back_readiness: Readiness {
        interest: UnixReady::hup() | UnixReady::error(),
        event:    UnixReady::from(Ready::empty()),
      },
      cursor_header: 0,
    }
  }

  // The header is send immediately at once upon the connection is establish
  // and prepended before any data.
  pub fn back_writable(&mut self, metrics: &mut SessionMetrics) -> (ProtocolResult, SessionResult) {
    debug!("Writing proxy protocol header");

    if let Some(ref mut socket) = self.backend {
      if let Some(ref mut header) = self.header {
        loop {
          match socket.write(&mut header[self.cursor_header..]) {
            Ok(sz) => {
              self.cursor_header += sz;
              metrics.backend_bout += sz;

              if self.cursor_header == header.len() {
                debug!("Proxy protocol sent, upgrading");
                return (ProtocolResult::Upgrade, SessionResult::Continue);
              }
            },
            Err(e) => match e.kind() {
              ErrorKind::WouldBlock => {
                self.back_readiness.event.remove(Ready::writable());
                return (ProtocolResult::Continue, SessionResult::Continue);
              },
              e => {
                incr!("proxy_protocol.errors");
                debug!("send proxy protocol write error {:?}", e);
                return (ProtocolResult::Continue, SessionResult::CloseSession);
              }
            },
          }
        }
      }
    }

    error!("started Send proxy protocol with no header or backend socket");
    (ProtocolResult::Continue, SessionResult::CloseSession)
  }

  pub fn front_socket(&self) -> &TcpStream {
    self.frontend.socket_ref()
  }

  pub fn back_socket(&self) -> Option<&TcpStream> {
    self.backend.as_ref()
  }

  pub fn set_back_socket(&mut self, socket: TcpStream) {
    self.backend = Some(socket);
  }

  pub fn back_token(&self) -> Option<Token> {
    self.backend_token
  }

  pub fn set_back_token(&mut self, token: Token) {
    self.backend_token = Some(token);
  }

  pub fn set_back_connected(&mut self, status: BackendConnectionStatus) {
    if status == BackendConnectionStatus::Connected {
      self.gen_proxy_protocol_header();
      self.back_readiness.interest.insert(UnixReady::from(Ready::writable()));
    }
  }

  pub fn front_readiness(&mut self) -> &mut Readiness {
    &mut self.front_readiness
  }

  pub fn back_readiness(&mut self) -> &mut Readiness {
    &mut self.back_readiness
  }

  fn gen_proxy_protocol_header(&mut self) {
    let addr_frontend = self.frontend.socket_ref().peer_addr().expect("frontend address should be available");

    let addr_backend = self.backend.as_ref().and_then(|socket| {
      socket.peer_addr().map_err(|e| error!("cannot get backend address: {:?}", e)).ok()
    });

    let addr_backend = match addr_backend {
      Some(addr) => addr,
      None       => return,
    };

    // PROXY command hardcoded for now, but we'll use LOCAL when we implement health checks
    let protocol_header = ProxyProtocolHeader::V2(HeaderV2::new(Command::Proxy, addr_frontend, addr_backend));
    self.header = Some(protocol_header.into_bytes());
  }

  pub fn into_pipe(mut self, front_buf: Checkout<Buffer>, back_buf: Checkout<Buffer>) -> Pipe<Front> {
    let backend_socket = self.backend.take().unwrap();
    let addr = backend_socket.peer_addr().map(|s| s.ip()).ok();

    let mut pipe = Pipe::new(
      self.frontend,
      self.frontend_token,
      Some(backend_socket),
      front_buf,
      back_buf,
      addr,
    );

    pipe.front_readiness = self.front_readiness;
    pipe.back_readiness  = self.back_readiness;

    pipe.front_readiness.interest.insert(UnixReady::from(Ready::readable()));
    pipe.back_readiness.interest.insert(UnixReady::from(Ready::readable()));

    if let Some(back_token) = self.backend_token {
      pipe.set_back_token(back_token);
    }

    pipe
  }
}

#[cfg(test)]
mod send_test {

  use super::*;

  use super::super::parser::parse_v2_header;

  use std::{sync::{Arc, Barrier}, thread::{self, JoinHandle}, net::SocketAddr};
  use mio::net::{TcpListener, TcpStream};
  use std::net::{TcpListener as StdTcpListener, TcpStream as StdTcpStream};
  use std::os::unix::io::{FromRawFd,IntoRawFd};

  #[test]
  fn it_should_send_a_proxy_protocol_header_to_the_upstream_backend() {
    setup_test_logger!();
    let addr_client: SocketAddr = "127.0.0.1:6666".parse().expect("parse address error");
    let addr_backend: SocketAddr = "127.0.0.1:2001".parse().expect("parse address error");
    let barrier = Arc::new(Barrier::new(3));
    let end_barrier = Arc::new(Barrier::new(2));

    start_client(addr_client.clone(), barrier.clone(), end_barrier.clone());
    let backend = start_backend(addr_backend.clone(), barrier.clone(), end_barrier.clone());
    start_middleware(addr_client, addr_backend, barrier.clone());

    backend.join().expect("Couldn't join on the associated backend");
  }

  // Get connection from the session and connect to the backend
  // When connections are etablish we send the proxy protocol header
  fn start_middleware(addr_client: SocketAddr, addr_backend: SocketAddr, barrier: Arc<Barrier>) {
    let listener = TcpListener::bind(&addr_client).expect("could not accept session connection");

    let client_stream;
    barrier.wait();

    loop {
      if let Ok((stream, _addr)) = listener.accept() {
        client_stream = stream;
        break;
      }
    }

    // connect in blocking first, then convert to a mio socket
    let backend_stream = StdTcpStream::connect(&addr_backend).expect("could not connect to the backend");
    let fd = backend_stream.into_raw_fd();
    let backend_stream = unsafe { TcpStream::from_raw_fd(fd) };

    let mut send_pp = SendProxyProtocol::new(client_stream, Token(0), Some(backend_stream));
    let mut session_metrics = SessionMetrics::new();

    send_pp.set_back_connected(BackendConnectionStatus::Connected);

    loop {
      let (protocol, session) = send_pp.back_writable(&mut session_metrics);
      if session != SessionResult::Continue {
        panic!("state machine error: protocol result = {:?}, session result = {:?}", protocol, session);
      }

      if protocol == ProtocolResult::Upgrade {
        break;
      }
    }
  }

  // Only connect to the middleware
  fn start_client(addr: SocketAddr, barrier: Arc<Barrier>, end_barrier: Arc<Barrier>) {
    thread::spawn(move|| {
      barrier.wait();

      let stream = StdTcpStream::connect(&addr).unwrap();

      end_barrier.wait();
    });
  }

  // Get connection from the middleware read on the socket stream.
  // We check if we receive a valid proxy protocol header
  fn start_backend(addr: SocketAddr, barrier: Arc<Barrier>, end_barrier: Arc<Barrier>) -> JoinHandle<()> {
    let listener = StdTcpListener::bind(&addr).expect("could not start backend");

    thread::spawn(move|| {
      barrier.wait();

      let mut buf: [u8; 28] = [0; 28];
      let (mut conn, _) = listener.accept().expect("could not accept connection from light middleware");
      println!("backend got a connection from the middleware");

      let mut index = 0usize;
      loop {
        if index >= 28 {
          break;
        }

        match conn.read(&mut buf[index..]) {
          Err(e) => match e.kind() {
            ErrorKind::WouldBlock => continue,
            e => {
              end_barrier.wait();
              panic!("read error: {:?}", e);
            }
          },
          Ok(sz) => {
            println!("backend read {} bytes", sz);
            index += sz;
          },
        }
      }

      match parse_v2_header(&buf) {
        Ok((_,_)) => println!("complete header received"),
        err => {
          end_barrier.wait();
          panic!("incorrect proxy protocol header received: {:?}", err);
        }
      };

      end_barrier.wait();
    })
  }
}
<commit_msg>Close the session when the client has disconnected and we try to generate the proxy protocol header (#550)<commit_after>use std::io::{Write, ErrorKind};
use std::io::Read;

use mio::*;
use mio::tcp::TcpStream;
use mio::unix::UnixReady;
use sozu_command::buffer::Buffer;
use {
  SessionMetrics,
  SessionResult,
  Readiness,
  BackendConnectionStatus,
  protocol::{ProtocolResult, pipe::Pipe},
  socket::SocketHandler,
  pool::Checkout,
};

use super::header::*;

pub struct SendProxyProtocol<Front:SocketHandler> {
  pub header:         Option<Vec<u8>>,
  pub frontend:       Front,
  pub backend:        Option<TcpStream>,
  pub frontend_token: Token,
  pub backend_token:  Option<Token>,
  pub front_readiness:Readiness,
  pub back_readiness: Readiness,
  cursor_header:      usize,
}

impl <Front:SocketHandler + Read> SendProxyProtocol<Front> {
  pub fn new(frontend: Front, frontend_token: Token, backend: Option<TcpStream>) -> Self {
    SendProxyProtocol {
      header: None,
      frontend,
      backend,
      frontend_token,
      backend_token:  None,
      front_readiness: Readiness {
        interest: UnixReady::hup() | UnixReady::error(),
        event:    UnixReady::from(Ready::empty()),
      },
      back_readiness: Readiness {
        interest: UnixReady::hup() | UnixReady::error(),
        event:    UnixReady::from(Ready::empty()),
      },
      cursor_header: 0,
    }
  }

  // The header is send immediately at once upon the connection is establish
  // and prepended before any data.
  pub fn back_writable(&mut self, metrics: &mut SessionMetrics) -> (ProtocolResult, SessionResult) {
    debug!("Trying to write proxy protocol header");

    // Generate the proxy protocol header if not already exist.
    if self.header.is_none() {
      if let Some(backend_addr) = self.back_socket().and_then(|s| s.peer_addr().ok()) {
        if let Ok(frontend_addr) = self.front_socket().peer_addr() {
          self.header = Some(ProxyProtocolHeader::V2(HeaderV2::new(Command::Proxy, frontend_addr, backend_addr)).into_bytes());
        } else {
          return (ProtocolResult::Continue, SessionResult::CloseSession);
        }
      };
    }

    if let Some(ref mut socket) = self.backend {
      if let Some(ref mut header) = self.header {
        loop {
          match socket.write(&mut header[self.cursor_header..]) {
            Ok(sz) => {
              self.cursor_header += sz;
              metrics.backend_bout += sz;

              if self.cursor_header == header.len() {
                debug!("Proxy protocol sent, upgrading");
                return (ProtocolResult::Upgrade, SessionResult::Continue);
              }
            },
            Err(e) => match e.kind() {
              ErrorKind::WouldBlock => {
                self.back_readiness.event.remove(Ready::writable());
                return (ProtocolResult::Continue, SessionResult::Continue);
              },
              e => {
                incr!("proxy_protocol.errors");
                debug!("send proxy protocol write error {:?}", e);
                return (ProtocolResult::Continue, SessionResult::CloseSession);
              }
            },
          }
        }
      }
    }

    error!("started Send proxy protocol with no header or backend socket");
    (ProtocolResult::Continue, SessionResult::CloseSession)
  }

  pub fn front_socket(&self) -> &TcpStream {
    self.frontend.socket_ref()
  }

  pub fn back_socket(&self) -> Option<&TcpStream> {
    self.backend.as_ref()
  }

  pub fn set_back_socket(&mut self, socket: TcpStream) {
    self.backend = Some(socket);
  }

  pub fn back_token(&self) -> Option<Token> {
    self.backend_token
  }

  pub fn set_back_token(&mut self, token: Token) {
    self.backend_token = Some(token);
  }

  pub fn set_back_connected(&mut self, status: BackendConnectionStatus) {
    if status == BackendConnectionStatus::Connected {
      self.back_readiness.interest.insert(UnixReady::from(Ready::writable()));
    }
  }

  pub fn front_readiness(&mut self) -> &mut Readiness {
    &mut self.front_readiness
  }

  pub fn back_readiness(&mut self) -> &mut Readiness {
    &mut self.back_readiness
  }

  pub fn into_pipe(mut self, front_buf: Checkout<Buffer>, back_buf: Checkout<Buffer>) -> Pipe<Front> {
    let backend_socket = self.backend.take().unwrap();
    let addr = backend_socket.peer_addr().map(|s| s.ip()).ok();

    let mut pipe = Pipe::new(
      self.frontend,
      self.frontend_token,
      Some(backend_socket),
      front_buf,
      back_buf,
      addr,
    );

    pipe.front_readiness = self.front_readiness;
    pipe.back_readiness  = self.back_readiness;

    pipe.front_readiness.interest.insert(UnixReady::from(Ready::readable()));
    pipe.back_readiness.interest.insert(UnixReady::from(Ready::readable()));

    if let Some(back_token) = self.backend_token {
      pipe.set_back_token(back_token);
    }

    pipe
  }
}

#[cfg(test)]
mod send_test {

  use super::*;

  use super::super::parser::parse_v2_header;

  use std::{sync::{Arc, Barrier}, thread::{self, JoinHandle}, net::SocketAddr};
  use mio::net::{TcpListener, TcpStream};
  use std::net::{TcpListener as StdTcpListener, TcpStream as StdTcpStream};
  use std::os::unix::io::{FromRawFd,IntoRawFd};

  #[test]
  fn it_should_send_a_proxy_protocol_header_to_the_upstream_backend() {
    setup_test_logger!();
    let addr_client: SocketAddr = "127.0.0.1:6666".parse().expect("parse address error");
    let addr_backend: SocketAddr = "127.0.0.1:2001".parse().expect("parse address error");
    let barrier = Arc::new(Barrier::new(3));
    let end_barrier = Arc::new(Barrier::new(2));

    start_client(addr_client.clone(), barrier.clone(), end_barrier.clone());
    let backend = start_backend(addr_backend.clone(), barrier.clone(), end_barrier.clone());
    start_middleware(addr_client, addr_backend, barrier.clone());

    backend.join().expect("Couldn't join on the associated backend");
  }

  // Get connection from the session and connect to the backend
  // When connections are etablish we send the proxy protocol header
  fn start_middleware(addr_client: SocketAddr, addr_backend: SocketAddr, barrier: Arc<Barrier>) {
    let listener = TcpListener::bind(&addr_client).expect("could not accept session connection");

    let client_stream;
    barrier.wait();

    loop {
      if let Ok((stream, _addr)) = listener.accept() {
        client_stream = stream;
        break;
      }
    }

    // connect in blocking first, then convert to a mio socket
    let backend_stream = StdTcpStream::connect(&addr_backend).expect("could not connect to the backend");
    let fd = backend_stream.into_raw_fd();
    let backend_stream = unsafe { TcpStream::from_raw_fd(fd) };

    let mut send_pp = SendProxyProtocol::new(client_stream, Token(0), Some(backend_stream));
    let mut session_metrics = SessionMetrics::new();

    send_pp.set_back_connected(BackendConnectionStatus::Connected);

    loop {
      let (protocol, session) = send_pp.back_writable(&mut session_metrics);
      if session != SessionResult::Continue {
        panic!("state machine error: protocol result = {:?}, session result = {:?}", protocol, session);
      }

      if protocol == ProtocolResult::Upgrade {
        break;
      }
    }
  }

  // Only connect to the middleware
  fn start_client(addr: SocketAddr, barrier: Arc<Barrier>, end_barrier: Arc<Barrier>) {
    thread::spawn(move|| {
      barrier.wait();

      let stream = StdTcpStream::connect(&addr).unwrap();

      end_barrier.wait();
    });
  }

  // Get connection from the middleware read on the socket stream.
  // We check if we receive a valid proxy protocol header
  fn start_backend(addr: SocketAddr, barrier: Arc<Barrier>, end_barrier: Arc<Barrier>) -> JoinHandle<()> {
    let listener = StdTcpListener::bind(&addr).expect("could not start backend");

    thread::spawn(move|| {
      barrier.wait();

      let mut buf: [u8; 28] = [0; 28];
      let (mut conn, _) = listener.accept().expect("could not accept connection from light middleware");
      println!("backend got a connection from the middleware");

      let mut index = 0usize;
      loop {
        if index >= 28 {
          break;
        }

        match conn.read(&mut buf[index..]) {
          Err(e) => match e.kind() {
            ErrorKind::WouldBlock => continue,
            e => {
              end_barrier.wait();
              panic!("read error: {:?}", e);
            }
          },
          Ok(sz) => {
            println!("backend read {} bytes", sz);
            index += sz;
          },
        }
      }

      match parse_v2_header(&buf) {
        Ok((_,_)) => println!("complete header received"),
        err => {
          end_barrier.wait();
          panic!("incorrect proxy protocol header received: {:?}", err);
        }
      };

      end_barrier.wait();
    })
  }
}
<|endoftext|>


<commit_before>
#[allow(dead_code)]
pub mod periph_base_addr {
    pub const I2C1: usize = 1073763328;
    pub const I2C2: usize = 1073764352;
    pub const I2C3: usize = 1073765376;
    pub const GPIOA: usize = 0x40020000;
    pub const GPIOB: usize = 0x40020400;
    pub const GPIOC: usize = 0x40020800;
    pub const GPIOD: usize = 0x40020C00;
    pub const GPIOE: usize = 0x40021000;
    pub const GPIOH: usize = 0x40021C00;
}

pub fn board_specific_init() {
}<commit_msg>Added initial RCC implementation to the BSP<commit_after>
#[allow(dead_code)]
pub mod periph_base_addr {
    pub const I2C1: usize = 1073763328;
    pub const I2C2: usize = 1073764352;
    pub const I2C3: usize = 1073765376;
    pub const GPIOA: usize = 0x40020000;
    pub const GPIOB: usize = 0x40020400;
    pub const GPIOC: usize = 0x40020800;
    pub const GPIOD: usize = 0x40020C00;
    pub const GPIOE: usize = 0x40021000;
    pub const GPIOH: usize = 0x40021C00;
    pub const RCC: usize = 0x40023800;
}

pub mod rcc {
    use volatile_register::RW;

    const RCC_AHB1_DMA2: u32 = 1 << 22;
    const RCC_AHB1_DMA1: u32 = 1 << 21;
    const RCC_AHB1_CRC: u32 = 1 << 12;
    const RCC_AHB1_GPIOH: u32 = 1 << 7;
    const RCC_AHB1_GPIOE: u32 = 1 << 4;
    const RCC_AHB1_GPIOD: u32 = 1 << 3;
    const RCC_AHB1_GPIOC: u32 = 1 << 2;
    const RCC_AHB1_GPIOB: u32 = 1 << 1;
    const RCC_AHB1_GPIOA: u32 = 1;

    const RCC_AHB2_OTGFS: u32 = 1 << 7;

    const RCC_APB1_PWR: u32 = 1 << 28;
    const RCC_APB1_I2C3: u32 = 1 << 23;
    const RCC_APB1_I2C2: u32 = 1 << 22;
    const RCC_APB1_I2C1: u32 = 1 << 21;
    const RCC_APB1_USART2: u32 = 1 << 17;
    const RCC_APB1_SPI3: u32 = 1 << 15;
    const RCC_APB1_SPI2: u32 = 1 << 14;
    const RCC_APB1_WWDG: u32 = 1 << 11;
    const RCC_APB1_TIM5: u32 = 1 << 3;
    const RCC_APB1_TIM4: u32 = 1 << 2;
    const RCC_APB1_TIM3: u32 = 1 << 1;
    const RCC_APB1_TIM2: u32 = 1;

    const RCC_APB2_SPI5: u32 = 1 << 20;
    const RCC_APB2_TIM11: u32 = 1 << 18;
    const RCC_APB2_TIM10: u32 = 1 << 17;
    const RCC_APB2_TIM9: u32 = 1 << 16;
    const RCC_APB2_SYSCFG: u32 = 1 << 14;
    const RCC_APB2_SPI4: u32 = 1 << 13;
    const RCC_APB2_SPI1: u32 = 1 << 12;
    const RCC_APB2_SDIO: u32 = 1 << 11;
    const RCC_APB2_ADC1: u32 = 1 << 8;
    const RCC_APB2_USART6: u32 = 1 << 5;
    const RCC_APB2_USART1: u32 = 1 << 4;
    const RCC_APB2_TIM1: u32 = 1;

    struct Rcc {
        _cr: RW<u32>,
        _pllcfgr: RW<u32>,
        _cfgr: RW<u32>,
        _cir: RW<u32>,
        ahb1rstr: RW<u32>,
        ahb2rstr: RW<u32>,
        _padding1: RW<u32>,
        _padding2: RW<u32>,
        apb1rstr: RW<u32>,
        apb2rstr: RW<u32>,
        _padding3: RW<u32>,
        _padding4: RW<u32>,
        ahb1enr: RW<u32>,
        ahb2enr: RW<u32>,
        _padding5: RW<u32>,
        _padding6: RW<u32>,
        apb1enr: RW<u32>,
        apb2enr: RW<u32>,
        _padding7: RW<u32>,
        _padding8: RW<u32>,
        _ahb1lpenr: RW<u32>,
        _ahb2lpenr: RW<u32>,
        _padding9: RW<u32>,
        _padding10: RW<u32>,
        _apb1lpenr: RW<u32>,
        _apb2lpenr: RW<u32>,
        _padding11: RW<u32>,
        _padding12: RW<u32>,
        _bdcr: RW<u32>,
        _csr: RW<u32>,
        _padding13: RW<u32>,
        _padding14: RW<u32>,
        _sscgr: RW<u32>,
        _plli2scfgr: RW<u32>,
        _dckcfgr: RW<u32>,
    }

    #[derive(Copy, Clone)]
    enum Bus {
        Ahb1,
        Ahb2,
        Apb1,
        Apb2,
    }

    #[derive(Copy, Clone)]
    pub enum Peripheral {
        GpioA,
        GpioB,
        GpioC,
        GpioD,
        GpioE,
        GpioH,
        Crc,
        Dma1,
        Dma2,

        OtgFs,

        Tim2,
        Tim3,
        Tim4,
        Tim5,
        Wwdg,
        Spi2,
        Spi3,
        Usart2,
        I2C1,
        I2C2,
        I2C3,
        Pwr,

        Tim1,
        Usart1,
        Usart6,
        Adc1,
        Sdio,
        Spi1,
        Spi4,
        SysCfg,
        Tim9,
        Tim10,
        Tim11,
        Spi5,
    }

    impl Peripheral {
        fn get_bus(&self) -> Bus {
            match *self {
                Peripheral::GpioA | Peripheral::GpioB | Peripheral::GpioC | Peripheral::GpioD |
                Peripheral::GpioE | Peripheral::GpioH | Peripheral::Crc | Peripheral::Dma1 |
                Peripheral::Dma2 => Bus::Ahb1,
                Peripheral::OtgFs => Bus::Ahb2,
                Peripheral::Tim2 |
                Peripheral::Tim3 |
                Peripheral::Tim4 |
                Peripheral::Tim5 |
                Peripheral::Wwdg |
                Peripheral::Spi2 |
                Peripheral::Spi3 |
                Peripheral::Usart2 |
                Peripheral::I2C1 |
                Peripheral::I2C2 |
                Peripheral::I2C3 |
                Peripheral::Pwr => Bus::Apb1,
                Peripheral::Tim1 |
                Peripheral::Usart1 |
                Peripheral::Usart6 |
                Peripheral::Adc1 |
                Peripheral::Sdio |
                Peripheral::Spi1 |
                Peripheral::Spi4 |
                Peripheral::SysCfg |
                Peripheral::Tim9 |
                Peripheral::Tim10 |
                Peripheral::Tim11 |
                Peripheral::Spi5 => Bus::Apb2,
            }
        }

        fn get_mask(&self) -> u32 {
            match *self {
                Peripheral::GpioA => RCC_AHB1_GPIOA,
                Peripheral::GpioB => RCC_AHB1_GPIOB,
                Peripheral::GpioC => RCC_AHB1_GPIOC,
                Peripheral::GpioD => RCC_AHB1_GPIOD,
                Peripheral::GpioE => RCC_AHB1_GPIOE,
                Peripheral::GpioH => RCC_AHB1_GPIOH,
                Peripheral::Crc => RCC_AHB1_CRC,
                Peripheral::Dma1 => RCC_AHB1_DMA1,
                Peripheral::Dma2 => RCC_AHB1_DMA2,
                Peripheral::OtgFs => RCC_AHB2_OTGFS,
                Peripheral::Tim2 => RCC_APB1_TIM2,
                Peripheral::Tim3 => RCC_APB1_TIM3,
                Peripheral::Tim4 => RCC_APB1_TIM4,
                Peripheral::Tim5 => RCC_APB1_TIM5,
                Peripheral::Wwdg => RCC_APB1_WWDG,
                Peripheral::Spi2 => RCC_APB1_SPI2,
                Peripheral::Spi3 => RCC_APB1_SPI3,
                Peripheral::Usart2 => RCC_APB1_USART2,
                Peripheral::I2C1 => RCC_APB1_I2C1,
                Peripheral::I2C2 => RCC_APB1_I2C2,
                Peripheral::I2C3 => RCC_APB1_I2C3,
                Peripheral::Pwr => RCC_APB1_PWR,
                Peripheral::Tim1 => RCC_APB2_TIM1,
                Peripheral::Usart1 => RCC_APB2_USART1,
                Peripheral::Usart6 => RCC_APB2_USART6,
                Peripheral::Adc1 => RCC_APB2_ADC1,
                Peripheral::Sdio => RCC_APB2_SDIO,
                Peripheral::Spi1 => RCC_APB2_SPI1,
                Peripheral::Spi4 => RCC_APB2_SPI4,
                Peripheral::SysCfg => RCC_APB2_SYSCFG,
                Peripheral::Tim9 => RCC_APB2_TIM9,
                Peripheral::Tim10 => RCC_APB2_TIM10,
                Peripheral::Tim11 => RCC_APB2_TIM11,
                Peripheral::Spi5 => RCC_APB2_SPI5,
            }
        }
    }

    pub fn enable_periph(periph: Peripheral) {
        let rcc = unsafe { &*(super::periph_base_addr::RCC as *const Rcc) };

        let reg = match periph.get_bus() {
            Bus::Ahb1 => &rcc.ahb1enr,
            Bus::Ahb2 => &rcc.ahb2enr,
            Bus::Apb1 => &rcc.apb1enr,
            Bus::Apb2 => &rcc.apb2enr,
        };

        unsafe {
            reg.modify(|curr| curr | periph.get_mask());
        }
    }

    pub fn disable_periph(periph: Peripheral) {
        let rcc = unsafe { &*(super::periph_base_addr::RCC as *const Rcc) };

        let reg = match periph.get_bus() {
            Bus::Ahb1 => &rcc.ahb1enr,
            Bus::Ahb2 => &rcc.ahb2enr,
            Bus::Apb1 => &rcc.apb1enr,
            Bus::Apb2 => &rcc.apb2enr,
        };

        unsafe {
            reg.modify(|curr| curr & !periph.get_mask());
        }
    }

    pub fn reset_periph(periph: Peripheral) {
        let rcc = unsafe { &*(super::periph_base_addr::RCC as *const Rcc) };

        let reg = match periph.get_bus() {
            Bus::Ahb1 => &rcc.ahb1rstr,
            Bus::Ahb2 => &rcc.ahb2rstr,
            Bus::Apb1 => &rcc.apb1rstr,
            Bus::Apb2 => &rcc.apb2rstr,
        };

        unsafe {
            reg.modify(|curr| curr | periph.get_mask());
            reg.modify(|curr| curr & !periph.get_mask());
        }
    }
}

pub fn board_specific_init() {}
<|endoftext|>


<commit_before>#[macro_use] extern crate log;
#[macro_use] extern crate version;
extern crate clap;

extern crate libimagcounter;
extern crate libimagrt;
extern crate libimagutil;

use std::process::exit;
use std::str::FromStr;

use libimagrt::runtime::Runtime;
use libimagcounter::counter::Counter;
use libimagutil::trace::trace_error;
use libimagutil::key_value_split::IntoKeyValue;

mod create;
mod delete;
mod interactive;
mod list;
mod ui;

use ui::build_ui;
use create::create;
use delete::delete;
use interactive::interactive;
use list::list;

enum Action {
    Inc,
    Dec,
    Reset,
    Set,
}

fn main() {
    let name = "imag-counter";
    let version = &version!()[..];
    let about = "Counter tool to count things";
    let ui = build_ui(Runtime::get_default_cli_builder(name, version, about));
    let rt = {
        let rt = Runtime::new(ui);
        if rt.is_ok() {
            rt.unwrap()
        } else {
            println!("Could not set up Runtime");
            println!("{:?}", rt.err().unwrap());
            exit(1);
        }
    };

    debug!("Hello. Logging was just enabled");
    debug!("I already set up the Runtime object and build the commandline interface parser.");
    debug!("Lets get rollin' ...");

    rt.cli()
        .subcommand_name()
        .map_or_else(|| {
                let (action, name) = {
                    if rt.cli().is_present("increment") {
                        (Action::Inc, rt.cli().value_of("increment").unwrap())
                    } else if rt.cli().is_present("decrement") {
                        (Action::Dec, rt.cli().value_of("decrement").unwrap())
                    } else if rt.cli().is_present("reset") {
                        (Action::Reset, rt.cli().value_of("reset").unwrap())
                    } else /* rt.cli().is_present("set") */ {
                        (Action::Set, rt.cli().value_of("set").unwrap())
                    }
                };

                match action {
                    Action::Inc => {
                        Counter::load(String::from(name), rt.store())
                            .map(|mut counter| {
                                match counter.inc() {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                    Action::Dec => {
                        Counter::load(String::from(name), rt.store())
                            .map(|mut counter| {
                                match counter.dec() {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                    Action::Reset => {
                        Counter::load(String::from(name), rt.store())
                            .map(|mut counter| {
                                match counter.reset() {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                    Action::Set => {
                        let kv = String::from(name).into_kv();
                        if kv.is_none() {
                            warn!("Not a key-value pair: '{}'", name);
                            exit(1);
                        }
                        let (key, value) = kv.unwrap().into();
                        let value = FromStr::from_str(&value[..]);
                        if value.is_err() {
                            warn!("Not a integer: '{:?}'", value);
                            exit(1);
                        }
                        let value : i64 = value.unwrap();
                        Counter::load(String::from(key), rt.store())
                            .map(|mut counter| {
                                match counter.set(value) {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                }
                .map_err(|e| trace_error(&e));
            },
            |name| {
                debug!("Call: {}", name);
                match name {
                    "create"      => create(&rt),
                    "delete"      => delete(&rt),
                    "interactive" => interactive(&rt),
                    "list"        => list(&rt),
                    _ => {
                        debug!("Unknown command"); // More error handling
                    },
                };
            })
}

<commit_msg>Remove init-logging from imag-counter<commit_after>#[macro_use] extern crate log;
#[macro_use] extern crate version;
extern crate clap;

extern crate libimagcounter;
extern crate libimagrt;
extern crate libimagutil;

use std::process::exit;
use std::str::FromStr;

use libimagrt::runtime::Runtime;
use libimagcounter::counter::Counter;
use libimagutil::trace::trace_error;
use libimagutil::key_value_split::IntoKeyValue;

mod create;
mod delete;
mod interactive;
mod list;
mod ui;

use ui::build_ui;
use create::create;
use delete::delete;
use interactive::interactive;
use list::list;

enum Action {
    Inc,
    Dec,
    Reset,
    Set,
}

fn main() {
    let name = "imag-counter";
    let version = &version!()[..];
    let about = "Counter tool to count things";
    let ui = build_ui(Runtime::get_default_cli_builder(name, version, about));
    let rt = {
        let rt = Runtime::new(ui);
        if rt.is_ok() {
            rt.unwrap()
        } else {
            println!("Could not set up Runtime");
            println!("{:?}", rt.err().unwrap());
            exit(1);
        }
    };

    rt.cli()
        .subcommand_name()
        .map_or_else(|| {
                let (action, name) = {
                    if rt.cli().is_present("increment") {
                        (Action::Inc, rt.cli().value_of("increment").unwrap())
                    } else if rt.cli().is_present("decrement") {
                        (Action::Dec, rt.cli().value_of("decrement").unwrap())
                    } else if rt.cli().is_present("reset") {
                        (Action::Reset, rt.cli().value_of("reset").unwrap())
                    } else /* rt.cli().is_present("set") */ {
                        (Action::Set, rt.cli().value_of("set").unwrap())
                    }
                };

                match action {
                    Action::Inc => {
                        Counter::load(String::from(name), rt.store())
                            .map(|mut counter| {
                                match counter.inc() {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                    Action::Dec => {
                        Counter::load(String::from(name), rt.store())
                            .map(|mut counter| {
                                match counter.dec() {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                    Action::Reset => {
                        Counter::load(String::from(name), rt.store())
                            .map(|mut counter| {
                                match counter.reset() {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                    Action::Set => {
                        let kv = String::from(name).into_kv();
                        if kv.is_none() {
                            warn!("Not a key-value pair: '{}'", name);
                            exit(1);
                        }
                        let (key, value) = kv.unwrap().into();
                        let value = FromStr::from_str(&value[..]);
                        if value.is_err() {
                            warn!("Not a integer: '{:?}'", value);
                            exit(1);
                        }
                        let value : i64 = value.unwrap();
                        Counter::load(String::from(key), rt.store())
                            .map(|mut counter| {
                                match counter.set(value) {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                }
                .map_err(|e| trace_error(&e));
            },
            |name| {
                debug!("Call: {}", name);
                match name {
                    "create"      => create(&rt),
                    "delete"      => delete(&rt),
                    "interactive" => interactive(&rt),
                    "list"        => list(&rt),
                    _ => {
                        debug!("Unknown command"); // More error handling
                    },
                };
            })
}

<|endoftext|>