<commit_before>//! Creation of ar archives like for the lib and staticlib crate type

use std::collections::BTreeMap;
use std::fs::File;
use std::path::{Path, PathBuf};

use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder};
use rustc_codegen_ssa::METADATA_FILENAME;
use rustc_session::Session;

use object::{Object, ObjectSymbol, SymbolKind};

#[derive(Debug)]
enum ArchiveEntry {
    FromArchive { archive_index: usize, entry_index: usize },
    File(PathBuf),
}

pub(crate) struct ArArchiveBuilder<'a> {
    sess: &'a Session,
    dst: PathBuf,
    lib_search_paths: Vec<PathBuf>,
    use_gnu_style_archive: bool,
    no_builtin_ranlib: bool,

    src_archives: Vec<(PathBuf, ar::Archive<File>)>,
    // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
    // the end of an archive for linkers to not get confused.
    entries: Vec<(String, ArchiveEntry)>,
}

impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
    fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self {
        use rustc_codegen_ssa::back::link::archive_search_paths;

        let (src_archives, entries) = if let Some(input) = input {
            let mut archive = ar::Archive::new(File::open(input).unwrap());
            let mut entries = Vec::new();

            let mut i = 0;
            while let Some(entry) = archive.next_entry() {
                let entry = entry.unwrap();
                entries.push((
                    String::from_utf8(entry.header().identifier().to_vec()).unwrap(),
                    ArchiveEntry::FromArchive { archive_index: 0, entry_index: i },
                ));
                i += 1;
            }

            (vec![(input.to_owned(), archive)], entries)
        } else {
            (vec![], Vec::new())
        };

        ArArchiveBuilder {
            sess,
            dst: output.to_path_buf(),
            lib_search_paths: archive_search_paths(sess),
            use_gnu_style_archive: sess.target.archive_format == "gnu",
            // FIXME fix builtin ranlib on macOS
            no_builtin_ranlib: sess.target.is_like_osx,

            src_archives,
            entries,
        }
    }

    fn src_files(&mut self) -> Vec<String> {
        self.entries.iter().map(|(name, _)| name.clone()).collect()
    }

    fn remove_file(&mut self, name: &str) {
        let index = self
            .entries
            .iter()
            .position(|(entry_name, _)| entry_name == name)
            .expect("Tried to remove file not existing in src archive");
        self.entries.remove(index);
    }

    fn add_file(&mut self, file: &Path) {
        self.entries.push((
            file.file_name().unwrap().to_str().unwrap().to_string(),
            ArchiveEntry::File(file.to_owned()),
        ));
    }

    fn add_native_library(&mut self, name: rustc_span::symbol::Symbol, verbatim: bool) {
        let location = find_library(name, verbatim, &self.lib_search_paths, self.sess);
        self.add_archive(location.clone(), |_| false).unwrap_or_else(|e| {
            panic!("failed to add native library {}: {}", location.to_string_lossy(), e);
        });
    }

    fn add_rlib(
        &mut self,
        rlib: &Path,
        name: &str,
        lto: bool,
        skip_objects: bool,
    ) -> std::io::Result<()> {
        let obj_start = name.to_owned();

        self.add_archive(rlib.to_owned(), move |fname: &str| {
            // Ignore metadata files, no matter the name.
            if fname == METADATA_FILENAME {
                return true;
            }

            // Don't include Rust objects if LTO is enabled
            if lto && fname.starts_with(&obj_start) && fname.ends_with(".o") {
                return true;
            }

            // Otherwise if this is *not* a rust object and we're skipping
            // objects then skip this file
            if skip_objects && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
                return true;
            }

            // ok, don't skip this
            false
        })
    }

    fn update_symbols(&mut self) {}

    fn build(mut self) {
        enum BuilderKind {
            Bsd(ar::Builder<File>),
            Gnu(ar::GnuBuilder<File>),
        }

        let sess = self.sess;

        let mut symbol_table = BTreeMap::new();

        let mut entries = Vec::new();

        for (entry_name, entry) in self.entries {
            // FIXME only read the symbol table of the object files to avoid having to keep all
            // object files in memory at once, or read them twice.
            let data = match entry {
                ArchiveEntry::FromArchive { archive_index, entry_index } => {
                    // FIXME read symbols from symtab
                    use std::io::Read;
                    let (ref _src_archive_path, ref mut src_archive) =
                        self.src_archives[archive_index];
                    let mut entry = src_archive.jump_to_entry(entry_index).unwrap();
                    let mut data = Vec::new();
                    entry.read_to_end(&mut data).unwrap();
                    data
                }
                ArchiveEntry::File(file) => std::fs::read(file).unwrap_or_else(|err| {
                    sess.fatal(&format!(
                        "error while reading object file during archive building: {}",
                        err
                    ));
                }),
            };

            if !self.no_builtin_ranlib {
                match object::File::parse(&*data) {
                    Ok(object) => {
                        symbol_table.insert(
                            entry_name.as_bytes().to_vec(),
                            object
                                .symbols()
                                .filter_map(|symbol| {
                                    if symbol.is_undefined()
                                        || symbol.is_local()
                                        || symbol.kind() != SymbolKind::Data
                                            && symbol.kind() != SymbolKind::Text
                                            && symbol.kind() != SymbolKind::Tls
                                    {
                                        None
                                    } else {
                                        symbol.name().map(|name| name.as_bytes().to_vec()).ok()
                                    }
                                })
                                .collect::<Vec<_>>(),
                        );
                    }
                    Err(err) => {
                        let err = err.to_string();
                        if err == "Unknown file magic" {
                            // Not an object file; skip it.
                        } else {
                            sess.fatal(&format!(
                                "error parsing `{}` during archive creation: {}",
                                entry_name, err
                            ));
                        }
                    }
                }
            }

            entries.push((entry_name, data));
        }

        let mut builder = if self.use_gnu_style_archive {
            BuilderKind::Gnu(
                ar::GnuBuilder::new(
                    File::create(&self.dst).unwrap_or_else(|err| {
                        sess.fatal(&format!(
                            "error opening destination during archive building: {}",
                            err
                        ));
                    }),
                    entries.iter().map(|(name, _)| name.as_bytes().to_vec()).collect(),
                    ar::GnuSymbolTableFormat::Size32,
                    symbol_table,
                )
                .unwrap(),
            )
        } else {
            BuilderKind::Bsd(
                ar::Builder::new(
                    File::create(&self.dst).unwrap_or_else(|err| {
                        sess.fatal(&format!(
                            "error opening destination during archive building: {}",
                            err
                        ));
                    }),
                    symbol_table,
                )
                .unwrap(),
            )
        };

        // Add all files
        for (entry_name, data) in entries.into_iter() {
            let header = ar::Header::new(entry_name.into_bytes(), data.len() as u64);
            match builder {
                BuilderKind::Bsd(ref mut builder) => builder.append(&header, &mut &*data).unwrap(),
                BuilderKind::Gnu(ref mut builder) => builder.append(&header, &mut &*data).unwrap(),
            }
        }

        // Finalize archive
        std::mem::drop(builder);

        if self.no_builtin_ranlib {
            let ranlib = crate::toolchain::get_toolchain_binary(self.sess, "ranlib");

            // Run ranlib to be able to link the archive
            let status = std::process::Command::new(ranlib)
                .arg(self.dst)
                .status()
                .expect("Couldn't run ranlib");

            if !status.success() {
                self.sess.fatal(&format!("Ranlib exited with code {:?}", status.code()));
            }
        }
    }

    fn inject_dll_import_lib(
        &mut self,
        _lib_name: &str,
        _dll_imports: &[rustc_middle::middle::cstore::DllImport],
        _tmpdir: &rustc_data_structures::temp_dir::MaybeTempDir,
    ) {
        bug!("injecting dll imports is not supported");
    }
}

impl<'a> ArArchiveBuilder<'a> {
    fn add_archive<F>(&mut self, archive_path: PathBuf, mut skip: F) -> std::io::Result<()>
    where
        F: FnMut(&str) -> bool + 'static,
    {
        let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
        let archive_index = self.src_archives.len();

        let mut i = 0;
        while let Some(entry) = archive.next_entry() {
            let entry = entry?;
            let file_name = String::from_utf8(entry.header().identifier().to_vec())
                .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;
            if !skip(&file_name) {
                self.entries
                    .push((file_name, ArchiveEntry::FromArchive { archive_index, entry_index: i }));
            }
            i += 1;
        }

        self.src_archives.push((archive_path, archive));
        Ok(())
    }
}
<commit_msg>Auto merge of #88559 - bjorn3:archive_logic_dedup, r=cjgillot<commit_after>//! Creation of ar archives like for the lib and staticlib crate type

use std::collections::BTreeMap;
use std::fs::File;
use std::path::{Path, PathBuf};

use rustc_codegen_ssa::back::archive::ArchiveBuilder;
use rustc_session::Session;

use object::{Object, ObjectSymbol, SymbolKind};

#[derive(Debug)]
enum ArchiveEntry {
    FromArchive { archive_index: usize, entry_index: usize },
    File(PathBuf),
}

pub(crate) struct ArArchiveBuilder<'a> {
    sess: &'a Session,
    dst: PathBuf,
    use_gnu_style_archive: bool,
    no_builtin_ranlib: bool,

    src_archives: Vec<(PathBuf, ar::Archive<File>)>,
    // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
    // the end of an archive for linkers to not get confused.
    entries: Vec<(String, ArchiveEntry)>,
}

impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
    fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self {
        let (src_archives, entries) = if let Some(input) = input {
            let mut archive = ar::Archive::new(File::open(input).unwrap());
            let mut entries = Vec::new();

            let mut i = 0;
            while let Some(entry) = archive.next_entry() {
                let entry = entry.unwrap();
                entries.push((
                    String::from_utf8(entry.header().identifier().to_vec()).unwrap(),
                    ArchiveEntry::FromArchive { archive_index: 0, entry_index: i },
                ));
                i += 1;
            }

            (vec![(input.to_owned(), archive)], entries)
        } else {
            (vec![], Vec::new())
        };

        ArArchiveBuilder {
            sess,
            dst: output.to_path_buf(),
            use_gnu_style_archive: sess.target.archive_format == "gnu",
            // FIXME fix builtin ranlib on macOS
            no_builtin_ranlib: sess.target.is_like_osx,

            src_archives,
            entries,
        }
    }

    fn src_files(&mut self) -> Vec<String> {
        self.entries.iter().map(|(name, _)| name.clone()).collect()
    }

    fn remove_file(&mut self, name: &str) {
        let index = self
            .entries
            .iter()
            .position(|(entry_name, _)| entry_name == name)
            .expect("Tried to remove file not existing in src archive");
        self.entries.remove(index);
    }

    fn add_file(&mut self, file: &Path) {
        self.entries.push((
            file.file_name().unwrap().to_str().unwrap().to_string(),
            ArchiveEntry::File(file.to_owned()),
        ));
    }

    fn add_archive<F>(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()>
    where
        F: FnMut(&str) -> bool + 'static,
    {
        let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
        let archive_index = self.src_archives.len();

        let mut i = 0;
        while let Some(entry) = archive.next_entry() {
            let entry = entry?;
            let file_name = String::from_utf8(entry.header().identifier().to_vec())
                .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;
            if !skip(&file_name) {
                self.entries
                    .push((file_name, ArchiveEntry::FromArchive { archive_index, entry_index: i }));
            }
            i += 1;
        }

        self.src_archives.push((archive_path.to_owned(), archive));
        Ok(())
    }

    fn update_symbols(&mut self) {}

    fn build(mut self) {
        enum BuilderKind {
            Bsd(ar::Builder<File>),
            Gnu(ar::GnuBuilder<File>),
        }

        let sess = self.sess;

        let mut symbol_table = BTreeMap::new();

        let mut entries = Vec::new();

        for (entry_name, entry) in self.entries {
            // FIXME only read the symbol table of the object files to avoid having to keep all
            // object files in memory at once, or read them twice.
            let data = match entry {
                ArchiveEntry::FromArchive { archive_index, entry_index } => {
                    // FIXME read symbols from symtab
                    use std::io::Read;
                    let (ref _src_archive_path, ref mut src_archive) =
                        self.src_archives[archive_index];
                    let mut entry = src_archive.jump_to_entry(entry_index).unwrap();
                    let mut data = Vec::new();
                    entry.read_to_end(&mut data).unwrap();
                    data
                }
                ArchiveEntry::File(file) => std::fs::read(file).unwrap_or_else(|err| {
                    sess.fatal(&format!(
                        "error while reading object file during archive building: {}",
                        err
                    ));
                }),
            };

            if !self.no_builtin_ranlib {
                match object::File::parse(&*data) {
                    Ok(object) => {
                        symbol_table.insert(
                            entry_name.as_bytes().to_vec(),
                            object
                                .symbols()
                                .filter_map(|symbol| {
                                    if symbol.is_undefined()
                                        || symbol.is_local()
                                        || symbol.kind() != SymbolKind::Data
                                            && symbol.kind() != SymbolKind::Text
                                            && symbol.kind() != SymbolKind::Tls
                                    {
                                        None
                                    } else {
                                        symbol.name().map(|name| name.as_bytes().to_vec()).ok()
                                    }
                                })
                                .collect::<Vec<_>>(),
                        );
                    }
                    Err(err) => {
                        let err = err.to_string();
                        if err == "Unknown file magic" {
                            // Not an object file; skip it.
                        } else {
                            sess.fatal(&format!(
                                "error parsing `{}` during archive creation: {}",
                                entry_name, err
                            ));
                        }
                    }
                }
            }

            entries.push((entry_name, data));
        }

        let mut builder = if self.use_gnu_style_archive {
            BuilderKind::Gnu(
                ar::GnuBuilder::new(
                    File::create(&self.dst).unwrap_or_else(|err| {
                        sess.fatal(&format!(
                            "error opening destination during archive building: {}",
                            err
                        ));
                    }),
                    entries.iter().map(|(name, _)| name.as_bytes().to_vec()).collect(),
                    ar::GnuSymbolTableFormat::Size32,
                    symbol_table,
                )
                .unwrap(),
            )
        } else {
            BuilderKind::Bsd(
                ar::Builder::new(
                    File::create(&self.dst).unwrap_or_else(|err| {
                        sess.fatal(&format!(
                            "error opening destination during archive building: {}",
                            err
                        ));
                    }),
                    symbol_table,
                )
                .unwrap(),
            )
        };

        // Add all files
        for (entry_name, data) in entries.into_iter() {
            let header = ar::Header::new(entry_name.into_bytes(), data.len() as u64);
            match builder {
                BuilderKind::Bsd(ref mut builder) => builder.append(&header, &mut &*data).unwrap(),
                BuilderKind::Gnu(ref mut builder) => builder.append(&header, &mut &*data).unwrap(),
            }
        }

        // Finalize archive
        std::mem::drop(builder);

        if self.no_builtin_ranlib {
            let ranlib = crate::toolchain::get_toolchain_binary(self.sess, "ranlib");

            // Run ranlib to be able to link the archive
            let status = std::process::Command::new(ranlib)
                .arg(self.dst)
                .status()
                .expect("Couldn't run ranlib");

            if !status.success() {
                self.sess.fatal(&format!("Ranlib exited with code {:?}", status.code()));
            }
        }
    }

    fn inject_dll_import_lib(
        &mut self,
        _lib_name: &str,
        _dll_imports: &[rustc_middle::middle::cstore::DllImport],
        _tmpdir: &rustc_data_structures::temp_dir::MaybeTempDir,
    ) {
        bug!("injecting dll imports is not supported");
    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::fs::File;
use std::str::FromStr;
use std::fmt;
use std::path::PathBuf;

#[derive(PartialEq)]
pub enum BatteryStatus {
    CHARGING, DISCHARGING, FULL
}

pub struct Battery {
    pub name: String,
    pub charge_now: u32,
    pub charge_full: u32,
    pub charge_full_design: u32,
    pub cycle_count: u32,
    pub charge_status: BatteryStatus,
    pub current_now: u32,
    pub current_avg: u32,
}

impl FromStr for BatteryStatus {
    type Err = ();

    fn from_str(s: &str) -> Result<BatteryStatus, ()> {
        match s {
            "Charging"    => Ok(BatteryStatus::CHARGING),
            "Discharging" => Ok(BatteryStatus::DISCHARGING),
            "Full"        => Ok(BatteryStatus::FULL),
            _  => Err(()),
        }
    }
}

impl fmt::Display for BatteryStatus {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let string = match *self {
            BatteryStatus::CHARGING    => "Charging",
            BatteryStatus::DISCHARGING => "Discharging",
            BatteryStatus::FULL        => "Full",
        };
        write!(f, "{}", string)
    }
}

impl Battery {
    pub fn initialize(name: &str) -> Option<Battery> {
        let charge_now = match read_battery_data(name, "charge_now") {
            Some(data) => data,
            None => return None,
        };
        let charge_full = match read_battery_data(name, "charge_full") {
            Some(data) => data,
            None => return None,
        };
        let charge_full_design = match read_battery_data(name, "charge_full_design") {
            Some(data) => data,
            None => return None,
        };
        let cycle_count = match read_battery_data(name, "cycle_count") {
            Some(data) => data,
            None => return None,
        };
        let current_status = match read_battery_data(name, "status") {
            Some(data) => data,
            None => return None,
        };
        let current_now = match read_battery_data(name, "current_now") {
            Some(data) => data,
            None => return None,
        };
        let current_avg = match read_battery_data(name, "current_avg") {
            Some(data) => data,
            None => return None,
        };
        return Some(Battery {
            name: name.to_owned(),
            charge_now: charge_now,
            charge_full: charge_full,
            charge_full_design: charge_full_design,
            cycle_count: cycle_count,
            charge_status: current_status,
            current_now: current_now,
            current_avg: current_avg,
        });
    }
    pub fn time_remaining(&self) -> String {
        let time_left: f64 = match self.charge_status {
            BatteryStatus::CHARGING => {
                (self.charge_full as f64 - self.charge_now as f64) / self.current_avg as f64
            },
            BatteryStatus::DISCHARGING => {
                (self.charge_now as f64 / self.current_avg as f64)
            },
            _ => 0.0
        };
        let time_left = time_left;
        let hours_left = time_left as u8;
        let mins_left = ((time_left - hours_left as f64) * 60.0) as u8;
        format!("{:02.0}:{:02.0}", hours_left, mins_left)
    }
    pub fn percent_remaining(&self) -> u32 {
        (self.charge_now * 100) / self.charge_full
    }
    pub fn health(&self) -> u32 {
        (self.charge_full * 100) / self.charge_full_design
    }
    pub fn abs_percent_remaining(&self) -> u32 {
        (self.charge_now * 100) / self.charge_full_design
    }
}

fn read_battery_data<T:FromStr>(name: &str, path: &str) -> Option<T> where <T as FromStr>::Err: fmt::Debug {
   return read_from_file(get_full_path(name, path));
}

fn get_full_path(name: &str, file: &str) -> PathBuf {
    let path: PathBuf = ["/sys", "class", "power_supply", name, file]
        .iter()
        .collect();
    return path;
}

fn read_from_file<T:FromStr>(path: PathBuf) -> Option<T> where <T as FromStr>::Err: fmt::Debug {
    let mut f = match File::open(path.as_path()) {
        Ok(f) => f,
        Err(err) => {
            eprintln!("Unable to open {:?}. Error: {}", path, err);
            return None;
        }
    };

    let mut contents = String::new();
    match f.read_to_string(&mut contents) {
        Ok(_) => (),
        Err(err) => {
            eprintln!("Error reading. Error: {}", err);
            return None;
        }
    };
    return match contents.trim().parse::<T>() {
        Ok(val) => Some(val),
        Err(_) => None,
    }
}
<commit_msg>Cap battery displayed percentage at 100%<commit_after>use std::io::Read;
use std::fs::File;
use std::str::FromStr;
use std::fmt;
use std::path::PathBuf;

#[derive(PartialEq)]
pub enum BatteryStatus {
    CHARGING, DISCHARGING, FULL
}

pub struct Battery {
    pub name: String,
    pub charge_now: u32,
    pub charge_full: u32,
    pub charge_full_design: u32,
    pub cycle_count: u32,
    pub charge_status: BatteryStatus,
    pub current_now: u32,
    pub current_avg: u32,
}

impl FromStr for BatteryStatus {
    type Err = ();

    fn from_str(s: &str) -> Result<BatteryStatus, ()> {
        match s {
            "Charging"    => Ok(BatteryStatus::CHARGING),
            "Discharging" => Ok(BatteryStatus::DISCHARGING),
            "Full"        => Ok(BatteryStatus::FULL),
            _  => Err(()),
        }
    }
}

impl fmt::Display for BatteryStatus {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let string = match *self {
            BatteryStatus::CHARGING    => "Charging",
            BatteryStatus::DISCHARGING => "Discharging",
            BatteryStatus::FULL        => "Full",
        };
        write!(f, "{}", string)
    }
}

impl Battery {
    pub fn initialize(name: &str) -> Option<Battery> {
        let charge_now = match read_battery_data(name, "charge_now") {
            Some(data) => data,
            None => return None,
        };
        let charge_full = match read_battery_data(name, "charge_full") {
            Some(data) => data,
            None => return None,
        };
        let charge_full_design = match read_battery_data(name, "charge_full_design") {
            Some(data) => data,
            None => return None,
        };
        let cycle_count = match read_battery_data(name, "cycle_count") {
            Some(data) => data,
            None => return None,
        };
        let current_status = match read_battery_data(name, "status") {
            Some(data) => data,
            None => return None,
        };
        let current_now = match read_battery_data(name, "current_now") {
            Some(data) => data,
            None => return None,
        };
        let current_avg = match read_battery_data(name, "current_avg") {
            Some(data) => data,
            None => return None,
        };
        return Some(Battery {
            name: name.to_owned(),
            charge_now: charge_now,
            charge_full: charge_full,
            charge_full_design: charge_full_design,
            cycle_count: cycle_count,
            charge_status: current_status,
            current_now: current_now,
            current_avg: current_avg,
        });
    }
    pub fn time_remaining(&self) -> String {
        let time_left: f64 = match self.charge_status {
            BatteryStatus::CHARGING => {
                (self.charge_full as f64 - self.charge_now as f64) / self.current_avg as f64
            },
            BatteryStatus::DISCHARGING => {
                (self.charge_now as f64 / self.current_avg as f64)
            },
            _ => 0.0
        };
        let time_left = time_left;
        let hours_left = time_left as u8;
        let mins_left = ((time_left - hours_left as f64) * 60.0) as u8;
        format!("{:02.0}:{:02.0}", hours_left, mins_left)
    }
    pub fn percent_remaining(&self) -> u32 {
        let percent = (self.charge_now * 100) / self.charge_full;
        if percent > 100 {
            return 100;
        }
        return percent;
    }
    pub fn health(&self) -> u32 {
        (self.charge_full * 100) / self.charge_full_design
    }
    pub fn abs_percent_remaining(&self) -> u32 {
        (self.charge_now * 100) / self.charge_full_design
    }
}

fn read_battery_data<T:FromStr>(name: &str, path: &str) -> Option<T> where <T as FromStr>::Err: fmt::Debug {
   return read_from_file(get_full_path(name, path));
}

fn get_full_path(name: &str, file: &str) -> PathBuf {
    let path: PathBuf = ["/sys", "class", "power_supply", name, file]
        .iter()
        .collect();
    return path;
}

fn read_from_file<T:FromStr>(path: PathBuf) -> Option<T> where <T as FromStr>::Err: fmt::Debug {
    let mut f = match File::open(path.as_path()) {
        Ok(f) => f,
        Err(err) => {
            eprintln!("Unable to open {:?}. Error: {}", path, err);
            return None;
        }
    };

    let mut contents = String::new();
    match f.read_to_string(&mut contents) {
        Ok(_) => (),
        Err(err) => {
            eprintln!("Error reading. Error: {}", err);
            return None;
        }
    };
    return match contents.trim().parse::<T>() {
        Ok(val) => Some(val),
        Err(_) => None,
    }
}
<|endoftext|>


<commit_before>use crate::dsl::{AsExpr, AsExprOf, SqlTypeOf};
use crate::expression::grouped::Grouped;
use crate::sql_types::{Inet, Jsonb, VarChar};

/// The return type of `lhs.ilike(rhs)`
pub type ILike<Lhs, Rhs> = Grouped<super::operators::ILike<Lhs, AsExprOf<Rhs, VarChar>>>;

/// The return type of `lhs.not_ilike(rhs)`
pub type NotILike<Lhs, Rhs> = Grouped<super::operators::NotILike<Lhs, AsExprOf<Rhs, VarChar>>>;

/// The return type of `lhs.similar_to(rhs)`
pub type SimilarTo<Lhs, Rhs> = Grouped<super::operators::SimilarTo<Lhs, AsExprOf<Rhs, VarChar>>>;

/// The return type of `lhs.not_similar_to(rhs)`
pub type NotSimilarTo<Lhs, Rhs> =
    Grouped<super::operators::NotSimilarTo<Lhs, AsExprOf<Rhs, VarChar>>>;

/// The return type of `lhs.is_not_distinct_from(rhs)`
pub type IsNotDistinctFrom<Lhs, Rhs> =
    Grouped<super::operators::IsNotDistinctFrom<Lhs, AsExpr<Rhs, Lhs>>>;

/// The return type of `lhs.is_distinct_from(rhs)`
pub type IsDistinctFrom<Lhs, Rhs> =
    Grouped<super::operators::IsDistinctFrom<Lhs, AsExpr<Rhs, Lhs>>>;

/// The return type of `lhs.overlaps_with(rhs)`
pub type OverlapsWith<Lhs, Rhs> = Grouped<super::operators::OverlapsWith<Lhs, AsExpr<Rhs, Lhs>>>;

/// The return type of `lhs.contains(rhs)` for array expressions
pub type ArrayContains<Lhs, Rhs> = Grouped<super::operators::Contains<Lhs, AsExpr<Rhs, Lhs>>>;

/// The return type of `lhs.contains(rhs)` for range expressions
pub type RangeContains<Lhs, Rhs> = Grouped<
    super::operators::Contains<
        Lhs,
        AsExprOf<Rhs, <SqlTypeOf<Lhs> as super::expression_methods::RangeHelper>::Inner>,
    >,
>;

/// The return type of `lhs.is_contained_by(rhs)`
pub type IsContainedBy<Lhs, Rhs> = Grouped<super::operators::IsContainedBy<Lhs, AsExpr<Rhs, Lhs>>>;

/// The return type of `expr.nulls_first()`
pub type NullsFirst<T> = super::operators::NullsFirst<T>;

/// The return type of `expr.nulls_last()`
pub type NullsLast<T> = super::operators::NullsLast<T>;

/// The return type of `expr.at_time_zone(tz)`
pub type AtTimeZone<Lhs, Rhs> =
    Grouped<super::date_and_time::AtTimeZone<Lhs, AsExprOf<Rhs, VarChar>>>;

/// The return type of `lsh.contains(rhs)`
pub type ContainsNet<Lhs, Rhs> = Grouped<super::operators::ContainsNet<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lsh.contains_or_eq(rhs)`
pub type ContainsNetLoose<Lhs, Rhs> =
    Grouped<super::operators::ContainsNetLoose<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lsh.is_contained_by(rhs)`
pub type IsContainedByNet<Lhs, Rhs> =
    Grouped<super::operators::IsContainedByNet<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lsh.is_contained_by_or_eq(rhs)`
pub type IsContainedByNetLoose<Lhs, Rhs> =
    Grouped<super::operators::IsContainedByNetLoose<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lhs.overlaps_with(rhs)`
pub type OverlapsWithNet<Lhs, Rhs> =
    Grouped<super::operators::OverlapsWith<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lsh.and(rhs)`
pub type AndNet<Lhs, Rhs> = Grouped<super::operators::AndNet<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lsh.or(rhs)`
pub type OrNet<Lhs, Rhs> = Grouped<super::operators::OrNet<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lsh.diff(rhs)`
pub type DifferenceNet<Lhs, Rhs> =
    Grouped<super::operators::DifferenceNet<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lsh.concat(rhs)`
pub type ConcatJsonb<Lhs, Rhs> = Grouped<super::operators::ConcatJsonb<Lhs, AsExprOf<Rhs, Jsonb>>>;

/// The return type of `lsh.contains(rhs)`
pub type HasKeyJsonb<Lhs, Rhs> =
    Grouped<super::operators::HasKeyJsonb<Lhs, AsExprOf<Rhs, VarChar>>>;
<commit_msg>fix method name in the comment<commit_after>use crate::dsl::{AsExpr, AsExprOf, SqlTypeOf};
use crate::expression::grouped::Grouped;
use crate::sql_types::{Inet, Jsonb, VarChar};

/// The return type of `lhs.ilike(rhs)`
pub type ILike<Lhs, Rhs> = Grouped<super::operators::ILike<Lhs, AsExprOf<Rhs, VarChar>>>;

/// The return type of `lhs.not_ilike(rhs)`
pub type NotILike<Lhs, Rhs> = Grouped<super::operators::NotILike<Lhs, AsExprOf<Rhs, VarChar>>>;

/// The return type of `lhs.similar_to(rhs)`
pub type SimilarTo<Lhs, Rhs> = Grouped<super::operators::SimilarTo<Lhs, AsExprOf<Rhs, VarChar>>>;

/// The return type of `lhs.not_similar_to(rhs)`
pub type NotSimilarTo<Lhs, Rhs> =
    Grouped<super::operators::NotSimilarTo<Lhs, AsExprOf<Rhs, VarChar>>>;

/// The return type of `lhs.is_not_distinct_from(rhs)`
pub type IsNotDistinctFrom<Lhs, Rhs> =
    Grouped<super::operators::IsNotDistinctFrom<Lhs, AsExpr<Rhs, Lhs>>>;

/// The return type of `lhs.is_distinct_from(rhs)`
pub type IsDistinctFrom<Lhs, Rhs> =
    Grouped<super::operators::IsDistinctFrom<Lhs, AsExpr<Rhs, Lhs>>>;

/// The return type of `lhs.overlaps_with(rhs)`
pub type OverlapsWith<Lhs, Rhs> = Grouped<super::operators::OverlapsWith<Lhs, AsExpr<Rhs, Lhs>>>;

/// The return type of `lhs.contains(rhs)` for array expressions
pub type ArrayContains<Lhs, Rhs> = Grouped<super::operators::Contains<Lhs, AsExpr<Rhs, Lhs>>>;

/// The return type of `lhs.contains(rhs)` for range expressions
pub type RangeContains<Lhs, Rhs> = Grouped<
    super::operators::Contains<
        Lhs,
        AsExprOf<Rhs, <SqlTypeOf<Lhs> as super::expression_methods::RangeHelper>::Inner>,
    >,
>;

/// The return type of `lhs.is_contained_by(rhs)`
pub type IsContainedBy<Lhs, Rhs> = Grouped<super::operators::IsContainedBy<Lhs, AsExpr<Rhs, Lhs>>>;

/// The return type of `expr.nulls_first()`
pub type NullsFirst<T> = super::operators::NullsFirst<T>;

/// The return type of `expr.nulls_last()`
pub type NullsLast<T> = super::operators::NullsLast<T>;

/// The return type of `expr.at_time_zone(tz)`
pub type AtTimeZone<Lhs, Rhs> =
    Grouped<super::date_and_time::AtTimeZone<Lhs, AsExprOf<Rhs, VarChar>>>;

/// The return type of `lsh.contains(rhs)`
pub type ContainsNet<Lhs, Rhs> = Grouped<super::operators::ContainsNet<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lsh.contains_or_eq(rhs)`
pub type ContainsNetLoose<Lhs, Rhs> =
    Grouped<super::operators::ContainsNetLoose<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lsh.is_contained_by(rhs)`
pub type IsContainedByNet<Lhs, Rhs> =
    Grouped<super::operators::IsContainedByNet<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lsh.is_contained_by_or_eq(rhs)`
pub type IsContainedByNetLoose<Lhs, Rhs> =
    Grouped<super::operators::IsContainedByNetLoose<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lhs.overlaps_with(rhs)`
pub type OverlapsWithNet<Lhs, Rhs> =
    Grouped<super::operators::OverlapsWith<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lsh.and(rhs)`
pub type AndNet<Lhs, Rhs> = Grouped<super::operators::AndNet<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lsh.or(rhs)`
pub type OrNet<Lhs, Rhs> = Grouped<super::operators::OrNet<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lsh.diff(rhs)`
pub type DifferenceNet<Lhs, Rhs> =
    Grouped<super::operators::DifferenceNet<Lhs, AsExprOf<Rhs, Inet>>>;

/// The return type of `lsh.concat(rhs)`
pub type ConcatJsonb<Lhs, Rhs> = Grouped<super::operators::ConcatJsonb<Lhs, AsExprOf<Rhs, Jsonb>>>;

/// The return type of `lsh.has_key(rhs)`
pub type HasKeyJsonb<Lhs, Rhs> =
    Grouped<super::operators::HasKeyJsonb<Lhs, AsExprOf<Rhs, VarChar>>>;
<|endoftext|>


<commit_before>use std::error::Error;
use std::io::Write;
use std::ops::Add;

use pg::{Pg, PgTypeMetadata, PgMetadataLookup};
use types::{self, FromSql, ToSql, ToSqlOutput, IsNull, Date, Interval, Time, Timestamp, Timestamptz};

primitive_impls!(Timestamptz -> (pg: (1184, 1185)));
primitive_impls!(Timestamptz);

#[cfg(feature = "quickcheck")]
mod quickcheck_impls;
mod std_time;
#[cfg(feature = "chrono")]
mod chrono;
#[cfg(feature = "deprecated-time")]
mod deprecated_time;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
/// Timestamps are represented in Postgres as a 64 bit signed integer representing the number of
/// microseconds since January 1st 2000. This struct is a dumb wrapper type, meant only to indicate
/// the integer's meaning.
pub struct PgTimestamp(pub i64);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
/// Dates are represented in Postgres as a 32 bit signed integer representing the number of julian
/// days since January 1st 2000. This struct is a dumb wrapper type, meant only to indicate the
/// integer's meaning.
pub struct PgDate(pub i32);

/// Time is represented in Postgres as a 64 bit signed integer representing the number of
/// microseconds since midnight. This struct is a dumb wrapper type, meant only to indicate the
/// integer's meaning.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct PgTime(pub i64);

/// Intervals in Postgres are separated into 3 parts. A 64 bit integer representing time in
/// microseconds, a 32 bit integer representing number of days, and a 32 bit integer
/// representing number of months. This struct is a dumb wrapper type, meant only to indicate the
/// meaning of these parts.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PgInterval {
    pub microseconds: i64,
    pub days: i32,
    pub months: i32,
}

impl PgInterval {
    pub fn new(microseconds: i64, days: i32, months: i32) -> Self {
        PgInterval {
            microseconds: microseconds,
            days: days,
            months: months,
        }
    }

    pub fn from_microseconds(microseconds: i64) -> Self {
        Self::new(microseconds, 0, 0)
    }

    pub fn from_days(days: i32) -> Self {
        Self::new(0, days, 0)
    }

    pub fn from_months(months: i32) -> Self {
        Self::new(0, 0, months)
    }
}

queryable_impls!(Date -> PgDate);
queryable_impls!(Time -> PgTime);
queryable_impls!(Timestamp -> PgTimestamp);
queryable_impls!(Timestamptz -> PgTimestamp);
expression_impls!(Date -> PgDate);
expression_impls!(Time -> PgTime);
expression_impls!(Timestamp -> PgTimestamp);
expression_impls!(Timestamptz -> PgTimestamp);

primitive_impls!(Interval -> (PgInterval, pg: (1186, 1187)));

use types::HasSqlType;

impl HasSqlType<types::Date> for Pg {
    fn metadata(_: &PgMetadataLookup) -> PgTypeMetadata {
        PgTypeMetadata {
            oid: 1082,
            array_oid: 1182,
        }
    }
}

impl HasSqlType<types::Time> for Pg {
    fn metadata(_: &PgMetadataLookup) -> PgTypeMetadata {
        PgTypeMetadata {
            oid: 1083,
            array_oid: 1183,
        }
    }
}

impl HasSqlType<types::Timestamp> for Pg {
    fn metadata(_: &PgMetadataLookup) -> PgTypeMetadata {
        PgTypeMetadata {
            oid: 1114,
            array_oid: 1115,
        }
    }
}

impl ToSql<types::Timestamp, Pg> for PgTimestamp {
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        ToSql::<types::BigInt, Pg>::to_sql(&self.0, out)
    }
}

impl FromSql<types::Timestamp, Pg> for PgTimestamp {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        FromSql::<types::BigInt, Pg>::from_sql(bytes)
            .map(PgTimestamp)
    }
}

impl ToSql<types::Timestamptz, Pg> for PgTimestamp {
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        ToSql::<types::Timestamp, Pg>::to_sql(self, out)
    }
}

impl FromSql<types::Timestamptz, Pg> for PgTimestamp {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        FromSql::<types::Timestamp, Pg>::from_sql(bytes)
    }
}

impl ToSql<types::Date, Pg> for PgDate {
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        ToSql::<types::Integer, Pg>::to_sql(&self.0, out)
    }
}

impl FromSql<types::Date, Pg> for PgDate {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        FromSql::<types::Integer, Pg>::from_sql(bytes)
            .map(PgDate)
    }
}

impl ToSql<types::Time, Pg> for PgTime {
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        ToSql::<types::BigInt, Pg>::to_sql(&self.0, out)
    }
}

impl FromSql<types::Time, Pg> for PgTime {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        FromSql::<types::BigInt, Pg>::from_sql(bytes)
            .map(PgTime)
    }
}

impl ToSql<types::Interval, Pg> for PgInterval {
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        try!(ToSql::<types::BigInt, Pg>::to_sql(&self.microseconds, out));
        try!(ToSql::<types::Integer, Pg>::to_sql(&self.days, out));
        try!(ToSql::<types::Integer, Pg>::to_sql(&self.months, out));
        Ok(IsNull::No)
    }
}

impl FromSql<types::Interval, Pg> for PgInterval {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        let bytes = not_none!(bytes);
        Ok(PgInterval {
            microseconds: try!(FromSql::<types::BigInt, Pg>::from_sql(Some(&bytes[..8]))),
            days: try!(FromSql::<types::Integer, Pg>::from_sql(Some(&bytes[8..12]))),
            months: try!(FromSql::<types::Integer, Pg>::from_sql(Some(&bytes[12..16]))),
        })
    }
}

impl Add<PgInterval> for PgInterval {
    type Output = PgInterval;

    fn add(self, other: PgInterval) -> Self::Output {
        PgInterval {
            microseconds: self.microseconds + other.microseconds,
            days: self.days + other.days,
            months: self.months + other.months,
        }
    }
}
<commit_msg>Remove some manual HasSqlType impls<commit_after>use std::error::Error;
use std::io::Write;
use std::ops::Add;

use pg::Pg;
use types::{self, FromSql, ToSql, ToSqlOutput, IsNull, Date, Interval, Time, Timestamp, Timestamptz};

primitive_impls!(Date -> (pg: (1082, 1182)));
primitive_impls!(Time -> (pg: (1083, 1183)));
primitive_impls!(Timestamp -> (pg: (1114, 1115)));
primitive_impls!(Timestamptz -> (pg: (1184, 1185)));
primitive_impls!(Timestamptz);

#[cfg(feature = "quickcheck")]
mod quickcheck_impls;
mod std_time;
#[cfg(feature = "chrono")]
mod chrono;
#[cfg(feature = "deprecated-time")]
mod deprecated_time;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
/// Timestamps are represented in Postgres as a 64 bit signed integer representing the number of
/// microseconds since January 1st 2000. This struct is a dumb wrapper type, meant only to indicate
/// the integer's meaning.
pub struct PgTimestamp(pub i64);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
/// Dates are represented in Postgres as a 32 bit signed integer representing the number of julian
/// days since January 1st 2000. This struct is a dumb wrapper type, meant only to indicate the
/// integer's meaning.
pub struct PgDate(pub i32);

/// Time is represented in Postgres as a 64 bit signed integer representing the number of
/// microseconds since midnight. This struct is a dumb wrapper type, meant only to indicate the
/// integer's meaning.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct PgTime(pub i64);

/// Intervals in Postgres are separated into 3 parts. A 64 bit integer representing time in
/// microseconds, a 32 bit integer representing number of days, and a 32 bit integer
/// representing number of months. This struct is a dumb wrapper type, meant only to indicate the
/// meaning of these parts.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PgInterval {
    pub microseconds: i64,
    pub days: i32,
    pub months: i32,
}

impl PgInterval {
    pub fn new(microseconds: i64, days: i32, months: i32) -> Self {
        PgInterval {
            microseconds: microseconds,
            days: days,
            months: months,
        }
    }

    pub fn from_microseconds(microseconds: i64) -> Self {
        Self::new(microseconds, 0, 0)
    }

    pub fn from_days(days: i32) -> Self {
        Self::new(0, days, 0)
    }

    pub fn from_months(months: i32) -> Self {
        Self::new(0, 0, months)
    }
}

queryable_impls!(Date -> PgDate);
queryable_impls!(Time -> PgTime);
queryable_impls!(Timestamp -> PgTimestamp);
queryable_impls!(Timestamptz -> PgTimestamp);
expression_impls!(Date -> PgDate);
expression_impls!(Time -> PgTime);
expression_impls!(Timestamp -> PgTimestamp);
expression_impls!(Timestamptz -> PgTimestamp);

primitive_impls!(Interval -> (PgInterval, pg: (1186, 1187)));

impl ToSql<types::Timestamp, Pg> for PgTimestamp {
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        ToSql::<types::BigInt, Pg>::to_sql(&self.0, out)
    }
}

impl FromSql<types::Timestamp, Pg> for PgTimestamp {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        FromSql::<types::BigInt, Pg>::from_sql(bytes)
            .map(PgTimestamp)
    }
}

impl ToSql<types::Timestamptz, Pg> for PgTimestamp {
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        ToSql::<types::Timestamp, Pg>::to_sql(self, out)
    }
}

impl FromSql<types::Timestamptz, Pg> for PgTimestamp {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        FromSql::<types::Timestamp, Pg>::from_sql(bytes)
    }
}

impl ToSql<types::Date, Pg> for PgDate {
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        ToSql::<types::Integer, Pg>::to_sql(&self.0, out)
    }
}

impl FromSql<types::Date, Pg> for PgDate {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        FromSql::<types::Integer, Pg>::from_sql(bytes)
            .map(PgDate)
    }
}

impl ToSql<types::Time, Pg> for PgTime {
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        ToSql::<types::BigInt, Pg>::to_sql(&self.0, out)
    }
}

impl FromSql<types::Time, Pg> for PgTime {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        FromSql::<types::BigInt, Pg>::from_sql(bytes)
            .map(PgTime)
    }
}

impl ToSql<types::Interval, Pg> for PgInterval {
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        try!(ToSql::<types::BigInt, Pg>::to_sql(&self.microseconds, out));
        try!(ToSql::<types::Integer, Pg>::to_sql(&self.days, out));
        try!(ToSql::<types::Integer, Pg>::to_sql(&self.months, out));
        Ok(IsNull::No)
    }
}

impl FromSql<types::Interval, Pg> for PgInterval {
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        let bytes = not_none!(bytes);
        Ok(PgInterval {
            microseconds: try!(FromSql::<types::BigInt, Pg>::from_sql(Some(&bytes[..8]))),
            days: try!(FromSql::<types::Integer, Pg>::from_sql(Some(&bytes[8..12]))),
            months: try!(FromSql::<types::Integer, Pg>::from_sql(Some(&bytes[12..16]))),
        })
    }
}

impl Add<PgInterval> for PgInterval {
    type Output = PgInterval;

    fn add(self, other: PgInterval) -> Self::Output {
        PgInterval {
            microseconds: self.microseconds + other.microseconds,
            days: self.days + other.days,
            months: self.months + other.months,
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>move one list unit test to doctests<commit_after><|endoftext|>


<commit_before>//! A reverse proxy application.
//!
//! This module provides a reverse proxy implementation for the Open
//! Matchmaking project.
//!
//! The purposes of the application  are handling client connections, applying
//! a middleware with checks for a token when it was specified and communicating
//! with a message broker for getting responses from microservices in the certain
//! format.
//!

use std::cell::{RefCell};
use std::collections::{HashMap};
use std::error::{Error};
use std::net::{SocketAddr};
use std::rc::{Rc};

use engine::{Engine};
use auth::middleware::{Middleware, EmptyMiddleware};
use auth::token::middleware::{JwtTokenMiddleware};

use cli::{CliOptions};
use futures::sync::{mpsc};
use futures::{Future, Sink};
use futures::stream::{Stream, SplitSink};
use tokio::net::{TcpListener, TcpStream};
use tokio::reactor::{Handle};
use tokio::runtime::{run};
use tokio_current_thread::{spawn};
use tokio_tungstenite::{accept_async};
use tokio_tungstenite::{WebSocketStream};
use tungstenite::protocol::{Message};

/// A reverse proxy application.
pub struct Proxy {
    engine: Rc<RefCell<Box<Engine>>>,
    connections: Rc<RefCell<HashMap<SocketAddr, mpsc::UnboundedSender<Message>>>>,
    auth_middleware: Rc<RefCell<Box<Middleware>>>,
}

impl Proxy {
    /// Returns a new instance of a reverse proxy application.
    pub fn new(cli: &CliOptions, engine: Box<Engine>) -> Proxy {
        let auth_middleware: Box<Middleware> = match cli.validate {
            true => Box::new(JwtTokenMiddleware::new(cli)),
               _ => Box::new(EmptyMiddleware::new(cli))
        };

        Proxy {
            engine: Rc::new(RefCell::new(engine)),
            connections: Rc::new(RefCell::new(HashMap::new())),
            auth_middleware: Rc::new(RefCell::new(auth_middleware)),
        }
    }

    /// Run the server on the specified address and port.
    pub fn run(&self, address: SocketAddr) {
        let handle = Handle::default();
        let listener = TcpListener::bind(&address).unwrap();
        println!("Listening on: {}", address);

        let server = listener.incoming().for_each(|(stream, addr)| {
            let engine_local = self.engine.clone();
            let connections_local = self.connections.clone();
            let auth_middleware_local = self.auth_middleware.clone();
            let handle_local = handle.clone();

            accept_async(stream)
                // Process the messages
                .and_then(move |ws_stream| {
                    // Create a channel for the stream, which other sockets will use to
                    // send us messages. It could be used for broadcasting your data to
                    // another users in the future.
                    let (tx, rx) = mpsc::unbounded();
                    connections_local.borrow_mut().insert(addr, tx);

                    // Split the WebSocket stream so that it will be possible to work
                    // with the reading and writing halves separately.
                    let (sink, stream) = ws_stream.split();

                    // Read and process each message
                    let handle_inner = handle_local.clone();
                    let connections_inner = connections_local.clone();
                    let ws_reader = stream.for_each(move |message: Message| {

                        // Get references to required components
                        let addr_nested = addr.clone();
                        let engine_nested = engine_local.clone();
                        let connections_nested = connections_inner.clone();
                        let transmitter_nested = &connections_nested.borrow_mut()[&addr_nested];
                        let transmitter_nested2 = transmitter_nested.clone();

                        // 1. Deserialize message into JSON
                        let json_message = match engine_local.borrow().deserialize_message(&message) {
                            Ok(json_message) => json_message,
                            Err(err) => {
                                let formatted_error = format!("{}", err);
                                let error_message = engine_nested.borrow().wrap_an_error(formatted_error.as_str());
                                transmitter_nested.unbounded_send(error_message).unwrap();
                                return Ok(())
                            }
                        };

                        // 2. Apply a middleware to each incoming message
                        let auth_future = auth_middleware_local.borrow()
                            .process_request(json_message.clone());

                        // 3. Put request into a queue in RabbitMQ and receive the response
                        let rabbitmq_future = engine_local.borrow().handle(
                            json_message.clone(), transmitter_nested.clone(), &handle_inner
                        );

                        let processing_request_future = auth_future
                            .and_then(move |_| rabbitmq_future)
                            .map_err(move |err| {
                                let formatted_error = format!("{}", err);
                                let error_message = engine_nested.borrow().wrap_an_error(formatted_error.as_str());
                                transmitter_nested2.unbounded_send(error_message).unwrap();
                                ()
                            });

                        spawn(processing_request_future);
                        Ok(())
                    });

                    // Write back prepared responses
                    let ws_writer = rx.fold(sink, |mut sink, msg| -> Result<SplitSink<WebSocketStream<TcpStream>>, ()> {
                        sink.start_send(msg).unwrap();
                        Ok(sink)
                    });

                    // Wait for either half to be done to tear down the other
                    let connection = ws_reader.map(|_| ()).map_err(|_| ())
                                              .select(ws_writer.map(|_| ()).map_err(|_| ()));

                    // Close the connection after using
                    spawn(connection.then(move |_| {
                        connections_local.borrow_mut().remove(&addr);
                        debug!("Connection {} closed.", addr);
                        Ok(())
                    }));

                    Ok(())
                })
                // An error occurred during the WebSocket handshake
                .or_else(|err| {
                    debug!("{}", err.description());
                    Ok(())
                })
        });

        // Run the server
        run(|_| server);
    }
}
<commit_msg>Fixed code after tokio-tungstenite changes<commit_after>//! A reverse proxy application.
//!
//! This module provides a reverse proxy implementation for the Open
//! Matchmaking project.
//!
//! The purposes of the application  are handling client connections, applying
//! a middleware with checks for a token when it was specified and communicating
//! with a message broker for getting responses from microservices in the certain
//! format.
//!

use std::collections::{HashMap};
use std::error::{Error};
use std::net::{SocketAddr};
use std::sync::{Arc, Mutex, RwLock};

use cli::{CliOptions};
use futures::sync::{mpsc};
use futures::{Future, Sink};
use futures::stream::{Stream};
use tokio::net::{TcpListener};
use tokio::reactor::{Handle};
use tokio::runtime::{run};
use tokio_current_thread::{spawn};
use tokio_tungstenite::{accept_async};
use tungstenite::protocol::{Message};

use engine::{Engine};
use auth::middleware::{Middleware, EmptyMiddleware};
use auth::token::middleware::{JwtTokenMiddleware};

/// A reverse proxy application.
pub struct Proxy {
    engine: Arc<RwLock<Box<Engine>>>,
    connections: Arc<Mutex<HashMap<SocketAddr, mpsc::UnboundedSender<Message>>>>,
    auth_middleware: Arc<RwLock<Box<Middleware>>>,
}

impl Proxy {
    /// Returns a new instance of a reverse proxy application.
    pub fn new(cli: &CliOptions, engine: Box<Engine>) -> Proxy {
        let auth_middleware: Box<Middleware> = match cli.validate {
            true => Box::new(JwtTokenMiddleware::new(cli)),
               _ => Box::new(EmptyMiddleware::new(cli))
        };

        Proxy {
            engine: Arc::new(RwLock::new(engine)),
            connections: Arc::new(Mutex::new(HashMap::new())),
            auth_middleware: Arc::new(RwLock::new(auth_middleware)),
        }
    }

    /// Run the server on the specified address and port.
    pub fn run(&self, address: SocketAddr) {
        let handle = Handle::default();
        let listener = TcpListener::bind(&address).unwrap();
        println!("Listening on: {}", address);

        let server = listener.incoming().for_each(move |stream| {
            let addr = stream.peer_addr().expect("Connected stream should have a peer address.");

            let engine_local = self.engine.clone();
            let connections_local = self.connections.clone();
            let auth_middleware_local = self.auth_middleware.clone();
            let handle_local = handle.clone();

            accept_async(stream)
                // Process the messages
                .and_then(move |ws_stream| {
                    // Create a channel for the stream, which other sockets will use to
                    // send us messages. It could be used for broadcasting your data to
                    // another users in the future.
                    let (tx, rx) = mpsc::unbounded();
                    connections_local.lock().unwrap().insert(addr, tx);

                    // Split the WebSocket stream so that it will be possible to work
                    // with the reading and writing halves separately.
                    let (sink, stream) = ws_stream.split();

                    // Read and process each message
                    let handle_inner = handle_local.clone();
                    let connections_inner = connections_local.clone();
                    let ws_reader = stream.for_each(move |message: Message| {

                        // Get references to required components
                        let addr_nested = addr.clone();
                        let engine_nested = engine_local.clone();
                        let connections_nested = connections_inner.clone();
                        let transmitter_nested = &connections_nested.clone().lock().unwrap()[&addr_nested];
                        let transmitter_nested2 = transmitter_nested.clone();

                        // 1. Deserialize message into JSON
                        let json_message = match engine_local.read().unwrap().deserialize_message(&message) {
                            Ok(json_message) => json_message,
                            Err(err) => {
                                let formatted_error = format!("{}", err);
                                let error_message = engine_nested.read().unwrap().wrap_an_error(formatted_error.as_str());
                                transmitter_nested.unbounded_send(error_message).unwrap();
                                return Ok(())
                            }
                        };

                        // 2. Apply a middleware to each incoming message
                        let auth_future = auth_middleware_local.read().unwrap()
                            .process_request(json_message.clone());

                        // 3. Put request into a queue in RabbitMQ and receive the response
                        let rabbitmq_future = engine_local.read().unwrap().handle(
                            json_message.clone(), transmitter_nested.clone(), &handle_inner
                        );

                        let processing_request_future = auth_future
                            .and_then(move |_| rabbitmq_future)
                            .map_err(move |err| {
                                let formatted_error = format!("{}", err);
                                let error_message = engine_nested.read().unwrap().wrap_an_error(formatted_error.as_str());
                                transmitter_nested2.unbounded_send(error_message).unwrap();
                                ()
                            });

                        spawn(processing_request_future);
                        Ok(())
                    });

                    // Write back prepared responses
                    let ws_writer = rx.fold(sink, |mut sink, msg| {
                        sink.start_send(msg).unwrap();
                        Ok(sink)
                    });

                    // Wait for either half to be done to tear down the other
                    let connection = ws_reader.map(|_| ()).map_err(|_| ())
                                              .select(ws_writer.map(|_| ()).map_err(|_| ()));

                    // Close the connection after using
                    spawn(connection.then(move |_| {
                        connections_inner.lock().unwrap().remove(&addr);
                        debug!("Connection {} closed.", addr);
                        Ok(())
                    }));

                    Ok(())
                })
                // An error occurred during the WebSocket handshake
                .or_else(|err| {
                    debug!("{}", err.description());
                    Ok(())
                })
        });

        // Run the server
        run(server.map_err(|_err| ()));
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2016 Robert Clipsham <robert@octarineparrot.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interface listing implementation for all non-Windows platforms

use std::mem;
use std::ffi::{CStr, CString};
use std::str::from_utf8_unchecked;
use std::net::IpAddr;

use libc;

use util::{NetworkInterface, MacAddr};

use internal;

/// Get a list of available network interfaces for the current machine.
pub fn interfaces() -> Vec<NetworkInterface> {
    fn merge(old: &mut NetworkInterface, new: &NetworkInterface) {
        old.mac = match new.mac {
            None => old.mac,
            _ => new.mac,
        };
        match (&mut old.ips, &new.ips) {
            (&mut Some(ref mut old_ips), &Some(ref new_ips)) => {
                old_ips.extend_from_slice(&new_ips[..])
            }
            (&mut ref mut old_ips @ None, &Some(ref new_ips)) => *old_ips = Some(new_ips.clone()),
            _ => {}
        };
        old.flags = old.flags | new.flags;
    }

    let mut ifaces: Vec<NetworkInterface> = Vec::new();
    unsafe {
        let mut addrs: *mut libc::ifaddrs = mem::uninitialized();
        if libc::getifaddrs(&mut addrs) != 0 {
            return ifaces;
        }
        let mut addr = addrs;
        while !addr.is_null() {
            let c_str = (*addr).ifa_name as *const i8;
            let bytes = CStr::from_ptr(c_str).to_bytes();
            let name = from_utf8_unchecked(bytes).to_owned();
            let (mac, ip) = sockaddr_to_network_addr((*addr).ifa_addr as *const libc::sockaddr);
            let ni = NetworkInterface {
                name: name.clone(),
                index: 0,
                mac: mac,
                ips: ip.map(|ip| [ip].to_vec()),
                flags: (*addr).ifa_flags,
            };
            let mut found: bool = false;
            for iface in &mut ifaces {
                if name == iface.name {
                    merge(iface, &ni);
                    found = true;
                }
            }
            if !found {
                ifaces.push(ni);
            }

            addr = (*addr).ifa_next;
        }
        libc::freeifaddrs(addrs);

        for iface in &mut ifaces {
            let name = CString::new(iface.name.as_bytes());
            iface.index = libc::if_nametoindex(name.unwrap().as_ptr());
        }

        ifaces
    }
}

#[cfg(target_os = "linux")]
fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Option<IpAddr>) {
    use std::net::SocketAddr;

    unsafe {
        if sa.is_null() {
            (None, None)
        } else if (*sa).sa_family as libc::c_int == libc::AF_PACKET {
            let sll: *const libc::sockaddr_ll = mem::transmute(sa);
            let mac = MacAddr((*sll).sll_addr[0],
                              (*sll).sll_addr[1],
                              (*sll).sll_addr[2],
                              (*sll).sll_addr[3],
                              (*sll).sll_addr[4],
                              (*sll).sll_addr[5]);

            (Some(mac), None)
        } else {
            let addr = internal::sockaddr_to_addr(mem::transmute(sa),
                                                  mem::size_of::<libc::sockaddr_storage>());

            match addr {
                Ok(SocketAddr::V4(sa)) => (None, Some(IpAddr::V4(*sa.ip()))),
                Ok(SocketAddr::V6(sa)) => (None, Some(IpAddr::V6(*sa.ip()))),
                Err(_) => (None, None),
            }
        }
    }
}

#[cfg(any(target_os = "freebsd", target_os = "macos"))]
fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Option<IpAddr>) {
    use bindings::bpf;
    use std::net::SocketAddr;

    unsafe {
        if sa.is_null() {
            (None, None)
        } else if (*sa).sa_family as libc::c_int == bpf::AF_LINK {
            let sdl: *const bpf::sockaddr_dl = mem::transmute(sa);
            let nlen = (*sdl).sdl_nlen as usize;
            let mac = MacAddr((*sdl).sdl_data[nlen] as u8,
                              (*sdl).sdl_data[nlen + 1] as u8,
                              (*sdl).sdl_data[nlen + 2] as u8,
                              (*sdl).sdl_data[nlen + 3] as u8,
                              (*sdl).sdl_data[nlen + 4] as u8,
                              (*sdl).sdl_data[nlen + 5] as u8);

            (Some(mac), None)
        } else {
            let addr = internal::sockaddr_to_addr(mem::transmute(sa),
                                                  mem::size_of::<libc::sockaddr_storage>());

            match addr {
                Ok(SocketAddr::V4(sa)) => (None, Some(IpAddr::V4(*sa.ip()))),
                Ok(SocketAddr::V6(sa)) => (None, Some(IpAddr::V6(*sa.ip()))),
                Err(_) => (None, None),
            }
        }
    }
}
<commit_msg>slight rust-fmt on new code<commit_after>// Copyright (c) 2014-2016 Robert Clipsham <robert@octarineparrot.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interface listing implementation for all non-Windows platforms

use std::mem;
use std::ffi::{CStr, CString};
use std::str::from_utf8_unchecked;
use std::net::IpAddr;

use libc;

use util::{MacAddr, NetworkInterface};

use internal;

/// Get a list of available network interfaces for the current machine.
pub fn interfaces() -> Vec<NetworkInterface> {
    fn merge(old: &mut NetworkInterface, new: &NetworkInterface) {
        old.mac = match new.mac {
            None => old.mac,
            _ => new.mac,
        };
        match (&mut old.ips, &new.ips) {
            (&mut Some(ref mut old_ips), &Some(ref new_ips)) => {
                old_ips.extend_from_slice(&new_ips[..])
            }
            (&mut ref mut old_ips @ None, &Some(ref new_ips)) => *old_ips = Some(new_ips.clone()),
            _ => {}
        };
        old.flags = old.flags | new.flags;
    }

    let mut ifaces: Vec<NetworkInterface> = Vec::new();
    unsafe {
        let mut addrs: *mut libc::ifaddrs = mem::uninitialized();
        if libc::getifaddrs(&mut addrs) != 0 {
            return ifaces;
        }
        let mut addr = addrs;
        while !addr.is_null() {
            let c_str = (*addr).ifa_name as *const i8;
            let bytes = CStr::from_ptr(c_str).to_bytes();
            let name = from_utf8_unchecked(bytes).to_owned();
            let (mac, ip) = sockaddr_to_network_addr((*addr).ifa_addr as *const libc::sockaddr);
            let ni = NetworkInterface {
                name: name.clone(),
                index: 0,
                mac: mac,
                ips: ip.map(|ip| [ip].to_vec()),
                flags: (*addr).ifa_flags,
            };
            let mut found: bool = false;
            for iface in &mut ifaces {
                if name == iface.name {
                    merge(iface, &ni);
                    found = true;
                }
            }
            if !found {
                ifaces.push(ni);
            }

            addr = (*addr).ifa_next;
        }
        libc::freeifaddrs(addrs);

        for iface in &mut ifaces {
            let name = CString::new(iface.name.as_bytes());
            iface.index = libc::if_nametoindex(name.unwrap().as_ptr());
        }

        ifaces
    }
}

#[cfg(target_os = "linux")]
fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Option<IpAddr>) {
    use std::net::SocketAddr;

    unsafe {
        if sa.is_null() {
            (None, None)
        } else if (*sa).sa_family as libc::c_int == libc::AF_PACKET {
            let sll: *const libc::sockaddr_ll = mem::transmute(sa);
            let mac = MacAddr((*sll).sll_addr[0],
                              (*sll).sll_addr[1],
                              (*sll).sll_addr[2],
                              (*sll).sll_addr[3],
                              (*sll).sll_addr[4],
                              (*sll).sll_addr[5]);

            (Some(mac), None)
        } else {
            let addr = internal::sockaddr_to_addr(mem::transmute(sa),
                                                  mem::size_of::<libc::sockaddr_storage>());

            match addr {
                Ok(SocketAddr::V4(sa)) => (None, Some(IpAddr::V4(*sa.ip()))),
                Ok(SocketAddr::V6(sa)) => (None, Some(IpAddr::V6(*sa.ip()))),
                Err(_) => (None, None),
            }
        }
    }
}

#[cfg(any(target_os = "freebsd", target_os = "macos"))]
fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Option<IpAddr>) {
    use bindings::bpf;
    use std::net::SocketAddr;

    unsafe {
        if sa.is_null() {
            (None, None)
        } else if (*sa).sa_family as libc::c_int == bpf::AF_LINK {
            let sdl: *const bpf::sockaddr_dl = mem::transmute(sa);
            let nlen = (*sdl).sdl_nlen as usize;
            let mac = MacAddr((*sdl).sdl_data[nlen] as u8,
                              (*sdl).sdl_data[nlen + 1] as u8,
                              (*sdl).sdl_data[nlen + 2] as u8,
                              (*sdl).sdl_data[nlen + 3] as u8,
                              (*sdl).sdl_data[nlen + 4] as u8,
                              (*sdl).sdl_data[nlen + 5] as u8);

            (Some(mac), None)
        } else {
            let addr = internal::sockaddr_to_addr(mem::transmute(sa),
                                                  mem::size_of::<libc::sockaddr_storage>());

            match addr {
                Ok(SocketAddr::V4(sa)) => (None, Some(IpAddr::V4(*sa.ip()))),
                Ok(SocketAddr::V6(sa)) => (None, Some(IpAddr::V6(*sa.ip()))),
                Err(_) => (None, None),
            }
        }
    }
}
<|endoftext|>


<commit_before>/*
--- Day 6: Signals and Noise ---

Something is jamming your communications with Santa. Fortunately, your signal is only partially jammed, and protocol in situations like this is to switch to a simple repetition code to get the message through.

In this model, the same message is sent repeatedly. You've recorded the repeating message signal (your puzzle input), but the data seems quite corrupted - almost too badly to recover. Almost.

All you need to do is figure out which character is most frequent for each position. For example, suppose you had recorded the following messages:

eedadn
drvtee
eandsr
raavrd
atevrs
tsrnev
sdttsa
rasrtv
nssdts
ntnada
svetve
tesnvt
vntsnd
vrdear
dvrsen
enarar
The most common character in the first column is e; in the second, a; in the third, s, and so on. Combining these characters returns the error-corrected message, easter.

Given the recording in your puzzle input, what is the error-corrected version of the message being sent?

Your puzzle answer was gebzfnbt.

--- Part Two ---

Of course, that would be the message - if you hadn't agreed to use a modified repetition code instead.

In this modified code, the sender instead transmits what looks like random data, but for each character, the character they actually want to send is slightly less likely than the others. Even after signal-jamming noise, you can look at the letter distributions in each column and choose the least common letter to reconstruct the original message.

In the above example, the least common character in the first column is a; in the second, d, and so on. Repeating this process for the remaining characters produces the original message, advent.

Given the recording in your puzzle input and this new decoding methodology, what is the original message that Santa is trying to send?
*/

use std::io::prelude::*;
use std::fs::File;
use std::collections::HashMap;

type Column   = HashMap<char, usize>;
type Register = Vec<Column>;

fn main() {
    let mut f = File::open("input.txt").unwrap();
    let mut input = String::new();
    f.read_to_string(&mut input).ok();

    let line_length = input.chars().count() / input.lines().count();
    println!("line_length:{}", line_length);

    let mut columns : Register = Vec::with_capacity(line_length);

    for _ in 0..line_length {
        columns.push(Column::new())
    }

    for line in input.lines() {
        for (idx, c) in line.chars().enumerate() {
            let val = match columns[idx].get(&c) {
                Some(val) => val + 1,
                None => 1,
            };

            columns[idx].insert(c, val);
        }
    }

    let message_a : String = columns.iter()
        .map(|c| *sort_column(&c).last().unwrap())
        .collect();
    println!("[PART A] message: {}", message_a);

    let message_b : String = columns.iter()
        .map(|c| *sort_column(&c).first().unwrap())
        .collect();
    println!("[PART B] message: {}", message_b);
}

fn sort_column(column : &Column) -> Vec<char> {
    let mut thingy : Vec<(&char, &usize)> = column.iter().collect();
    thingy.sort_by_key(|r| r.1);
    thingy.iter().map(|r| *r.0).collect()
}<commit_msg>Remove printlns<commit_after>/*
--- Day 6: Signals and Noise ---

Something is jamming your communications with Santa. Fortunately, your signal is only partially jammed, and protocol in situations like this is to switch to a simple repetition code to get the message through.

In this model, the same message is sent repeatedly. You've recorded the repeating message signal (your puzzle input), but the data seems quite corrupted - almost too badly to recover. Almost.

All you need to do is figure out which character is most frequent for each position. For example, suppose you had recorded the following messages:

eedadn
drvtee
eandsr
raavrd
atevrs
tsrnev
sdttsa
rasrtv
nssdts
ntnada
svetve
tesnvt
vntsnd
vrdear
dvrsen
enarar
The most common character in the first column is e; in the second, a; in the third, s, and so on. Combining these characters returns the error-corrected message, easter.

Given the recording in your puzzle input, what is the error-corrected version of the message being sent?

Your puzzle answer was gebzfnbt.

--- Part Two ---

Of course, that would be the message - if you hadn't agreed to use a modified repetition code instead.

In this modified code, the sender instead transmits what looks like random data, but for each character, the character they actually want to send is slightly less likely than the others. Even after signal-jamming noise, you can look at the letter distributions in each column and choose the least common letter to reconstruct the original message.

In the above example, the least common character in the first column is a; in the second, d, and so on. Repeating this process for the remaining characters produces the original message, advent.

Given the recording in your puzzle input and this new decoding methodology, what is the original message that Santa is trying to send?
*/

use std::io::prelude::*;
use std::fs::File;
use std::collections::HashMap;

type Column   = HashMap<char, usize>;

fn main() {
    let mut f = File::open("input.txt").unwrap();
    let mut input = String::new();
    f.read_to_string(&mut input).ok();

    let line_length = input.chars().count() / input.lines().count();
    let mut columns : Vec<Column> = Vec::with_capacity(line_length);

    for _ in 0..line_length {
        columns.push(Column::new())
    }

    for line in input.lines() {
        for (idx, c) in line.chars().enumerate() {
            let val = match columns[idx].get(&c) {
                Some(val) => val + 1,
                None => 1,
            };

            columns[idx].insert(c, val);
        }
    }

    let message_a : String = columns.iter()
        .map(|c| *sort_column(&c).last().unwrap())
        .collect();
    println!("[PART A] message: {}", message_a);

    let message_b : String = columns.iter()
        .map(|c| *sort_column(&c).first().unwrap())
        .collect();
    println!("[PART B] message: {}", message_b);
}

fn sort_column(column : &Column) -> Vec<char> {
    let mut thingy : Vec<(&char, &usize)> = column.iter().collect();
    thingy.sort_by_key(|r| r.1);
    thingy.iter().map(|r| *r.0).collect()
}<|endoftext|>


<commit_before>use collections::slice::{mod, AsSlice, SlicePrelude};
use collections::vec::{mod, Vec};
use core::mem;
use core::iter::{mod, Iterator};
use core::option::{mod, Some, None, Option};

use iobuf::Iobuf;

/// A span over potentially many Iobufs. This is useful as a "string" type where
/// the contents of the string can potentially come from multiple IObufs, and
/// you want to avoid copying.
///
/// As an optimization, pushing an Iobuf that points to data immediately after
/// the range represented by the last Iobuf pushed will result in just expanding
/// the held Iobuf's range. This prevents allocating lots of unnecessary
/// intermediate buffers, while still maintaining the illusion of "pushing lots
/// of buffers" while incrementally parsing.
///
/// A `BufSpan` is internally represented as either an `Iobuf` or a `Vec<Iobuf>`,
/// depending on how many different buffers were used.
pub enum BufSpan<Buf> {
  Empty,
  One (Buf),
  Many(Vec<Buf>),
}

impl<Buf: Iobuf> BufSpan<Buf> {
  /// Creates a new, empty `Bufspan`.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf};
  ///
  /// let s: BufSpan<ROIobuf<'static>> = BufSpan::new();
  /// assert!(s.is_empty());
  /// ```
  #[inline]
  pub fn new() -> BufSpan<Buf> {
    Empty
  }

  /// Creates a new `BufSpan` from a slice of bytes.
  ///
  /// ```
  /// use iobuf::{BufSpan, Iobuf, ROIobuf};
  /// use std::iter::AdditiveIterator;
  ///
  /// let s = BufSpan::from_buf(ROIobuf::from_slice(b"hello"));
  /// assert_eq!(s.iter().count(), 1);
  /// assert_eq!(s.iter().map(|b| b.len()).sum(), 5);
  /// ```
  #[inline]
  pub fn from_buf(b: Buf) -> BufSpan<Buf> {
    One(b)
  }

  /// Returns `true` iff the span is over an empty range.
  ///
  /// ```
  /// use iobuf::{BufSpan, Iobuf, ROIobuf};
  ///
  /// let mut s = BufSpan::new();
  ///
  /// assert!(s.is_empty());
  ///
  /// s.push(ROIobuf::from_str(""));
  /// assert!(s.is_empty());
  ///
  /// s.push(ROIobuf::from_str("hello, world!"));
  /// assert!(!s.is_empty());
  /// ```
  #[inline]
  pub fn is_empty(&self) -> bool {
    match *self {
      Empty       => true,
      One (ref b) => b.is_empty(),
      Many(ref v) => v.iter().all(|b| b.is_empty()),
    }
  }

  /// The fast path during pushing -- either fills in the first buffer, or
  /// extends an existing one.
  ///
  /// Returns `None` if the fast path was taken and nothing more needs to be
  /// done. Returns `Some` if we need to do a slow push.
  #[inline]
  fn try_to_extend(&mut self, b: Buf) -> Option<Buf> {
    match *self {
      Empty => {},
      One(ref mut b0) => {
        unsafe {
          if b0.is_extended_by(&b) {
            b0.unsafe_extend(b.len());
            return None;
          } else {
            return Some(b); // Upgrade the `One` into a `Many` in the slow path.
          }
        }
      }
      Many(ref mut v) => {
        // I wish this wouldn't unwind, and just abort... :(
        let last = v.last_mut().unwrap();
        unsafe {
          if last.is_extended_by(&b) {
            last.unsafe_extend(b.len());
            return None;
          } else {
            return Some(b);
          }
        }
      }
    }

    // Handle this case in the fast path, instead of leaving it for slow_push
    // to clean up.
    *self = One(b);
    None
  }

  /// Appends a buffer to a `BufSpan`. If the buffer is an extension of the
  /// previously pushed buffer, the range will be extended. Otherwise, the new
  /// non-extension buffer will be added to the end of a vector.
  #[inline]
  pub fn push(&mut self, b: Buf) {
    match self.try_to_extend(b) {
      None    => {},
      Some(b) => self.slow_push(b),
    }
  }

  /// The slow path during a push. This is only taken if a `BufSpan` must span
  /// multiple backing buffers.
  #[cold]
  fn slow_push(&mut self, b: Buf) {
    let this = mem::replace(self, Empty);
    *self =
      match this {
        Empty   => One(b),
        One(b0) => {
          let mut v = Vec::with_capacity(2);
          v.push(b0);
          v.push(b);
          Many(v)
        },
        Many(mut bs) => { bs.push(b); Many(bs) }
      };
  }

  /// Returns an iterator over references to the buffers inside the `BufSpan`.
  #[inline]
  pub fn iter<'a>(&'a self) -> SpanIter<'a, Buf> {
    match *self {
      Empty       => Opt(None.into_iter()),
      One (ref b) => Opt(Some(b).into_iter()),
      Many(ref v) => Lot(v.as_slice().iter()),
    }
  }

  /// Returns a moving iterator over the buffers inside the `BufSpan`.
  #[inline]
  pub fn into_iter(self) -> SpanMoveIter<Buf> {
    match self {
      Empty   => MoveOpt(None.into_iter()),
      One (b) => MoveOpt(Some(b).into_iter()),
      Many(v) => MoveLot(v.into_iter()),
    }
  }

  /// Returns an iterator over the bytes in the `BufSpan`.
  #[inline]
  pub fn iter_bytes<'a>(&'a self) -> ByteIter<'a, Buf> {
    self.iter()
        .flat_map(|buf| unsafe { buf.as_window_slice().iter() })
        .map(|&b| b)
  }

  /// Returns `true` iff the bytes in this `BufSpan` are the same as the bytes
  /// in the other `BufSpan`.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf, RWIobuf};
  ///
  /// let a = BufSpan::from_buf(ROIobuf::from_str("hello"));
  /// let b = BufSpan::from_buf(RWIobuf::from_string("hello".into_string()));
  ///
  /// assert!(a.byte_equal(&b));
  ///
  /// let mut c = BufSpan::from_buf(ROIobuf::from_str("hel"));
  /// c.push(ROIobuf::from_str("lo"));
  ///
  /// assert!(a.byte_equal(&c)); assert!(c.byte_equal(&a));
  ///
  /// let d = BufSpan::from_buf(ROIobuf::from_str("helo"));
  /// assert!(!a.byte_equal(&d));
  /// ```
  #[inline]
  pub fn byte_equal<Buf2: Iobuf>(&self, other: &BufSpan<Buf2>) -> bool {
    self.iter_bytes().zip(other.iter_bytes()).all(|(a, b)| a == b)
  }

  /// A more efficient version of byte_equal, specialized to work exclusively on
  /// slices.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf};
  ///
  /// let a = BufSpan::from_buf(ROIobuf::from_str("hello"));
  ///
  /// assert!(a.byte_equal_slice(b"hello"));
  /// assert!(!a.byte_equal_slice(b"helo"));
  /// ```
  #[inline]
  pub fn byte_equal_slice(&self, other: &[u8]) -> bool {
    self.iter_bytes().zip(other.iter()).all(|(a, &b)| a == b)
  }
}

/// An iterator over the bytes in a `BufSpan`.
pub type ByteIter<'a, Buf> =
  iter::Map<'static, &'a u8, u8,
    iter::FlatMap<'static, &'a Buf,
      SpanIter<'a, Buf>,
      slice::Items<'a, u8>>>;

/// An iterator over references to buffers inside a `BufSpan`.
pub enum SpanIter<'a, Buf: 'a> {
  Opt(option::Item<&'a Buf>),
  Lot(slice::Items<'a, Buf>),
}

impl<'a, Buf: Iobuf> Iterator<&'a Buf> for SpanIter<'a, Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<&'a Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      Opt(ref mut iter) => iter.next(),
      Lot(ref mut iter) => iter.next(),
    }
  }
}

/// A moving iterator over buffers inside a `BufSpan`.
pub enum SpanMoveIter<Buf> {
  MoveOpt(option::Item<Buf>),
  MoveLot(vec::MoveItems<Buf>),
}

impl<Buf: Iobuf> Iterator<Buf> for SpanMoveIter<Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      MoveOpt(ref mut iter) => iter.next(),
      MoveLot(ref mut iter) => iter.next(),
    }
  }
}
<commit_msg>bugfix in count_bytes<commit_after>use collections::slice::{mod, AsSlice, SlicePrelude};
use collections::vec::{mod, Vec};
use core::mem;
use core::iter::{mod, AdditiveIterator, Iterator};
use core::option::{mod, Some, None, Option};

use iobuf::Iobuf;

/// A span over potentially many Iobufs. This is useful as a "string" type where
/// the contents of the string can potentially come from multiple IObufs, and
/// you want to avoid copying.
///
/// As an optimization, pushing an Iobuf that points to data immediately after
/// the range represented by the last Iobuf pushed will result in just expanding
/// the held Iobuf's range. This prevents allocating lots of unnecessary
/// intermediate buffers, while still maintaining the illusion of "pushing lots
/// of buffers" while incrementally parsing.
///
/// A `BufSpan` is internally represented as either an `Iobuf` or a `Vec<Iobuf>`,
/// depending on how many different buffers were used.
pub enum BufSpan<Buf> {
  Empty,
  One (Buf),
  Many(Vec<Buf>),
}

impl<Buf: Iobuf> BufSpan<Buf> {
  /// Creates a new, empty `Bufspan`.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf};
  ///
  /// let s: BufSpan<ROIobuf<'static>> = BufSpan::new();
  /// assert!(s.is_empty());
  /// ```
  #[inline]
  pub fn new() -> BufSpan<Buf> {
    Empty
  }

  /// Creates a new `BufSpan` from a slice of bytes.
  ///
  /// ```
  /// use iobuf::{BufSpan, Iobuf, ROIobuf};
  /// use std::iter::AdditiveIterator;
  ///
  /// let s = BufSpan::from_buf(ROIobuf::from_slice(b"hello"));
  /// assert_eq!(s.iter().count(), 1);
  /// assert_eq!(s.iter().map(|b| b.len()).sum(), 5);
  /// ```
  #[inline]
  pub fn from_buf(b: Buf) -> BufSpan<Buf> {
    One(b)
  }

  /// Returns `true` iff the span is over an empty range.
  ///
  /// ```
  /// use iobuf::{BufSpan, Iobuf, ROIobuf};
  ///
  /// let mut s = BufSpan::new();
  ///
  /// assert!(s.is_empty());
  ///
  /// s.push(ROIobuf::from_str(""));
  /// assert!(s.is_empty());
  ///
  /// s.push(ROIobuf::from_str("hello, world!"));
  /// assert!(!s.is_empty());
  /// ```
  #[inline]
  pub fn is_empty(&self) -> bool {
    match *self {
      Empty       => true,
      One (ref b) => b.is_empty(),
      Many(ref v) => v.iter().all(|b| b.is_empty()),
    }
  }

  /// The fast path during pushing -- either fills in the first buffer, or
  /// extends an existing one.
  ///
  /// Returns `None` if the fast path was taken and nothing more needs to be
  /// done. Returns `Some` if we need to do a slow push.
  #[inline]
  fn try_to_extend(&mut self, b: Buf) -> Option<Buf> {
    match *self {
      Empty => {},
      One(ref mut b0) => {
        unsafe {
          if b0.is_extended_by(&b) {
            b0.unsafe_extend(b.len());
            return None;
          } else {
            return Some(b); // Upgrade the `One` into a `Many` in the slow path.
          }
        }
      }
      Many(ref mut v) => {
        // I wish this wouldn't unwind, and just abort... :(
        let last = v.last_mut().unwrap();
        unsafe {
          if last.is_extended_by(&b) {
            last.unsafe_extend(b.len());
            return None;
          } else {
            return Some(b);
          }
        }
      }
    }

    // Handle this case in the fast path, instead of leaving it for slow_push
    // to clean up.
    *self = One(b);
    None
  }

  /// Appends a buffer to a `BufSpan`. If the buffer is an extension of the
  /// previously pushed buffer, the range will be extended. Otherwise, the new
  /// non-extension buffer will be added to the end of a vector.
  #[inline]
  pub fn push(&mut self, b: Buf) {
    match self.try_to_extend(b) {
      None    => {},
      Some(b) => self.slow_push(b),
    }
  }

  /// The slow path during a push. This is only taken if a `BufSpan` must span
  /// multiple backing buffers.
  #[cold]
  fn slow_push(&mut self, b: Buf) {
    let this = mem::replace(self, Empty);
    *self =
      match this {
        Empty   => One(b),
        One(b0) => {
          let mut v = Vec::with_capacity(2);
          v.push(b0);
          v.push(b);
          Many(v)
        },
        Many(mut bs) => { bs.push(b); Many(bs) }
      };
  }

  /// Returns an iterator over references to the buffers inside the `BufSpan`.
  #[inline]
  pub fn iter<'a>(&'a self) -> SpanIter<'a, Buf> {
    match *self {
      Empty       => Opt(None.into_iter()),
      One (ref b) => Opt(Some(b).into_iter()),
      Many(ref v) => Lot(v.as_slice().iter()),
    }
  }

  /// Returns a moving iterator over the buffers inside the `BufSpan`.
  #[inline]
  pub fn into_iter(self) -> SpanMoveIter<Buf> {
    match self {
      Empty   => MoveOpt(None.into_iter()),
      One (b) => MoveOpt(Some(b).into_iter()),
      Many(v) => MoveLot(v.into_iter()),
    }
  }

  /// Returns an iterator over the bytes in the `BufSpan`.
  #[inline]
  pub fn iter_bytes<'a>(&'a self) -> ByteIter<'a, Buf> {
    self.iter()
        .flat_map(|buf| unsafe { buf.as_window_slice().iter() })
        .map(|&b| b)
  }

  /// Returns `true` iff the bytes in this `BufSpan` are the same as the bytes
  /// in the other `BufSpan`.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf, RWIobuf};
  ///
  /// let a = BufSpan::from_buf(ROIobuf::from_str("hello"));
  /// let b = BufSpan::from_buf(RWIobuf::from_string("hello".into_string()));
  ///
  /// assert!(a.byte_equal(&b));
  ///
  /// let mut c = BufSpan::from_buf(ROIobuf::from_str("hel"));
  /// c.push(ROIobuf::from_str("lo"));
  ///
  /// assert!(a.byte_equal(&c)); assert!(c.byte_equal(&a));
  ///
  /// let d = BufSpan::from_buf(ROIobuf::from_str("helo"));
  /// assert!(!a.byte_equal(&d));
  /// ```
  #[inline]
  pub fn byte_equal<Buf2: Iobuf>(&self, other: &BufSpan<Buf2>) -> bool {
    self.count_bytes() == other.count_bytes()
    && self.iter_bytes().zip(other.iter_bytes()).all(|(a, b)| a == b)
  }

  /// A more efficient version of byte_equal, specialized to work exclusively on
  /// slices.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf};
  ///
  /// let a = BufSpan::from_buf(ROIobuf::from_str("hello"));
  ///
  /// assert!(a.byte_equal_slice(b"hello"));
  /// assert!(!a.byte_equal_slice(b"helo"));
  /// ```
  #[inline]
  pub fn byte_equal_slice(&self, other: &[u8]) -> bool {
    self.count_bytes() as uint == other.len()
    && self.iter_bytes().zip(other.iter()).all(|(a, &b)| a == b)
  }

  /// Counts the number of bytes this `BufSpan` is over. This is
  /// `O(self.iter().len())`.
  #[inline]
  pub fn count_bytes(&self) -> u32 {
    self.iter().map(|b| b.len()).sum()
  }
}

/// An iterator over the bytes in a `BufSpan`.
pub type ByteIter<'a, Buf> =
  iter::Map<'static, &'a u8, u8,
    iter::FlatMap<'static, &'a Buf,
      SpanIter<'a, Buf>,
      slice::Items<'a, u8>>>;

/// An iterator over references to buffers inside a `BufSpan`.
pub enum SpanIter<'a, Buf: 'a> {
  Opt(option::Item<&'a Buf>),
  Lot(slice::Items<'a, Buf>),
}

impl<'a, Buf: Iobuf> Iterator<&'a Buf> for SpanIter<'a, Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<&'a Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      Opt(ref mut iter) => iter.next(),
      Lot(ref mut iter) => iter.next(),
    }
  }
}

/// A moving iterator over buffers inside a `BufSpan`.
pub enum SpanMoveIter<Buf> {
  MoveOpt(option::Item<Buf>),
  MoveLot(vec::MoveItems<Buf>),
}

impl<Buf: Iobuf> Iterator<Buf> for SpanMoveIter<Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      MoveOpt(ref mut iter) => iter.next(),
      MoveLot(ref mut iter) => iter.next(),
    }
  }
}
<|endoftext|>


<commit_before>use Action;
use input::Button;
use piston_window::Size;

pub struct InputMapBuilder<A: Action> {
    input_remappings: Vec<(Button, A)>,
    x_axis_movement_inverted: bool,
    y_axis_movement_inverted: bool,
    x_axis_scroll_inverted: bool,
    y_axis_scroll_inverted: bool,
    viewport_size: Size
}

impl<A: Action> InputMapBuilder<A> {
    pub fn x_scroll_inverted(mut self, invert: bool) -> Self {
        self.x_axis_scroll_inverted = invert;
        self
    }

    pub fn get_x_scroll_inverted(mut self, invert: bool) -> Self {
        &self.x_axis_scroll_inverted
    }

    pub fn y_scroll_inverted(mut self, invert: bool) -> Self {
        self.y_axis_scroll_inverted = invert;
        self
    }

    pub fn get_y_scroll_inverted(&self) -> bool {
        &self.y_axis_scroll_inverted
    }

    pub fn viewport_size(mut self, sz: Size) -> Self {
        self.viewport_size = sz;
        self
    }

    pub fn get_viewport_size(&self) -> &Size {
        &self.viewport_size
    }
}

impl<A: Action> Default for InputMapBuilder<A> {
    fn default() -> Self {
        InputMapBuilder {
            input_remappings: vec![],
            x_axis_movement_inverted: false,
            y_axis_movement_inverted: false,
            x_axis_scroll_inverted: false,
            y_axis_scroll_inverted: false,
            viewport_size: Size {width: 800, height: 600}
        }
    }
}

impl<A> Into<InputMap<A>> for InputMapBuilder<A> {
    fn into(self) -> InputMap<A> {
        InputMap::new() // TODO implement
    }
}

<commit_msg>Add use statements for standard library features, and add a trait bound on the Into impl<commit_after>use Action;
use input::Button;
use piston_window::Size;
use std::convert::Into;
use std::default::Default;

pub struct InputMapBuilder<A: Action> {
    input_remappings: Vec<(Button, A)>,
    x_axis_movement_inverted: bool,
    y_axis_movement_inverted: bool,
    x_axis_scroll_inverted: bool,
    y_axis_scroll_inverted: bool,
    viewport_size: Size
}

impl<A: Action> InputMapBuilder<A> {
    pub fn x_scroll_inverted(mut self, invert: bool) -> Self {
        self.x_axis_scroll_inverted = invert;
        self
    }

    pub fn get_x_scroll_inverted(mut self, invert: bool) -> Self {
        &self.x_axis_scroll_inverted
    }

    pub fn y_scroll_inverted(mut self, invert: bool) -> Self {
        self.y_axis_scroll_inverted = invert;
        self
    }

    pub fn get_y_scroll_inverted(&self) -> bool {
        &self.y_axis_scroll_inverted
    }

    pub fn viewport_size(mut self, sz: Size) -> Self {
        self.viewport_size = sz;
        self
    }

    pub fn get_viewport_size(&self) -> &Size {
        &self.viewport_size
    }
}

impl<A: Action> Default for InputMapBuilder<A> {
    fn default() -> Self {
        InputMapBuilder {
            input_remappings: vec![],
            x_axis_movement_inverted: false,
            y_axis_movement_inverted: false,
            x_axis_scroll_inverted: false,
            y_axis_scroll_inverted: false,
            viewport_size: Size {width: 800, height: 600}
        }
    }
}

impl<A: Action> Into<InputMap<A>> for InputMapBuilder<A> {
    fn into(self) -> InputMap<A> {
        InputMap::new() // TODO implement
    }
}

<|endoftext|>