<commit_before>pub mod gregorian {
    /// Easter in the Gregorian calendar
    pub fn month_day(year: i32) -> (u32, u32) {
        let a = year % 19;
        let b = year / 100;
        let c = year % 100;
        let d = b / 4;
        let e = b % 4;
        let f = (b + 8) / 25;
        let g = (b - f + 1) / 3;
        let h = (19 * a + b - d - g + 15) % 30;
        let i = c / 4;
        let k = c % 4;
        let l = (32 + 2 * e + 2 * i - h - k) % 7;
        let m = (a + 11 * h + 22 * l) / 451;
        let month = (h + l - 7 * m + 114) / 31;
        let day = (h + l - 7 * m + 114) % 31 + 1;
        (month as u32, day as u32)
    }
}

pub mod julian {
    /// Easter in the Julian calendar
    pub fn month_day(year: i32) -> (u32, u32) {
        let a = year % 4;
        let b = year % 7;
        let c = year % 19;
        let d = (19 * c + 15) % 30;
        let e = (2 * a + 4 * b - d + 34) % 7;
        let f = d + e + 114;
        let month = f / 31;
        let day = f % 31 + 1;
        (month as u32, day as u32)
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn gregorian_month_day() {
        use super::gregorian::month_day;
        assert_eq!(month_day(1961), (4, 2));
        assert_eq!(month_day(1996), (4, 7));
        assert_eq!(month_day(1997), (3, 30));
        assert_eq!(month_day(1998), (4, 12));
        assert_eq!(month_day(2000), (4, 23));
        assert_eq!(month_day(2001), (4, 15));
        assert_eq!(month_day(2002), (3, 31));
        assert_eq!(month_day(2003), (4, 20));
        assert_eq!(month_day(2004), (4, 11));
        assert_eq!(month_day(2005), (3, 27));
        assert_eq!(month_day(2006), (4, 16));
        assert_eq!(month_day(2007), (4, 8));
        assert_eq!(month_day(2008), (3, 23));
        assert_eq!(month_day(2009), (4, 12));
        assert_eq!(month_day(2010), (4, 4));
        assert_eq!(month_day(2011), (4, 24));
        assert_eq!(month_day(2012), (4, 8));
        assert_eq!(month_day(2013), (3, 31));
        assert_eq!(month_day(2014), (4, 20));
        assert_eq!(month_day(2015), (4, 5));
        assert_eq!(month_day(2016), (3, 27));
        assert_eq!(month_day(2017), (4, 16));
        assert_eq!(month_day(2018), (4, 1));
        assert_eq!(month_day(2019), (4, 21));
        assert_eq!(month_day(2020), (4, 12));
    }

    #[test]
    fn julian_month_day() {
        use super::julian::month_day;
        assert_eq!(month_day(1961), (3, 27));
        assert_eq!(month_day(1996), (4, 1));
        assert_eq!(month_day(1997), (4, 14));
        assert_eq!(month_day(1998), (4, 6));
        assert_eq!(month_day(1999), (3, 29));
        assert_eq!(month_day(2000), (4, 17));
        assert_eq!(month_day(2001), (4, 2));
        assert_eq!(month_day(2002), (4, 22));
        assert_eq!(month_day(2003), (4, 14));
        assert_eq!(month_day(2004), (3, 29));
        assert_eq!(month_day(2005), (4, 18));
        assert_eq!(month_day(2006), (4, 10));
        assert_eq!(month_day(2007), (3, 26));
        assert_eq!(month_day(2008), (4, 14));
        assert_eq!(month_day(2009), (4, 6));
        assert_eq!(month_day(2010), (3, 22));
        assert_eq!(month_day(2011), (4, 11));
        assert_eq!(month_day(2012), (4, 2));
        assert_eq!(month_day(2013), (4, 22));
        assert_eq!(month_day(2014), (4, 7));
        assert_eq!(month_day(2015), (3, 30));
        assert_eq!(month_day(2016), (4, 18));
        assert_eq!(month_day(2017), (4, 3));
        assert_eq!(month_day(2018), (3, 26));
        assert_eq!(month_day(2019), (4, 15));
        assert_eq!(month_day(2020), (4, 6));
    }
}
<commit_msg>panic if easter hasn't happened yet<commit_after>fn check_easter_happened(year: i32) {
    if year < 33 {
        panic!(format!("Jesus isn't dead yet in the year {}", year));
    }
}

pub mod gregorian {
    /// Easter in the Gregorian calendar
    pub fn month_day(year: i32) -> (u32, u32) {
        super::check_easter_happened(year);
        let a = year % 19;
        let b = year / 100;
        let c = year % 100;
        let d = b / 4;
        let e = b % 4;
        let f = (b + 8) / 25;
        let g = (b - f + 1) / 3;
        let h = (19 * a + b - d - g + 15) % 30;
        let i = c / 4;
        let k = c % 4;
        let l = (32 + 2 * e + 2 * i - h - k) % 7;
        let m = (a + 11 * h + 22 * l) / 451;
        let month = (h + l - 7 * m + 114) / 31;
        let day = (h + l - 7 * m + 114) % 31 + 1;
        (month as u32, day as u32)
    }
}

pub mod julian {
    /// Easter in the Julian calendar
    pub fn month_day(year: i32) -> (u32, u32) {
        super::check_easter_happened(year);
        let a = year % 4;
        let b = year % 7;
        let c = year % 19;
        let d = (19 * c + 15) % 30;
        let e = (2 * a + 4 * b - d + 34) % 7;
        let f = d + e + 114;
        let month = f / 31;
        let day = f % 31 + 1;
        (month as u32, day as u32)
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn gregorian_month_day() {
        use super::gregorian::month_day;
        assert_eq!(month_day(1961), (4, 2));
        assert_eq!(month_day(1996), (4, 7));
        assert_eq!(month_day(1997), (3, 30));
        assert_eq!(month_day(1998), (4, 12));
        assert_eq!(month_day(2000), (4, 23));
        assert_eq!(month_day(2001), (4, 15));
        assert_eq!(month_day(2002), (3, 31));
        assert_eq!(month_day(2003), (4, 20));
        assert_eq!(month_day(2004), (4, 11));
        assert_eq!(month_day(2005), (3, 27));
        assert_eq!(month_day(2006), (4, 16));
        assert_eq!(month_day(2007), (4, 8));
        assert_eq!(month_day(2008), (3, 23));
        assert_eq!(month_day(2009), (4, 12));
        assert_eq!(month_day(2010), (4, 4));
        assert_eq!(month_day(2011), (4, 24));
        assert_eq!(month_day(2012), (4, 8));
        assert_eq!(month_day(2013), (3, 31));
        assert_eq!(month_day(2014), (4, 20));
        assert_eq!(month_day(2015), (4, 5));
        assert_eq!(month_day(2016), (3, 27));
        assert_eq!(month_day(2017), (4, 16));
        assert_eq!(month_day(2018), (4, 1));
        assert_eq!(month_day(2019), (4, 21));
        assert_eq!(month_day(2020), (4, 12));
    }

    #[test]
    fn julian_month_day() {
        use super::julian::month_day;
        assert_eq!(month_day(1961), (3, 27));
        assert_eq!(month_day(1996), (4, 1));
        assert_eq!(month_day(1997), (4, 14));
        assert_eq!(month_day(1998), (4, 6));
        assert_eq!(month_day(1999), (3, 29));
        assert_eq!(month_day(2000), (4, 17));
        assert_eq!(month_day(2001), (4, 2));
        assert_eq!(month_day(2002), (4, 22));
        assert_eq!(month_day(2003), (4, 14));
        assert_eq!(month_day(2004), (3, 29));
        assert_eq!(month_day(2005), (4, 18));
        assert_eq!(month_day(2006), (4, 10));
        assert_eq!(month_day(2007), (3, 26));
        assert_eq!(month_day(2008), (4, 14));
        assert_eq!(month_day(2009), (4, 6));
        assert_eq!(month_day(2010), (3, 22));
        assert_eq!(month_day(2011), (4, 11));
        assert_eq!(month_day(2012), (4, 2));
        assert_eq!(month_day(2013), (4, 22));
        assert_eq!(month_day(2014), (4, 7));
        assert_eq!(month_day(2015), (3, 30));
        assert_eq!(month_day(2016), (4, 18));
        assert_eq!(month_day(2017), (4, 3));
        assert_eq!(month_day(2018), (3, 26));
        assert_eq!(month_day(2019), (4, 15));
        assert_eq!(month_day(2020), (4, 6));
    }
}
<|endoftext|>


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

//! Rust wrapper for RocksDB.
//!
//! # Examples
//!
//! ```
//! use rocksdb::{DB, Options};
//! // NB: db is automatically closed at end of lifetime
//! let path = "_path_for_rocksdb_storage";
//! {
//!    let db = DB::open_default(path).unwrap();
//!    db.put(b"my key", b"my value");
//!    match db.get(b"my key") {
//!        Ok(Some(value)) => println!("retrieved value {}", value.to_utf8().unwrap()),
//!        Ok(None) => println!("value not found"),
//!        Err(e) => println!("operational problem encountered: {}", e),
//!    }
//!    db.delete(b"my key").unwrap();
//! }
//! let _ = DB::destroy(&Options::default(), path);
//! ```
//!
//! Opening a database and a single column family with custom options:
//!
//! ```
//! use rocksdb::{DB, ColumnFamilyDescriptor, Options};
//!
//! let path = "_path_for_rocksdb_storage_with_cfs";
//! let mut cf_opts = Options::default();
//! cf_opts.set_max_write_buffer_number(16);
//! let cf = ColumnFamilyDescriptor::new("cf1", cf_opts);
//!
//! let mut db_opts = Options::default();
//! db_opts.create_missing_column_families(true);
//! db_opts.create_if_missing(true);
//! {
//!     let db = DB::open_cf_descriptors(&db_opts, path, vec![cf]).unwrap();
//! }
//! let _ = DB::destroy(&db_opts, path);
//! ```
//!

extern crate libc;
extern crate librocksdb_sys as ffi;

#[macro_use]
mod ffi_util;

pub mod backup;
pub mod checkpoint;
pub mod compaction_filter;
mod comparator;
mod db;
mod db_options;
pub mod merge_operator;
mod slice_transform;

pub use compaction_filter::Decision as CompactionDecision;
pub use db::{
    DBCompactionStyle, DBCompressionType, DBIterator, DBPinnableSlice, DBRawIterator,
    DBRecoveryMode, DBVector, Direction, IteratorMode, ReadOptions, Snapshot, WriteBatch,
};

pub use slice_transform::SliceTransform;

pub use merge_operator::MergeOperands;
use std::collections::BTreeMap;
use std::error;
use std::fmt;
use std::marker::PhantomData;
use std::path::PathBuf;
use std::sync::{Arc, RwLock};

/// A RocksDB database.
///
/// See crate level documentation for a simple usage example.
pub struct DB {
    inner: *mut ffi::rocksdb_t,
    cfs: Arc<RwLock<BTreeMap<String, *mut ffi::rocksdb_column_family_handle_t>>>,
    path: PathBuf,
}

/// A descriptor for a RocksDB column family.
///
/// A description of the column family, containing the name and `Options`.
pub struct ColumnFamilyDescriptor {
    name: String,
    options: Options,
}

/// A simple wrapper round a string, used for errors reported from
/// ffi calls.
#[derive(Debug, Clone, PartialEq)]
pub struct Error {
    message: String,
}

impl Error {
    fn new(message: String) -> Error {
        Error { message }
    }

    pub fn to_string(self) -> String {
        self.into()
    }
}

impl AsRef<str> for Error {
    fn as_ref(&self) -> &str {
        &self.message
    }
}

impl From<Error> for String {
    fn from(e: Error) -> String {
        e.message
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        &self.message
    }
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.message.fmt(formatter)
    }
}

/// For configuring block-based file storage.
pub struct BlockBasedOptions {
    inner: *mut ffi::rocksdb_block_based_table_options_t,
}

/// Used by BlockBasedOptions::set_index_type.
pub enum BlockBasedIndexType {
    /// A space efficient index block that is optimized for
    /// binary-search-based index.
    BinarySearch,

    /// The hash index, if enabled, will perform a hash lookup if
    /// a prefix extractor has been provided through Options::set_prefix_extractor.
    HashSearch,

    /// A two-level index implementation. Both levels are binary search indexes.
    TwoLevelIndexSearch,
}

/// Defines the underlying memtable implementation.
/// See https://github.com/facebook/rocksdb/wiki/MemTable for more information.
pub enum MemtableFactory {
    Vector,
    HashSkipList {
        bucket_count: usize,
        height: i32,
        branching_factor: i32,
    },
    HashLinkList {
        bucket_count: usize,
    },
}

/// Used with DBOptions::set_plain_table_factory.
/// See https://github.com/facebook/rocksdb/wiki/PlainTable-Format.
///
/// Defaults:
///  user_key_length: 0 (variable length)
///  bloom_bits_per_key: 10
///  hash_table_ratio: 0.75
///  index_sparseness: 16
pub struct PlainTableFactoryOptions {
    pub user_key_length: u32,
    pub bloom_bits_per_key: i32,
    pub hash_table_ratio: f64,
    pub index_sparseness: usize,
}

/// Database-wide options around performance and behavior.
///
/// Please read [the official tuning guide](https://github.com/facebook/rocksdb/wiki/RocksDB-Tuning-Guide), and most importantly, measure performance under realistic workloads with realistic hardware.
///
/// # Examples
///
/// ```
/// use rocksdb::{Options, DB};
/// use rocksdb::DBCompactionStyle;
///
/// fn badly_tuned_for_somebody_elses_disk() -> DB {
///    let path = "path/for/rocksdb/storageX";
///    let mut opts = Options::default();
///    opts.create_if_missing(true);
///    opts.set_max_open_files(10000);
///    opts.set_use_fsync(false);
///    opts.set_bytes_per_sync(8388608);
///    opts.optimize_for_point_lookup(1024);
///    opts.set_table_cache_num_shard_bits(6);
///    opts.set_max_write_buffer_number(32);
///    opts.set_write_buffer_size(536870912);
///    opts.set_target_file_size_base(1073741824);
///    opts.set_min_write_buffer_number_to_merge(4);
///    opts.set_level_zero_stop_writes_trigger(2000);
///    opts.set_level_zero_slowdown_writes_trigger(0);
///    opts.set_compaction_style(DBCompactionStyle::Universal);
///    opts.set_max_background_compactions(4);
///    opts.set_max_background_flushes(4);
///    opts.set_disable_auto_compactions(true);
///
///    DB::open(&opts, path).unwrap()
/// }
/// ```
pub struct Options {
    inner: *mut ffi::rocksdb_options_t,
}

/// Optionally disable WAL or sync for this write.
///
/// # Examples
///
/// Making an unsafe write of a batch:
///
/// ```
/// use rocksdb::{DB, Options, WriteBatch, WriteOptions};
///
/// let path = "_path_for_rocksdb_storageY";
/// {
///     let db = DB::open_default(path).unwrap();
///     let mut batch = WriteBatch::default();
///     batch.put(b"my key", b"my value");
///     batch.put(b"key2", b"value2");
///     batch.put(b"key3", b"value3");
///
///     let mut write_options = WriteOptions::default();
///     write_options.set_sync(false);
///     write_options.disable_wal(true);
///
///     db.write_opt(batch, &write_options);
/// }
/// let _ = DB::destroy(&Options::default(), path);
/// ```
pub struct WriteOptions {
    inner: *mut ffi::rocksdb_writeoptions_t,
}

/// An opaque type used to represent a column family. Returned from some functions, and used
/// in others
#[derive(Copy, Clone)]
pub struct ColumnFamily<'a> {
    inner: *mut ffi::rocksdb_column_family_handle_t,
    db: PhantomData<&'a DB>,
}

unsafe impl<'a> Send for ColumnFamily<'a> {}
<commit_msg>Handle std::result::Result in examples<commit_after>// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Rust wrapper for RocksDB.
//!
//! # Examples
//!
//! ```
//! use rocksdb::{DB, Options};
//! // NB: db is automatically closed at end of lifetime
//! let path = "_path_for_rocksdb_storage";
//! {
//!    let db = DB::open_default(path).unwrap();
//!    db.put(b"my key", b"my value").unwrap();
//!    match db.get(b"my key") {
//!        Ok(Some(value)) => println!("retrieved value {}", value.to_utf8().unwrap()),
//!        Ok(None) => println!("value not found"),
//!        Err(e) => println!("operational problem encountered: {}", e),
//!    }
//!    db.delete(b"my key").unwrap();
//! }
//! let _ = DB::destroy(&Options::default(), path);
//! ```
//!
//! Opening a database and a single column family with custom options:
//!
//! ```
//! use rocksdb::{DB, ColumnFamilyDescriptor, Options};
//!
//! let path = "_path_for_rocksdb_storage_with_cfs";
//! let mut cf_opts = Options::default();
//! cf_opts.set_max_write_buffer_number(16);
//! let cf = ColumnFamilyDescriptor::new("cf1", cf_opts);
//!
//! let mut db_opts = Options::default();
//! db_opts.create_missing_column_families(true);
//! db_opts.create_if_missing(true);
//! {
//!     let db = DB::open_cf_descriptors(&db_opts, path, vec![cf]).unwrap();
//! }
//! let _ = DB::destroy(&db_opts, path);
//! ```
//!

extern crate libc;
extern crate librocksdb_sys as ffi;

#[macro_use]
mod ffi_util;

pub mod backup;
pub mod checkpoint;
pub mod compaction_filter;
mod comparator;
mod db;
mod db_options;
pub mod merge_operator;
mod slice_transform;

pub use compaction_filter::Decision as CompactionDecision;
pub use db::{
    DBCompactionStyle, DBCompressionType, DBIterator, DBPinnableSlice, DBRawIterator,
    DBRecoveryMode, DBVector, Direction, IteratorMode, ReadOptions, Snapshot, WriteBatch,
};

pub use slice_transform::SliceTransform;

pub use merge_operator::MergeOperands;
use std::collections::BTreeMap;
use std::error;
use std::fmt;
use std::marker::PhantomData;
use std::path::PathBuf;
use std::sync::{Arc, RwLock};

/// A RocksDB database.
///
/// See crate level documentation for a simple usage example.
pub struct DB {
    inner: *mut ffi::rocksdb_t,
    cfs: Arc<RwLock<BTreeMap<String, *mut ffi::rocksdb_column_family_handle_t>>>,
    path: PathBuf,
}

/// A descriptor for a RocksDB column family.
///
/// A description of the column family, containing the name and `Options`.
pub struct ColumnFamilyDescriptor {
    name: String,
    options: Options,
}

/// A simple wrapper round a string, used for errors reported from
/// ffi calls.
#[derive(Debug, Clone, PartialEq)]
pub struct Error {
    message: String,
}

impl Error {
    fn new(message: String) -> Error {
        Error { message }
    }

    pub fn to_string(self) -> String {
        self.into()
    }
}

impl AsRef<str> for Error {
    fn as_ref(&self) -> &str {
        &self.message
    }
}

impl From<Error> for String {
    fn from(e: Error) -> String {
        e.message
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        &self.message
    }
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.message.fmt(formatter)
    }
}

/// For configuring block-based file storage.
pub struct BlockBasedOptions {
    inner: *mut ffi::rocksdb_block_based_table_options_t,
}

/// Used by BlockBasedOptions::set_index_type.
pub enum BlockBasedIndexType {
    /// A space efficient index block that is optimized for
    /// binary-search-based index.
    BinarySearch,

    /// The hash index, if enabled, will perform a hash lookup if
    /// a prefix extractor has been provided through Options::set_prefix_extractor.
    HashSearch,

    /// A two-level index implementation. Both levels are binary search indexes.
    TwoLevelIndexSearch,
}

/// Defines the underlying memtable implementation.
/// See https://github.com/facebook/rocksdb/wiki/MemTable for more information.
pub enum MemtableFactory {
    Vector,
    HashSkipList {
        bucket_count: usize,
        height: i32,
        branching_factor: i32,
    },
    HashLinkList {
        bucket_count: usize,
    },
}

/// Used with DBOptions::set_plain_table_factory.
/// See https://github.com/facebook/rocksdb/wiki/PlainTable-Format.
///
/// Defaults:
///  user_key_length: 0 (variable length)
///  bloom_bits_per_key: 10
///  hash_table_ratio: 0.75
///  index_sparseness: 16
pub struct PlainTableFactoryOptions {
    pub user_key_length: u32,
    pub bloom_bits_per_key: i32,
    pub hash_table_ratio: f64,
    pub index_sparseness: usize,
}

/// Database-wide options around performance and behavior.
///
/// Please read [the official tuning guide](https://github.com/facebook/rocksdb/wiki/RocksDB-Tuning-Guide), and most importantly, measure performance under realistic workloads with realistic hardware.
///
/// # Examples
///
/// ```
/// use rocksdb::{Options, DB};
/// use rocksdb::DBCompactionStyle;
///
/// fn badly_tuned_for_somebody_elses_disk() -> DB {
///    let path = "path/for/rocksdb/storageX";
///    let mut opts = Options::default();
///    opts.create_if_missing(true);
///    opts.set_max_open_files(10000);
///    opts.set_use_fsync(false);
///    opts.set_bytes_per_sync(8388608);
///    opts.optimize_for_point_lookup(1024);
///    opts.set_table_cache_num_shard_bits(6);
///    opts.set_max_write_buffer_number(32);
///    opts.set_write_buffer_size(536870912);
///    opts.set_target_file_size_base(1073741824);
///    opts.set_min_write_buffer_number_to_merge(4);
///    opts.set_level_zero_stop_writes_trigger(2000);
///    opts.set_level_zero_slowdown_writes_trigger(0);
///    opts.set_compaction_style(DBCompactionStyle::Universal);
///    opts.set_max_background_compactions(4);
///    opts.set_max_background_flushes(4);
///    opts.set_disable_auto_compactions(true);
///
///    DB::open(&opts, path).unwrap()
/// }
/// ```
pub struct Options {
    inner: *mut ffi::rocksdb_options_t,
}

/// Optionally disable WAL or sync for this write.
///
/// # Examples
///
/// Making an unsafe write of a batch:
///
/// ```
/// use rocksdb::{DB, Options, WriteBatch, WriteOptions};
///
/// let path = "_path_for_rocksdb_storageY";
/// {
///     let db = DB::open_default(path).unwrap();
///     let mut batch = WriteBatch::default();
///     batch.put(b"my key", b"my value");
///     batch.put(b"key2", b"value2");
///     batch.put(b"key3", b"value3");
///
///     let mut write_options = WriteOptions::default();
///     write_options.set_sync(false);
///     write_options.disable_wal(true);
///
///     db.write_opt(batch, &write_options);
/// }
/// let _ = DB::destroy(&Options::default(), path);
/// ```
pub struct WriteOptions {
    inner: *mut ffi::rocksdb_writeoptions_t,
}

/// An opaque type used to represent a column family. Returned from some functions, and used
/// in others
#[derive(Copy, Clone)]
pub struct ColumnFamily<'a> {
    inner: *mut ffi::rocksdb_column_family_handle_t,
    db: PhantomData<&'a DB>,
}

unsafe impl<'a> Send for ColumnFamily<'a> {}
<|endoftext|>


<commit_before>//! DPI is important, so read the docs for this module if you don't want to be confused.
//!
//! Originally, `winit` dealt entirely in physical pixels (excluding unintentional inconsistencies), but now all
//! window-related functions both produce and consume logical pixels. Monitor-related functions still use physical
//! pixels, as do any context-related functions in `glutin`.
//!
//! If you've never heard of these terms before, then you're not alone, and this documentation will explain the
//! concepts.
//!
//! Modern screens have a defined physical resolution, most commonly 1920x1080. Indepedent of that is the amount of
//! space the screen occupies, which is to say, the height and width in millimeters. The relationship between these two
//! measurements is the *pixel density*. Mobile screens require a high pixel density, as they're held close to the
//! eyes. Larger displays also require a higher pixel density, hence the growing presence of 1440p and 4K displays.
//!
//! So, this presents a problem. Let's say we want to render a square 100px button. It will occupy 100x100 of the
//! screen's pixels, which in many cases, seems perfectly fine. However, because this size doesn't account for the
//! screen's dimensions or pixel density, the button's size can vary quite a bit. On a 4K display, it would be unusably
//! small.
//!
//! That's a description of what happens when the button is 100x100 *physical* pixels. Instead, let's try using 100x100
//! *logical* pixels. To map logical pixels to physical pixels, we simply multiply by the DPI (dots per inch) factor.
//! On a "typical" desktop display, the DPI factor will be 1.0, so 100x100 logical pixels equates to 100x100 physical
//! pixels. However, a 1440p display may have a DPI factor of 1.25, so the button is rendered as 125x125 physical pixels.
//! Ideally, the button now has approximately the same perceived size across varying displays.
//!
//! Failure to account for the DPI factor can create a badly degraded user experience. Most notably, it can make users
//! feel like they have bad eyesight, which will potentially cause them to think about growing elderly, resulting in
//! them entering an existential panic. Once users enter that state, they will no longer be focused on your application.
//!
//! There are two ways to get the DPI factor:
//! - You can track the [`HiDpiFactorChanged`](crate::event::WindowEvent::HiDpiFactorChanged) event of your
//!   windows. This event is sent any time the DPI factor changes, either because the window moved to another monitor,
//!   or because the user changed the configuration of their screen.
//! - You can also retrieve the DPI factor of a monitor by calling
//!   [`MonitorHandle::hidpi_factor`](crate::monitor::MonitorHandle::hidpi_factor), or the
//!   current DPI factor applied to a window by calling
//!   [`Window::hidpi_factor`](crate::window::Window::hidpi_factor), which is roughly equivalent
//!   to `window.current_monitor().hidpi_factor()`.
//!
//! Depending on the platform, the window's actual DPI factor may only be known after
//! the event loop has started and your window has been drawn once. To properly handle these cases,
//! the most robust way is to monitor the [`HiDpiFactorChanged`](crate::event::WindowEvent::HiDpiFactorChanged)
//! event and dynamically adapt your drawing logic to follow the DPI factor.
//!
//! Here's an overview of what sort of DPI factors you can expect, and where they come from:
//! - **Windows:** On Windows 8 and 10, per-monitor scaling is readily configured by users from the display settings.
//! While users are free to select any option they want, they're only given a selection of "nice" DPI factors, i.e.
//! 1.0, 1.25, 1.5... on Windows 7, the DPI factor is global and changing it requires logging out.
//! - **macOS:** The buzzword is "retina displays", which have a DPI factor of 2.0. Otherwise, the DPI factor is 1.0.
//! Intermediate DPI factors are never used, thus 1440p displays/etc. aren't properly supported. It's possible for any
//! display to use that 2.0 DPI factor, given the use of the command line.
//! - **X11:** On X11, we calcuate the DPI factor based on the millimeter dimensions provided by XRandR. This can
//! result in a wide range of possible values, including some interesting ones like 1.0833333333333333. This can be
//! overridden using the `WINIT_HIDPI_FACTOR` environment variable, though that's not recommended.
//! - **Wayland:** On Wayland, DPI factors are set per-screen by the server, and are always integers (most often 1 or 2).
//! - **iOS:** DPI factors are both constant and device-specific on iOS.
//! - **Android:** This feature isn't yet implemented on Android, so the DPI factor will always be returned as 1.0.
//! - **Web:** DPI factors are handled by the browser and will always be 1.0 for your application.
//!
//! The window's logical size is conserved across DPI changes, resulting in the physical size changing instead. This
//! may be surprising on X11, but is quite standard elsewhere. Physical size changes always produce a
//! [`Resized`](crate::event::WindowEvent::Resized) event, even on platforms where no resize actually occurs,
//! such as macOS and Wayland. As a result, it's not necessary to separately handle
//! [`HiDpiFactorChanged`](crate::event::WindowEvent::HiDpiFactorChanged) if you're only listening for size.
//!
//! Your GPU has no awareness of the concept of logical pixels, and unless you like wasting pixel density, your
//! framebuffer's size should be in physical pixels.
//!
//! `winit` will send [`Resized`](crate::event::WindowEvent::Resized) events whenever a window's logical size
//! changes, and [`HiDpiFactorChanged`](crate::event::WindowEvent::HiDpiFactorChanged) events
//! whenever the DPI factor changes. Receiving either of these events means that the physical size of your window has
//! changed, and you should recompute it using the latest values you received for each. If the logical size and the
//! DPI factor change simultaneously, `winit` will send both events together; thus, it's recommended to buffer
//! these events and process them at the end of the queue.
//!
//! If you never received any [`HiDpiFactorChanged`](crate::event::WindowEvent::HiDpiFactorChanged) events,
//! then your window's DPI factor is 1.

/// Checks that the DPI factor is a normal positive `f64`.
///
/// All functions that take a DPI factor assert that this will return `true`. If you're sourcing DPI factors from
/// anywhere other than winit, it's recommended to validate them using this function before passing them to winit;
/// otherwise, you risk panics.
#[inline]
pub fn validate_hidpi_factor(dpi_factor: f64) -> bool {
    dpi_factor.is_sign_positive() && dpi_factor.is_normal()
}

/// A position represented in logical pixels.
///
/// The position is stored as floats, so please be careful. Casting floats to integers truncates the fractional part,
/// which can cause noticable issues. To help with that, an `Into<(i32, i32)>` implementation is provided which
/// does the rounding for you.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct LogicalPosition {
    pub x: f64,
    pub y: f64,
}

impl LogicalPosition {
    #[inline]
    pub fn new(x: f64, y: f64) -> Self {
        LogicalPosition { x, y }
    }

    #[inline]
    pub fn from_physical<T: Into<PhysicalPosition>>(physical: T, dpi_factor: f64) -> Self {
        physical.into().to_logical(dpi_factor)
    }

    #[inline]
    pub fn to_physical(&self, dpi_factor: f64) -> PhysicalPosition {
        assert!(validate_hidpi_factor(dpi_factor));
        let x = self.x * dpi_factor;
        let y = self.y * dpi_factor;
        PhysicalPosition::new(x, y)
    }
}

impl From<(f64, f64)> for LogicalPosition {
    #[inline]
    fn from((x, y): (f64, f64)) -> Self {
        Self::new(x, y)
    }
}

impl From<(i32, i32)> for LogicalPosition {
    #[inline]
    fn from((x, y): (i32, i32)) -> Self {
        Self::new(x as f64, y as f64)
    }
}

impl Into<(f64, f64)> for LogicalPosition {
    #[inline]
    fn into(self) -> (f64, f64) {
        (self.x, self.y)
    }
}

impl Into<(i32, i32)> for LogicalPosition {
    /// Note that this rounds instead of truncating.
    #[inline]
    fn into(self) -> (i32, i32) {
        (self.x.round() as _, self.y.round() as _)
    }
}

/// A position represented in physical pixels.
///
/// The position is stored as floats, so please be careful. Casting floats to integers truncates the fractional part,
/// which can cause noticable issues. To help with that, an `Into<(i32, i32)>` implementation is provided which
/// does the rounding for you.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PhysicalPosition {
    pub x: f64,
    pub y: f64,
}

impl PhysicalPosition {
    #[inline]
    pub fn new(x: f64, y: f64) -> Self {
        PhysicalPosition { x, y }
    }

    #[inline]
    pub fn from_logical<T: Into<LogicalPosition>>(logical: T, dpi_factor: f64) -> Self {
        logical.into().to_physical(dpi_factor)
    }

    #[inline]
    pub fn to_logical(&self, dpi_factor: f64) -> LogicalPosition {
        assert!(validate_hidpi_factor(dpi_factor));
        let x = self.x / dpi_factor;
        let y = self.y / dpi_factor;
        LogicalPosition::new(x, y)
    }
}

impl From<(f64, f64)> for PhysicalPosition {
    #[inline]
    fn from((x, y): (f64, f64)) -> Self {
        Self::new(x, y)
    }
}

impl From<(i32, i32)> for PhysicalPosition {
    #[inline]
    fn from((x, y): (i32, i32)) -> Self {
        Self::new(x as f64, y as f64)
    }
}

impl Into<(f64, f64)> for PhysicalPosition {
    #[inline]
    fn into(self) -> (f64, f64) {
        (self.x, self.y)
    }
}

impl Into<(i32, i32)> for PhysicalPosition {
    /// Note that this rounds instead of truncating.
    #[inline]
    fn into(self) -> (i32, i32) {
        (self.x.round() as _, self.y.round() as _)
    }
}

/// A size represented in logical pixels.
///
/// The size is stored as floats, so please be careful. Casting floats to integers truncates the fractional part,
/// which can cause noticable issues. To help with that, an `Into<(u32, u32)>` implementation is provided which
/// does the rounding for you.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct LogicalSize {
    pub width: f64,
    pub height: f64,
}

impl LogicalSize {
    #[inline]
    pub fn new(width: f64, height: f64) -> Self {
        LogicalSize { width, height }
    }

    #[inline]
    pub fn from_physical<T: Into<PhysicalSize>>(physical: T, dpi_factor: f64) -> Self {
        physical.into().to_logical(dpi_factor)
    }

    #[inline]
    pub fn to_physical(&self, dpi_factor: f64) -> PhysicalSize {
        assert!(validate_hidpi_factor(dpi_factor));
        let width = self.width * dpi_factor;
        let height = self.height * dpi_factor;
        PhysicalSize::new(width, height)
    }
}

impl From<(f64, f64)> for LogicalSize {
    #[inline]
    fn from((width, height): (f64, f64)) -> Self {
        Self::new(width, height)
    }
}

impl From<(u32, u32)> for LogicalSize {
    #[inline]
    fn from((width, height): (u32, u32)) -> Self {
        Self::new(width as f64, height as f64)
    }
}

impl Into<(f64, f64)> for LogicalSize {
    #[inline]
    fn into(self) -> (f64, f64) {
        (self.width, self.height)
    }
}

impl Into<(u32, u32)> for LogicalSize {
    /// Note that this rounds instead of truncating.
    #[inline]
    fn into(self) -> (u32, u32) {
        (self.width.round() as _, self.height.round() as _)
    }
}

/// A size represented in physical pixels.
///
/// The size is stored as floats, so please be careful. Casting floats to integers truncates the fractional part,
/// which can cause noticable issues. To help with that, an `Into<(u32, u32)>` implementation is provided which
/// does the rounding for you.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PhysicalSize {
    pub width: f64,
    pub height: f64,
}

impl PhysicalSize {
    #[inline]
    pub fn new(width: f64, height: f64) -> Self {
        PhysicalSize { width, height }
    }

    #[inline]
    pub fn from_logical<T: Into<LogicalSize>>(logical: T, dpi_factor: f64) -> Self {
        logical.into().to_physical(dpi_factor)
    }

    #[inline]
    pub fn to_logical(&self, dpi_factor: f64) -> LogicalSize {
        assert!(validate_hidpi_factor(dpi_factor));
        let width = self.width / dpi_factor;
        let height = self.height / dpi_factor;
        LogicalSize::new(width, height)
    }
}

impl From<(f64, f64)> for PhysicalSize {
    #[inline]
    fn from((width, height): (f64, f64)) -> Self {
        Self::new(width, height)
    }
}

impl From<(u32, u32)> for PhysicalSize {
    #[inline]
    fn from((width, height): (u32, u32)) -> Self {
        Self::new(width as f64, height as f64)
    }
}

impl Into<(f64, f64)> for PhysicalSize {
    #[inline]
    fn into(self) -> (f64, f64) {
        (self.width, self.height)
    }
}

impl Into<(u32, u32)> for PhysicalSize {
    /// Note that this rounds instead of truncating.
    #[inline]
    fn into(self) -> (u32, u32) {
        (self.width.round() as _, self.height.round() as _)
    }
}
<commit_msg>Fixed typo (#1273)<commit_after>//! DPI is important, so read the docs for this module if you don't want to be confused.
//!
//! Originally, `winit` dealt entirely in physical pixels (excluding unintentional inconsistencies), but now all
//! window-related functions both produce and consume logical pixels. Monitor-related functions still use physical
//! pixels, as do any context-related functions in `glutin`.
//!
//! If you've never heard of these terms before, then you're not alone, and this documentation will explain the
//! concepts.
//!
//! Modern screens have a defined physical resolution, most commonly 1920x1080. Indepedent of that is the amount of
//! space the screen occupies, which is to say, the height and width in millimeters. The relationship between these two
//! measurements is the *pixel density*. Mobile screens require a high pixel density, as they're held close to the
//! eyes. Larger displays also require a higher pixel density, hence the growing presence of 1440p and 4K displays.
//!
//! So, this presents a problem. Let's say we want to render a square 100px button. It will occupy 100x100 of the
//! screen's pixels, which in many cases, seems perfectly fine. However, because this size doesn't account for the
//! screen's dimensions or pixel density, the button's size can vary quite a bit. On a 4K display, it would be unusably
//! small.
//!
//! That's a description of what happens when the button is 100x100 *physical* pixels. Instead, let's try using 100x100
//! *logical* pixels. To map logical pixels to physical pixels, we simply multiply by the DPI (dots per inch) factor.
//! On a "typical" desktop display, the DPI factor will be 1.0, so 100x100 logical pixels equates to 100x100 physical
//! pixels. However, a 1440p display may have a DPI factor of 1.25, so the button is rendered as 125x125 physical pixels.
//! Ideally, the button now has approximately the same perceived size across varying displays.
//!
//! Failure to account for the DPI factor can create a badly degraded user experience. Most notably, it can make users
//! feel like they have bad eyesight, which will potentially cause them to think about growing elderly, resulting in
//! them entering an existential panic. Once users enter that state, they will no longer be focused on your application.
//!
//! There are two ways to get the DPI factor:
//! - You can track the [`HiDpiFactorChanged`](crate::event::WindowEvent::HiDpiFactorChanged) event of your
//!   windows. This event is sent any time the DPI factor changes, either because the window moved to another monitor,
//!   or because the user changed the configuration of their screen.
//! - You can also retrieve the DPI factor of a monitor by calling
//!   [`MonitorHandle::hidpi_factor`](crate::monitor::MonitorHandle::hidpi_factor), or the
//!   current DPI factor applied to a window by calling
//!   [`Window::hidpi_factor`](crate::window::Window::hidpi_factor), which is roughly equivalent
//!   to `window.current_monitor().hidpi_factor()`.
//!
//! Depending on the platform, the window's actual DPI factor may only be known after
//! the event loop has started and your window has been drawn once. To properly handle these cases,
//! the most robust way is to monitor the [`HiDpiFactorChanged`](crate::event::WindowEvent::HiDpiFactorChanged)
//! event and dynamically adapt your drawing logic to follow the DPI factor.
//!
//! Here's an overview of what sort of DPI factors you can expect, and where they come from:
//! - **Windows:** On Windows 8 and 10, per-monitor scaling is readily configured by users from the display settings.
//! While users are free to select any option they want, they're only given a selection of "nice" DPI factors, i.e.
//! 1.0, 1.25, 1.5... on Windows 7, the DPI factor is global and changing it requires logging out.
//! - **macOS:** The buzzword is "retina displays", which have a DPI factor of 2.0. Otherwise, the DPI factor is 1.0.
//! Intermediate DPI factors are never used, thus 1440p displays/etc. aren't properly supported. It's possible for any
//! display to use that 2.0 DPI factor, given the use of the command line.
//! - **X11:** On X11, we calculate the DPI factor based on the millimeter dimensions provided by XRandR. This can
//! result in a wide range of possible values, including some interesting ones like 1.0833333333333333. This can be
//! overridden using the `WINIT_HIDPI_FACTOR` environment variable, though that's not recommended.
//! - **Wayland:** On Wayland, DPI factors are set per-screen by the server, and are always integers (most often 1 or 2).
//! - **iOS:** DPI factors are both constant and device-specific on iOS.
//! - **Android:** This feature isn't yet implemented on Android, so the DPI factor will always be returned as 1.0.
//! - **Web:** DPI factors are handled by the browser and will always be 1.0 for your application.
//!
//! The window's logical size is conserved across DPI changes, resulting in the physical size changing instead. This
//! may be surprising on X11, but is quite standard elsewhere. Physical size changes always produce a
//! [`Resized`](crate::event::WindowEvent::Resized) event, even on platforms where no resize actually occurs,
//! such as macOS and Wayland. As a result, it's not necessary to separately handle
//! [`HiDpiFactorChanged`](crate::event::WindowEvent::HiDpiFactorChanged) if you're only listening for size.
//!
//! Your GPU has no awareness of the concept of logical pixels, and unless you like wasting pixel density, your
//! framebuffer's size should be in physical pixels.
//!
//! `winit` will send [`Resized`](crate::event::WindowEvent::Resized) events whenever a window's logical size
//! changes, and [`HiDpiFactorChanged`](crate::event::WindowEvent::HiDpiFactorChanged) events
//! whenever the DPI factor changes. Receiving either of these events means that the physical size of your window has
//! changed, and you should recompute it using the latest values you received for each. If the logical size and the
//! DPI factor change simultaneously, `winit` will send both events together; thus, it's recommended to buffer
//! these events and process them at the end of the queue.
//!
//! If you never received any [`HiDpiFactorChanged`](crate::event::WindowEvent::HiDpiFactorChanged) events,
//! then your window's DPI factor is 1.

/// Checks that the DPI factor is a normal positive `f64`.
///
/// All functions that take a DPI factor assert that this will return `true`. If you're sourcing DPI factors from
/// anywhere other than winit, it's recommended to validate them using this function before passing them to winit;
/// otherwise, you risk panics.
#[inline]
pub fn validate_hidpi_factor(dpi_factor: f64) -> bool {
    dpi_factor.is_sign_positive() && dpi_factor.is_normal()
}

/// A position represented in logical pixels.
///
/// The position is stored as floats, so please be careful. Casting floats to integers truncates the fractional part,
/// which can cause noticable issues. To help with that, an `Into<(i32, i32)>` implementation is provided which
/// does the rounding for you.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct LogicalPosition {
    pub x: f64,
    pub y: f64,
}

impl LogicalPosition {
    #[inline]
    pub fn new(x: f64, y: f64) -> Self {
        LogicalPosition { x, y }
    }

    #[inline]
    pub fn from_physical<T: Into<PhysicalPosition>>(physical: T, dpi_factor: f64) -> Self {
        physical.into().to_logical(dpi_factor)
    }

    #[inline]
    pub fn to_physical(&self, dpi_factor: f64) -> PhysicalPosition {
        assert!(validate_hidpi_factor(dpi_factor));
        let x = self.x * dpi_factor;
        let y = self.y * dpi_factor;
        PhysicalPosition::new(x, y)
    }
}

impl From<(f64, f64)> for LogicalPosition {
    #[inline]
    fn from((x, y): (f64, f64)) -> Self {
        Self::new(x, y)
    }
}

impl From<(i32, i32)> for LogicalPosition {
    #[inline]
    fn from((x, y): (i32, i32)) -> Self {
        Self::new(x as f64, y as f64)
    }
}

impl Into<(f64, f64)> for LogicalPosition {
    #[inline]
    fn into(self) -> (f64, f64) {
        (self.x, self.y)
    }
}

impl Into<(i32, i32)> for LogicalPosition {
    /// Note that this rounds instead of truncating.
    #[inline]
    fn into(self) -> (i32, i32) {
        (self.x.round() as _, self.y.round() as _)
    }
}

/// A position represented in physical pixels.
///
/// The position is stored as floats, so please be careful. Casting floats to integers truncates the fractional part,
/// which can cause noticable issues. To help with that, an `Into<(i32, i32)>` implementation is provided which
/// does the rounding for you.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PhysicalPosition {
    pub x: f64,
    pub y: f64,
}

impl PhysicalPosition {
    #[inline]
    pub fn new(x: f64, y: f64) -> Self {
        PhysicalPosition { x, y }
    }

    #[inline]
    pub fn from_logical<T: Into<LogicalPosition>>(logical: T, dpi_factor: f64) -> Self {
        logical.into().to_physical(dpi_factor)
    }

    #[inline]
    pub fn to_logical(&self, dpi_factor: f64) -> LogicalPosition {
        assert!(validate_hidpi_factor(dpi_factor));
        let x = self.x / dpi_factor;
        let y = self.y / dpi_factor;
        LogicalPosition::new(x, y)
    }
}

impl From<(f64, f64)> for PhysicalPosition {
    #[inline]
    fn from((x, y): (f64, f64)) -> Self {
        Self::new(x, y)
    }
}

impl From<(i32, i32)> for PhysicalPosition {
    #[inline]
    fn from((x, y): (i32, i32)) -> Self {
        Self::new(x as f64, y as f64)
    }
}

impl Into<(f64, f64)> for PhysicalPosition {
    #[inline]
    fn into(self) -> (f64, f64) {
        (self.x, self.y)
    }
}

impl Into<(i32, i32)> for PhysicalPosition {
    /// Note that this rounds instead of truncating.
    #[inline]
    fn into(self) -> (i32, i32) {
        (self.x.round() as _, self.y.round() as _)
    }
}

/// A size represented in logical pixels.
///
/// The size is stored as floats, so please be careful. Casting floats to integers truncates the fractional part,
/// which can cause noticable issues. To help with that, an `Into<(u32, u32)>` implementation is provided which
/// does the rounding for you.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct LogicalSize {
    pub width: f64,
    pub height: f64,
}

impl LogicalSize {
    #[inline]
    pub fn new(width: f64, height: f64) -> Self {
        LogicalSize { width, height }
    }

    #[inline]
    pub fn from_physical<T: Into<PhysicalSize>>(physical: T, dpi_factor: f64) -> Self {
        physical.into().to_logical(dpi_factor)
    }

    #[inline]
    pub fn to_physical(&self, dpi_factor: f64) -> PhysicalSize {
        assert!(validate_hidpi_factor(dpi_factor));
        let width = self.width * dpi_factor;
        let height = self.height * dpi_factor;
        PhysicalSize::new(width, height)
    }
}

impl From<(f64, f64)> for LogicalSize {
    #[inline]
    fn from((width, height): (f64, f64)) -> Self {
        Self::new(width, height)
    }
}

impl From<(u32, u32)> for LogicalSize {
    #[inline]
    fn from((width, height): (u32, u32)) -> Self {
        Self::new(width as f64, height as f64)
    }
}

impl Into<(f64, f64)> for LogicalSize {
    #[inline]
    fn into(self) -> (f64, f64) {
        (self.width, self.height)
    }
}

impl Into<(u32, u32)> for LogicalSize {
    /// Note that this rounds instead of truncating.
    #[inline]
    fn into(self) -> (u32, u32) {
        (self.width.round() as _, self.height.round() as _)
    }
}

/// A size represented in physical pixels.
///
/// The size is stored as floats, so please be careful. Casting floats to integers truncates the fractional part,
/// which can cause noticable issues. To help with that, an `Into<(u32, u32)>` implementation is provided which
/// does the rounding for you.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PhysicalSize {
    pub width: f64,
    pub height: f64,
}

impl PhysicalSize {
    #[inline]
    pub fn new(width: f64, height: f64) -> Self {
        PhysicalSize { width, height }
    }

    #[inline]
    pub fn from_logical<T: Into<LogicalSize>>(logical: T, dpi_factor: f64) -> Self {
        logical.into().to_physical(dpi_factor)
    }

    #[inline]
    pub fn to_logical(&self, dpi_factor: f64) -> LogicalSize {
        assert!(validate_hidpi_factor(dpi_factor));
        let width = self.width / dpi_factor;
        let height = self.height / dpi_factor;
        LogicalSize::new(width, height)
    }
}

impl From<(f64, f64)> for PhysicalSize {
    #[inline]
    fn from((width, height): (f64, f64)) -> Self {
        Self::new(width, height)
    }
}

impl From<(u32, u32)> for PhysicalSize {
    #[inline]
    fn from((width, height): (u32, u32)) -> Self {
        Self::new(width as f64, height as f64)
    }
}

impl Into<(f64, f64)> for PhysicalSize {
    #[inline]
    fn into(self) -> (f64, f64) {
        (self.width, self.height)
    }
}

impl Into<(u32, u32)> for PhysicalSize {
    /// Note that this rounds instead of truncating.
    #[inline]
    fn into(self) -> (u32, u32) {
        (self.width.round() as _, self.height.round() as _)
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::slice::bytes::copy_memory;

static S: [u8, ..256] = [
    0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
    0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
    0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
    0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
    0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
    0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
    0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
    0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
    0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
    0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
    0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
    0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
    0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
    0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
    0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
    0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
];

#[inline]
fn md2_pad(msg: &[u8]) -> Vec<u8> {
    let mut msg = msg.to_vec();
    let pad = 16 - msg.len() % 16;
    msg.grow_fn(pad, |_| pad as u8);
    msg
}

#[inline]
fn md2_checksum(msg: &[u8]) -> [u8, ..16] {
    let mut checksum = [0u8, ..16];
    let mut last = 0u8;

    for chunk in msg.chunks(16) {
        for (i, byte) in checksum.iter_mut().enumerate() {
            *byte ^= S[(chunk[i] ^ last) as uint];
            last = *byte;
        }
    }

    checksum
}

#[inline]
fn md2_compress(state: &[u8], msg: &[u8]) -> [u8, ..16] {
    // Two 128 bit blocks in, one 128 bit block out.
    assert!(state.len() == 16 && msg.len() == 16);

    let mut x = [0u8, ..48];
    let mut result = [0u8, ..16];

    // Copy over the previous state.
    copy_memory(x.slice_mut(0, 16), state);

    // Copy over the message block.
    copy_memory(x.slice_mut(16, 32), msg);

    // XOR the previous state and the message block.
    for (i, byte) in msg.iter().enumerate() {
        x[32 + i] = *byte ^ x[i];
    }

    // Encrypt block (18 rounds).
    let mut t = 0u8;
    for i in range(0, 18) {
        for byte in x.iter_mut() {
            *byte ^= S[t as uint];
            t = *byte;
        }
        t += i;
    }

    // Copy the new state.
    copy_memory(&mut result, x.slice(0, 16));
    result
}

pub fn md2(msg: &[u8]) -> [u8, ..16] {
    // Pad the message to be a multiple of 16 bytes long.
    let msg = md2_pad(msg);
    assert!(msg.len() % 16 == 0);

    // Compress all message blocks.
    let state = msg.chunks(16).fold([0u8, ..16], |s, m| md2_compress(&s, m));

    // Compute the checksum.
    let checksum = md2_checksum(msg.as_slice());

    // Compress checksum and return.
    md2_compress(&state, &checksum)
}

#[cfg(test)]
mod test {
    use md2;

    fn hex(buf: &[u8]) -> String {
        buf.iter().fold(String::new(), |a, &b| format!("{}{:02x}", a, b))
    }

    fn cmp(d: &str, s: &str) {
        assert_eq!(d.to_string(), hex(&md2(s.as_bytes())));
    }

    #[test]
    fn test_md2() {
        cmp("8350e5a3e24c153df2275c9f80692773", "");
        cmp("32ec01ec4a6dac72c0ab96fb34c0b5d1", "a");
        cmp("da853b0d3f88d99b30283a69e6ded6bb", "abc");
        cmp("ab4f496bfb2a530b219ff33031fe06b0", "message digest");
        cmp("4e8ddff3650292ab5a4108c3aa47940b", "abcdefghijklmnopqrstuvwxyz");
        cmp("da33def2a42df13975352846c30338cd", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
        cmp("d5976f79d83d3a0dc9806c3c66f3efd8", "12345678901234567890123456789012345678901234567890123456789012345678901234567890");
    }
}
<commit_msg>add reverse s-box<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::slice::bytes::copy_memory;

static S: [u8, ..256] = [
    0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
    0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
    0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
    0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
    0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
    0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
    0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
    0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
    0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
    0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
    0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
    0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
    0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
    0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
    0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
    0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
];

static S2: [u8, ..256] = [
    0xDD, 0x07, 0x8F, 0x5F, 0x7E, 0x12, 0x0E, 0x46, 0xCB, 0xB7, 0xEF, 0x4C, 0xCC, 0xB2, 0xE3, 0x9F,
    0x4A, 0xFD, 0x2F, 0x0F, 0xFF, 0x44, 0x27, 0x2D, 0x2B, 0x61, 0xF7, 0x90, 0x98, 0xDE, 0x20, 0xF6,
    0x87, 0x4F, 0x4D, 0xA3, 0xC8, 0x92, 0xAF, 0x57, 0xB5, 0x00, 0x6B, 0x1A, 0xB0, 0x8D, 0x01, 0x3D,
    0x62, 0xF0, 0x56, 0xFB, 0x9C, 0x58, 0x09, 0xC2, 0x72, 0xDF, 0xA7, 0xDC, 0x23, 0x08, 0x59, 0x47,
    0x9D, 0xBC, 0x29, 0x02, 0xF1, 0x80, 0x99, 0xA1, 0x64, 0x37, 0xCF, 0xEE, 0x1D, 0xBE, 0x31, 0x70,
    0xF2, 0xA5, 0xBF, 0xB1, 0x0A, 0xA0, 0x6D, 0x22, 0xE5, 0x83, 0x54, 0x89, 0xA9, 0x52, 0x69, 0x4E,
    0x91, 0x9A, 0x10, 0xD5, 0x84, 0x8B, 0xE4, 0x28, 0x41, 0x9B, 0xC0, 0x7A, 0xC4, 0xD7, 0xB3, 0x2A,
    0x82, 0x85, 0xEA, 0x16, 0x7D, 0xED, 0x78, 0xE9, 0xD0, 0x42, 0x3F, 0xCA, 0x06, 0x76, 0x9E, 0x51,
    0x50, 0xBD, 0x1E, 0xFE, 0xB6, 0xB4, 0x88, 0x86, 0xD1, 0x4B, 0x2C, 0xD3, 0x17, 0xFA, 0x3B, 0xF4,
    0x55, 0x43, 0x6A, 0x19, 0x48, 0xD2, 0x74, 0x5E, 0x18, 0xF9, 0x53, 0x21, 0x7C, 0x81, 0x35, 0xFC,
    0x38, 0x0B, 0x04, 0xA2, 0x75, 0x65, 0xE8, 0x11, 0x8E, 0x40, 0x6E, 0xC6, 0x6C, 0x93, 0x94, 0xA6,
    0x95, 0xCE, 0x45, 0x63, 0xF3, 0x66, 0x77, 0xE2, 0x71, 0x96, 0xAC, 0x3C, 0x1C, 0xCD, 0x30, 0x5C,
    0x14, 0xC5, 0x49, 0xA8, 0x32, 0xAD, 0x6F, 0x15, 0xC3, 0x03, 0x1F, 0xD9, 0x5A, 0xBA, 0xAB, 0x8A,
    0xE6, 0x67, 0x73, 0xB8, 0x25, 0xDA, 0x33, 0x68, 0x05, 0x1B, 0x34, 0xF8, 0xC1, 0xA4, 0x36, 0xB9,
    0x26, 0xC9, 0x7B, 0xD4, 0xE7, 0x2E, 0x8C, 0x5B, 0xD6, 0xD8, 0xAE, 0xEC, 0x0C, 0xF5, 0x3E, 0xE1,
    0x0D, 0x7F, 0xE0, 0x13, 0xBB, 0x3A, 0x97, 0x5D, 0xEB, 0xAA, 0xC7, 0x39, 0x79, 0x24, 0xDB, 0x60
];

#[inline]
fn md2_pad(msg: &[u8]) -> Vec<u8> {
    let mut msg = msg.to_vec();
    let pad = 16 - msg.len() % 16;
    msg.grow_fn(pad, |_| pad as u8);
    msg
}

#[inline]
fn md2_checksum(msg: &[u8]) -> [u8, ..16] {
    let mut checksum = [0u8, ..16];
    let mut last = 0u8;

    for chunk in msg.chunks(16) {
        for (i, byte) in checksum.iter_mut().enumerate() {
            *byte ^= S[(chunk[i] ^ last) as uint];
            last = *byte;
        }
    }

    checksum
}

#[inline]
fn md2_compress(state: &[u8], msg: &[u8]) -> [u8, ..16] {
    // Two 128 bit blocks in, one 128 bit block out.
    assert!(state.len() == 16 && msg.len() == 16);

    let mut x = [0u8, ..48];
    let mut result = [0u8, ..16];

    // Copy over the previous state.
    copy_memory(x.slice_mut(0, 16), state);

    // Copy over the message block.
    copy_memory(x.slice_mut(16, 32), msg);

    // XOR the previous state and the message block.
    for (i, byte) in msg.iter().enumerate() {
        x[32 + i] = *byte ^ x[i];
    }

    // Encrypt block (18 rounds).
    let mut t = 0u8;
    for i in range(0, 18) {
        for byte in x.iter_mut() {
            *byte ^= S[t as uint];
            t = *byte;
        }
        t += i;
    }

    // Copy the new state.
    copy_memory(&mut result, x.slice(0, 16));
    result
}

pub fn md2(msg: &[u8]) -> [u8, ..16] {
    // Pad the message to be a multiple of 16 bytes long.
    let msg = md2_pad(msg);
    assert!(msg.len() % 16 == 0);

    // Compress all message blocks.
    let state = msg.chunks(16).fold([0u8, ..16], |s, m| md2_compress(&s, m));

    // Compute the checksum.
    let checksum = md2_checksum(msg.as_slice());

    // Compress checksum and return.
    md2_compress(&state, &checksum)
}

#[cfg(test)]
mod test {
    use md2;

    fn hex(buf: &[u8]) -> String {
        buf.iter().fold(String::new(), |a, &b| format!("{}{:02x}", a, b))
    }

    fn cmp(d: &str, s: &str) {
        assert_eq!(d.to_string(), hex(&md2(s.as_bytes())));
    }

    #[test]
    fn test_md2() {
        cmp("8350e5a3e24c153df2275c9f80692773", "");
        cmp("32ec01ec4a6dac72c0ab96fb34c0b5d1", "a");
        cmp("da853b0d3f88d99b30283a69e6ded6bb", "abc");
        cmp("ab4f496bfb2a530b219ff33031fe06b0", "message digest");
        cmp("4e8ddff3650292ab5a4108c3aa47940b", "abcdefghijklmnopqrstuvwxyz");
        cmp("da33def2a42df13975352846c30338cd", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
        cmp("d5976f79d83d3a0dc9806c3c66f3efd8", "12345678901234567890123456789012345678901234567890123456789012345678901234567890");
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]
#![feature(globs, phase)]

extern crate libc;
#[cfg(test)]
extern crate quickcheck;
#[cfg(test)]
#[phase(plugin)]
extern crate quickcheck_macros;

use std::io::{File, FileAccess, FileMode, IoError, IoResult};
use std::num::FromPrimitive;
use std::os::unix::AsRawFd;

use termios::{FAILURE, Termios, SUCCESS};

mod termios;
#[cfg(test)]
mod socat;
#[cfg(test)]
mod test;

#[derive(Copy, PartialEq)]
pub struct BlockingMode {
    /// The device will block until `bytes` are received
    pub bytes: u8,
    /// The device will block for at least `deciseconds` after each `read()` call
    pub deciseconds: u8,
}

pub struct SerialPort {
    fd: libc::c_int,
    file: File,
    termios: Termios,
}

impl SerialPort {
    /// Opens a serial `device` in "raw" mode
    pub fn open(device: &Path, access: FileAccess) -> IoResult<SerialPort> {
        let file = try!(File::open_mode(device, FileMode::Open, access));
        let fd = file.as_raw_fd();

        let mut termios = Termios::new();

        match unsafe { termios::tcgetattr(fd, &mut termios) } {
            FAILURE => return Err(IoError::last_error()),
            SUCCESS => {},
            _ => unreachable!(),
        }

        unsafe { termios::cfmakeraw(&mut termios) };

        let sp = SerialPort { fd: fd, file: file, termios: termios };

        try!(sp.update());

        Ok(sp)
    }

    /// Returns the input and output baud rates
    #[cfg(target_os = "linux")]
    pub fn baud_rate(&self) -> IoResult<(BaudRate, BaudRate)> {
        let termios = try!(self.fetch());

        let input = termios.c_ispeed;
        let input = match FromPrimitive::from_u32(input) {
            None => panic!("unrecognized BaudRate value: {}", input),
            Some(input) => input,
        };

        let output = termios.c_ospeed;
        let output = match FromPrimitive::from_u32(output) {
            None => panic!("unrecognized BaudRate value: {}", output),
            Some(output) => output,
        };

        Ok((input, output))
    }

    /// Returns the input and output baud rates
    #[cfg(target_os = "macos")]
    pub fn baud_rate(&self) -> IoResult<(BaudRate, BaudRate)> {
        let termios = try!(self.fetch());

        let input = termios.c_ispeed;
        let input = match FromPrimitive::from_u64(input) {
            None => panic!("unrecognized BaudRate value: {}", input),
            Some(input) => input,
        };

        let output = termios.c_ospeed;
        let output = match FromPrimitive::from_u64(output) {
            None => panic!("unrecognized BaudRate value: {}", output),
            Some(output) => output,
        };

        Ok((input, output))
    }

    /// Returns the blocking mode used by the device
    pub fn blocking_mode(&self) -> IoResult<BlockingMode> {
        use termios::{VMIN, VTIME};

        Ok(BlockingMode {
            bytes: self.termios.c_cc[VMIN as uint],
            deciseconds: self.termios.c_cc[VTIME as uint],
        })
    }

    /// Returns the number of data bits used per character
    #[cfg(target_os = "linux")]
    pub fn data_bits(&self) -> IoResult<DataBits> {
        use termios::CSIZE;

        let bits = try!(self.fetch()).c_cflag & CSIZE;

        match FromPrimitive::from_u32(bits) {
            None => panic!("unrecognized DataBits value: {}", bits),
            Some(bits) => Ok(bits),
        }
    }

    /// Returns the number of data bits used per character
    #[cfg(target_os = "macos")]
    pub fn data_bits(&self) -> IoResult<DataBits> {
        use termios::CSIZE;

        let bits = try!(self.fetch()).c_cflag & CSIZE;

        match FromPrimitive::from_u64(bits) {
            None => panic!("unrecognized DataBits value: {}", bits),
            Some(bits) => Ok(bits),
        }
    }

    /// Returns the flow control used by the device
    pub fn flow_control(&self) -> IoResult<FlowControl> {
        use FlowControl::*;
        use termios::{CRTSCTS, IXANY, IXOFF, IXON};

        let termios = try!(self.fetch());

        if termios.c_cflag & CRTSCTS != 0 {
            Ok(Hardware)
        } else if termios.c_iflag & (IXANY | IXOFF | IXON) == 0 {
            Ok(None)
        } else {
            Ok(Software)
        }
    }

    /// Returns the bit parity used by the device
    pub fn parity(&self) -> IoResult<Parity> {
        use Parity::*;
        use termios::{PARENB, PARODD};

        let termios = try!(self.fetch());

        match (termios.c_cflag & PARENB != 0, termios.c_cflag & PARODD != 0) {
            (true, true) => Ok(Odd),
            (true, false) => Ok(Even),
            (false, _) => Ok(None),
        }
    }

    /// Changes the baud rate of the input/output or both directions
    pub fn set_baud_rate(&mut self, direction: Direction, rate: BaudRate) -> IoResult<()> {
        use Direction::*;
        use termios::speed_t;

        match unsafe { match direction {
            Both => termios::cfsetspeed(&mut self.termios, rate as speed_t),
            Input => termios::cfsetispeed(&mut self.termios, rate as speed_t),
            Output => termios::cfsetospeed(&mut self.termios, rate as speed_t),
        } } {
            FAILURE => Err(IoError::last_error()),
            SUCCESS => self.update(),
            _ => unreachable!(),
        }
    }

    /// Changes the blocking mode used by the device
    pub fn set_blocking_mode(&mut self, mode: BlockingMode) -> IoResult<()> {
        use termios::{VMIN, VTIME};

        self.termios.c_cc[VMIN as uint] = mode.bytes;
        self.termios.c_cc[VTIME as uint] = mode.deciseconds;

        self.update()
    }

    /// Changes the number of data bits per character
    #[cfg(target_os = "linux")]
    pub fn set_data_bits(&mut self, bits: DataBits) -> IoResult<()> {
        use termios::CSIZE;

        self.termios.c_cflag &= !CSIZE;
        self.termios.c_cflag |= bits as u32;

        self.update()
    }

    /// Changes the number of data bits per character
    #[cfg(target_os = "macos")]
    pub fn set_data_bits(&mut self, bits: DataBits) -> IoResult<()> {
        use termios::CSIZE;

        self.termios.c_cflag &= !CSIZE;
        self.termios.c_cflag |= bits as u64;

        self.update()
    }

    /// Changes the flow control used by the device
    pub fn set_flow_control(&mut self, flow: FlowControl) -> IoResult<()> {
        use FlowControl::*;
        use termios::{CRTSCTS, IXANY, IXOFF, IXON};

        match flow {
            Hardware=> {
                self.termios.c_cflag |= CRTSCTS;
                self.termios.c_iflag &= !(IXANY | IXOFF | IXON);
            },
            None => {
                self.termios.c_cflag &= !CRTSCTS;
                self.termios.c_iflag &= !(IXANY | IXOFF | IXON);
            },
            Software => {
                self.termios.c_cflag &= !CRTSCTS;
                self.termios.c_iflag |= IXANY | IXOFF | IXON;
            },
        }

        self.update()
    }

    /// Changes the bit parity used by the device
    pub fn set_parity(&mut self, parity: Parity) -> IoResult<()> {
        use Parity::*;
        use termios::{PARENB, PARODD};

        match parity {
            Even=> {
                self.termios.c_cflag |= PARENB;
                self.termios.c_cflag &= !PARODD;
            },
            None => self.termios.c_cflag &= !PARENB,
            Odd=> self.termios.c_cflag |= PARENB | PARODD,
        }

        self.update()
    }

    /// Changes the number of stop bits per character
    pub fn set_stop_bits(&mut self, bits: StopBits) -> IoResult<()> {
        use StopBits::*;
        use termios::CSTOPB;

        match bits {
            One => self.termios.c_cflag &= !CSTOPB,
            Two => self.termios.c_cflag |= CSTOPB,
        }

        self.update()
    }

    /// Returns the number of stop bits per character
    pub fn stop_bits(&self) -> IoResult<StopBits> {
        use StopBits::*;
        use termios::CSTOPB;

        if try!(self.fetch()).c_cflag & CSTOPB == 0 {
            Ok(One)
        } else {
            Ok(Two)
        }
    }

    /// Fetches the current state of the termios structure
    fn fetch(&self) -> IoResult<Termios> {
        let mut termios = Termios::new();

        match unsafe { termios::tcgetattr(self.fd, &mut termios) } {
            FAILURE => Err(IoError::last_error()),
            SUCCESS => Ok(termios),
            _ => unreachable!(),
        }
    }

    /// Updates the underlying termios structure
    fn update(&self) -> IoResult<()> {
        use termios::TCSANOW;

        match unsafe { termios::tcsetattr(self.fd, TCSANOW, &self.termios) } {
            FAILURE => Err(IoError::last_error()),
            SUCCESS => Ok(()),
            _ => unreachable!(),
        }
    }
}

impl Reader for SerialPort {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.file.read(buf)
    }
}

impl Writer for SerialPort {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.file.write(buf)
    }
}

#[cfg(target_os = "linux")]
#[derive(Copy, FromPrimitive, PartialEq, Show)]
#[repr(u32)]
pub enum BaudRate {
    B0 = termios::B0,
    B50 = termios::B50,
    B75 = termios::B75,
    B110 = termios::B110,
    B134 = termios::B134,
    B150 = termios::B150,
    B200 = termios::B200,
    B300 = termios::B300,
    B600 = termios::B600,
    B1K2 = termios::B1200,
    B1K8 = termios::B1800,
    B2K4 = termios::B2400,
    B4K8 = termios::B4800,
    B9K6 = termios::B9600,
    B19K2 = termios::B19200,
    B38K4 = termios::B38400,
    B57K6 = termios::B57600,
    B115K2 = termios::B115200,
    B230K4 = termios::B230400,
    B460K8 = termios::B460800,
    B500K = termios::B500000,
    B576K = termios::B576000,
    B921K6 = termios::B921600,
    B1M = termios::B1000000,
    B1M152 = termios::B1152000,
    B1M5 = termios::B1500000,
    B2M = termios::B2000000,
    B2M5 = termios::B2500000,
    B3M = termios::B3000000,
    B3M5 = termios::B3500000,
    B4M = termios::B4000000,
}

#[cfg(target_os = "macos")]
#[derive(Copy, FromPrimitive, PartialEq, Show)]
#[repr(u64)]
pub enum BaudRate {
    B0 = termios::B0,
    B50 = termios::B50,
    B75 = termios::B75,
    B110 = termios::B110,
    B134 = termios::B134,
    B150 = termios::B150,
    B200 = termios::B200,
    B300 = termios::B300,
    B600 = termios::B600,
    B1K2 = termios::B1200,
    B1K8 = termios::B1800,
    B2K4 = termios::B2400,
    B4K8 = termios::B4800,
    B7K2 = termios::B7200,
    B9K6 = termios::B9600,
    B14K4 = termios::B14400,
    B19K2 = termios::B19200,
    B28K8 = termios::B28800,
    B38K4 = termios::B38400,
    B57K6 = termios::B57600,
    B76K8 = termios::B76800,
    B115K2 = termios::B115200,
    B230K4 = termios::B230400,
}

#[cfg(target_os = "linux")]
#[derive(Copy, FromPrimitive, PartialEq, Show)]
#[repr(u32)]
pub enum DataBits {
    Five = termios::CS5,
    Six = termios::CS6,
    Seven = termios::CS7,
    Eight = termios::CS8,
}

#[cfg(target_os = "macos")]
#[derive(Copy, FromPrimitive, PartialEq, Show)]
#[repr(u64)]
pub enum DataBits {
    Five = termios::CS5,
    Six = termios::CS6,
    Seven = termios::CS7,
    Eight = termios::CS8,
}

#[derive(Copy)]
pub enum Direction {
    Both,
    Input,
    Output,
}

#[derive(Copy, FromPrimitive, PartialEq, Show)]
pub enum FlowControl {
    Hardware,
    None,
    Software,
}

#[derive(Copy, FromPrimitive, PartialEq, Show)]
pub enum Parity {
    Even,
    None,
    Odd,
}

#[derive(Copy, FromPrimitive, PartialEq, Show)]
#[repr(u32)]
pub enum StopBits {
    One,
    Two,
}
<commit_msg>fix: update to rust nightly<commit_after>#![deny(warnings)]
#![feature(plugin)]

extern crate libc;
#[cfg(test)]
extern crate quickcheck;
#[cfg(test)]
#[plugin]
extern crate quickcheck_macros;

use std::io::{File, FileAccess, FileMode, IoError, IoResult};
use std::num::FromPrimitive;
use std::os::unix::AsRawFd;

use termios::{FAILURE, Termios, SUCCESS};

mod termios;
#[cfg(test)]
mod socat;
#[cfg(test)]
mod test;

#[derive(Copy, PartialEq)]
pub struct BlockingMode {
    /// The device will block until `bytes` are received
    pub bytes: u8,
    /// The device will block for at least `deciseconds` after each `read()` call
    pub deciseconds: u8,
}

pub struct SerialPort {
    fd: libc::c_int,
    file: File,
    termios: Termios,
}

impl SerialPort {
    /// Opens a serial `device` in "raw" mode
    pub fn open(device: &Path, access: FileAccess) -> IoResult<SerialPort> {
        let file = try!(File::open_mode(device, FileMode::Open, access));
        let fd = file.as_raw_fd();

        let mut termios = Termios::new();

        match unsafe { termios::tcgetattr(fd, &mut termios) } {
            FAILURE => return Err(IoError::last_error()),
            SUCCESS => {},
            _ => unreachable!(),
        }

        unsafe { termios::cfmakeraw(&mut termios) };

        let sp = SerialPort { fd: fd, file: file, termios: termios };

        try!(sp.update());

        Ok(sp)
    }

    /// Returns the input and output baud rates
    #[cfg(target_os = "linux")]
    pub fn baud_rate(&self) -> IoResult<(BaudRate, BaudRate)> {
        let termios = try!(self.fetch());

        let input = termios.c_ispeed;
        let input = match FromPrimitive::from_u32(input) {
            None => panic!("unrecognized BaudRate value: {}", input),
            Some(input) => input,
        };

        let output = termios.c_ospeed;
        let output = match FromPrimitive::from_u32(output) {
            None => panic!("unrecognized BaudRate value: {}", output),
            Some(output) => output,
        };

        Ok((input, output))
    }

    /// Returns the input and output baud rates
    #[cfg(target_os = "macos")]
    pub fn baud_rate(&self) -> IoResult<(BaudRate, BaudRate)> {
        let termios = try!(self.fetch());

        let input = termios.c_ispeed;
        let input = match FromPrimitive::from_u64(input) {
            None => panic!("unrecognized BaudRate value: {}", input),
            Some(input) => input,
        };

        let output = termios.c_ospeed;
        let output = match FromPrimitive::from_u64(output) {
            None => panic!("unrecognized BaudRate value: {}", output),
            Some(output) => output,
        };

        Ok((input, output))
    }

    /// Returns the blocking mode used by the device
    pub fn blocking_mode(&self) -> IoResult<BlockingMode> {
        use termios::{VMIN, VTIME};

        Ok(BlockingMode {
            bytes: self.termios.c_cc[VMIN as uint],
            deciseconds: self.termios.c_cc[VTIME as uint],
        })
    }

    /// Returns the number of data bits used per character
    #[cfg(target_os = "linux")]
    pub fn data_bits(&self) -> IoResult<DataBits> {
        use termios::CSIZE;

        let bits = try!(self.fetch()).c_cflag & CSIZE;

        match FromPrimitive::from_u32(bits) {
            None => panic!("unrecognized DataBits value: {}", bits),
            Some(bits) => Ok(bits),
        }
    }

    /// Returns the number of data bits used per character
    #[cfg(target_os = "macos")]
    pub fn data_bits(&self) -> IoResult<DataBits> {
        use termios::CSIZE;

        let bits = try!(self.fetch()).c_cflag & CSIZE;

        match FromPrimitive::from_u64(bits) {
            None => panic!("unrecognized DataBits value: {}", bits),
            Some(bits) => Ok(bits),
        }
    }

    /// Returns the flow control used by the device
    pub fn flow_control(&self) -> IoResult<FlowControl> {
        use FlowControl::*;
        use termios::{CRTSCTS, IXANY, IXOFF, IXON};

        let termios = try!(self.fetch());

        if termios.c_cflag & CRTSCTS != 0 {
            Ok(Hardware)
        } else if termios.c_iflag & (IXANY | IXOFF | IXON) == 0 {
            Ok(None)
        } else {
            Ok(Software)
        }
    }

    /// Returns the bit parity used by the device
    pub fn parity(&self) -> IoResult<Parity> {
        use Parity::*;
        use termios::{PARENB, PARODD};

        let termios = try!(self.fetch());

        match (termios.c_cflag & PARENB != 0, termios.c_cflag & PARODD != 0) {
            (true, true) => Ok(Odd),
            (true, false) => Ok(Even),
            (false, _) => Ok(None),
        }
    }

    /// Changes the baud rate of the input/output or both directions
    pub fn set_baud_rate(&mut self, direction: Direction, rate: BaudRate) -> IoResult<()> {
        use Direction::*;
        use termios::speed_t;

        match unsafe { match direction {
            Both => termios::cfsetspeed(&mut self.termios, rate as speed_t),
            Input => termios::cfsetispeed(&mut self.termios, rate as speed_t),
            Output => termios::cfsetospeed(&mut self.termios, rate as speed_t),
        } } {
            FAILURE => Err(IoError::last_error()),
            SUCCESS => self.update(),
            _ => unreachable!(),
        }
    }

    /// Changes the blocking mode used by the device
    pub fn set_blocking_mode(&mut self, mode: BlockingMode) -> IoResult<()> {
        use termios::{VMIN, VTIME};

        self.termios.c_cc[VMIN as uint] = mode.bytes;
        self.termios.c_cc[VTIME as uint] = mode.deciseconds;

        self.update()
    }

    /// Changes the number of data bits per character
    #[cfg(target_os = "linux")]
    pub fn set_data_bits(&mut self, bits: DataBits) -> IoResult<()> {
        use termios::CSIZE;

        self.termios.c_cflag &= !CSIZE;
        self.termios.c_cflag |= bits as u32;

        self.update()
    }

    /// Changes the number of data bits per character
    #[cfg(target_os = "macos")]
    pub fn set_data_bits(&mut self, bits: DataBits) -> IoResult<()> {
        use termios::CSIZE;

        self.termios.c_cflag &= !CSIZE;
        self.termios.c_cflag |= bits as u64;

        self.update()
    }

    /// Changes the flow control used by the device
    pub fn set_flow_control(&mut self, flow: FlowControl) -> IoResult<()> {
        use FlowControl::*;
        use termios::{CRTSCTS, IXANY, IXOFF, IXON};

        match flow {
            Hardware=> {
                self.termios.c_cflag |= CRTSCTS;
                self.termios.c_iflag &= !(IXANY | IXOFF | IXON);
            },
            None => {
                self.termios.c_cflag &= !CRTSCTS;
                self.termios.c_iflag &= !(IXANY | IXOFF | IXON);
            },
            Software => {
                self.termios.c_cflag &= !CRTSCTS;
                self.termios.c_iflag |= IXANY | IXOFF | IXON;
            },
        }

        self.update()
    }

    /// Changes the bit parity used by the device
    pub fn set_parity(&mut self, parity: Parity) -> IoResult<()> {
        use Parity::*;
        use termios::{PARENB, PARODD};

        match parity {
            Even=> {
                self.termios.c_cflag |= PARENB;
                self.termios.c_cflag &= !PARODD;
            },
            None => self.termios.c_cflag &= !PARENB,
            Odd=> self.termios.c_cflag |= PARENB | PARODD,
        }

        self.update()
    }

    /// Changes the number of stop bits per character
    pub fn set_stop_bits(&mut self, bits: StopBits) -> IoResult<()> {
        use StopBits::*;
        use termios::CSTOPB;

        match bits {
            One => self.termios.c_cflag &= !CSTOPB,
            Two => self.termios.c_cflag |= CSTOPB,
        }

        self.update()
    }

    /// Returns the number of stop bits per character
    pub fn stop_bits(&self) -> IoResult<StopBits> {
        use StopBits::*;
        use termios::CSTOPB;

        if try!(self.fetch()).c_cflag & CSTOPB == 0 {
            Ok(One)
        } else {
            Ok(Two)
        }
    }

    /// Fetches the current state of the termios structure
    fn fetch(&self) -> IoResult<Termios> {
        let mut termios = Termios::new();

        match unsafe { termios::tcgetattr(self.fd, &mut termios) } {
            FAILURE => Err(IoError::last_error()),
            SUCCESS => Ok(termios),
            _ => unreachable!(),
        }
    }

    /// Updates the underlying termios structure
    fn update(&self) -> IoResult<()> {
        use termios::TCSANOW;

        match unsafe { termios::tcsetattr(self.fd, TCSANOW, &self.termios) } {
            FAILURE => Err(IoError::last_error()),
            SUCCESS => Ok(()),
            _ => unreachable!(),
        }
    }
}

impl Reader for SerialPort {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.file.read(buf)
    }
}

impl Writer for SerialPort {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.file.write(buf)
    }
}

#[cfg(target_os = "linux")]
#[derive(Copy, FromPrimitive, PartialEq, Show)]
#[repr(u32)]
pub enum BaudRate {
    B0 = termios::B0,
    B50 = termios::B50,
    B75 = termios::B75,
    B110 = termios::B110,
    B134 = termios::B134,
    B150 = termios::B150,
    B200 = termios::B200,
    B300 = termios::B300,
    B600 = termios::B600,
    B1K2 = termios::B1200,
    B1K8 = termios::B1800,
    B2K4 = termios::B2400,
    B4K8 = termios::B4800,
    B9K6 = termios::B9600,
    B19K2 = termios::B19200,
    B38K4 = termios::B38400,
    B57K6 = termios::B57600,
    B115K2 = termios::B115200,
    B230K4 = termios::B230400,
    B460K8 = termios::B460800,
    B500K = termios::B500000,
    B576K = termios::B576000,
    B921K6 = termios::B921600,
    B1M = termios::B1000000,
    B1M152 = termios::B1152000,
    B1M5 = termios::B1500000,
    B2M = termios::B2000000,
    B2M5 = termios::B2500000,
    B3M = termios::B3000000,
    B3M5 = termios::B3500000,
    B4M = termios::B4000000,
}

#[cfg(target_os = "macos")]
#[derive(Copy, FromPrimitive, PartialEq, Show)]
#[repr(u64)]
pub enum BaudRate {
    B0 = termios::B0,
    B50 = termios::B50,
    B75 = termios::B75,
    B110 = termios::B110,
    B134 = termios::B134,
    B150 = termios::B150,
    B200 = termios::B200,
    B300 = termios::B300,
    B600 = termios::B600,
    B1K2 = termios::B1200,
    B1K8 = termios::B1800,
    B2K4 = termios::B2400,
    B4K8 = termios::B4800,
    B7K2 = termios::B7200,
    B9K6 = termios::B9600,
    B14K4 = termios::B14400,
    B19K2 = termios::B19200,
    B28K8 = termios::B28800,
    B38K4 = termios::B38400,
    B57K6 = termios::B57600,
    B76K8 = termios::B76800,
    B115K2 = termios::B115200,
    B230K4 = termios::B230400,
}

#[cfg(target_os = "linux")]
#[derive(Copy, FromPrimitive, PartialEq, Show)]
#[repr(u32)]
pub enum DataBits {
    Five = termios::CS5,
    Six = termios::CS6,
    Seven = termios::CS7,
    Eight = termios::CS8,
}

#[cfg(target_os = "macos")]
#[derive(Copy, FromPrimitive, PartialEq, Show)]
#[repr(u64)]
pub enum DataBits {
    Five = termios::CS5,
    Six = termios::CS6,
    Seven = termios::CS7,
    Eight = termios::CS8,
}

#[derive(Copy)]
pub enum Direction {
    Both,
    Input,
    Output,
}

#[derive(Copy, FromPrimitive, PartialEq, Show)]
pub enum FlowControl {
    Hardware,
    None,
    Software,
}

#[derive(Copy, FromPrimitive, PartialEq, Show)]
pub enum Parity {
    Even,
    None,
    Odd,
}

#[derive(Copy, FromPrimitive, PartialEq, Show)]
#[repr(u32)]
pub enum StopBits {
    One,
    Two,
}
<|endoftext|>


<commit_before>
pub fn puzzle(input: &str) -> u32 {
    0
}

#[derive(Debug, Copy, Clone, PartialEq)]
enum Tile {
    Safe,
    Trap,
}

fn next_tile(left: Tile, center: Tile, right: Tile) -> Tile {
    use Tile::*;
    match (left, center, right) {
        (Trap, Trap, Safe) => Trap,
        (Safe, Trap, Trap) => Trap,
        (Trap, Safe, Safe) => Trap,
        (Safe, Safe, Trap) => Trap,
        _ => Safe,
    }
}

#[derive(Debug, Clone, PartialEq)]
struct Row(Vec<Tile>);

impl Row {
    fn next(&self) -> Row {
        let mut x = vec![Tile::Safe];
        x.extend_from_slice(&self.0);
        x.push(Tile::Safe);

        Row(x.windows(3).map(|tiles| {
            next_tile(tiles[0], tiles[1], tiles[2])
        }).collect())
    }
}

fn string_to_row(s: &str) -> Row {
    Row(s.chars().map(|c| {
        match c {
            '.' => Tile::Safe,
            '^' => Tile::Trap,
            _ => panic!("unknown tile character {}", c),
        }
    }).collect())
}

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

    #[test]
    fn safe() {
        assert_eq!(next_tile(Tile::Safe, Tile::Safe, Tile::Safe), Tile::Safe);
        assert_eq!(next_tile(Tile::Safe, Tile::Trap, Tile::Safe), Tile::Safe);
        assert_eq!(next_tile(Tile::Trap, Tile::Safe, Tile::Trap), Tile::Safe);
        assert_eq!(next_tile(Tile::Trap, Tile::Trap, Tile::Trap), Tile::Safe);
    }

    #[test]
    fn first_rule() {
        assert_eq!(next_tile(Tile::Trap, Tile::Trap, Tile::Safe), Tile::Trap);
    }

    #[test]
    fn second_rule() {
        assert_eq!(next_tile(Tile::Safe, Tile::Trap, Tile::Trap), Tile::Trap);
    }

    #[test]
    fn third_rule() {
        assert_eq!(next_tile(Tile::Trap, Tile::Safe, Tile::Safe), Tile::Trap);
    }

    #[test]
    fn fourth_rule() {
        assert_eq!(next_tile(Tile::Safe, Tile::Safe, Tile::Trap), Tile::Trap);
    }

    #[test]
    fn row_at_a_time() {
        assert_eq!(string_to_row("..^^.").next(), string_to_row(".^^^^"));
    }

}
<commit_msg>Refactor using froms<commit_after>use std::str::FromStr;
use std::error::Error;

pub fn puzzle(input: &str) -> u32 {
    0
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Tile {
    Safe,
    Trap,
}

pub fn next_tile(left: Tile, center: Tile, right: Tile) -> Tile {
    use Tile::*;
    match (left, center, right) {
        (Trap, Trap, Safe) => Trap,
        (Safe, Trap, Trap) => Trap,
        (Trap, Safe, Safe) => Trap,
        (Safe, Safe, Trap) => Trap,
        _ => Safe,
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct Row(Vec<Tile>);

impl Row {
    fn next(&self) -> Row {
        let mut x = vec![Tile::Safe];
        x.extend_from_slice(&self.0);
        x.push(Tile::Safe);

        Row(x.windows(3).map(|tiles| {
            next_tile(tiles[0], tiles[1], tiles[2])
        }).collect())
    }
}

impl Tile {
    fn from_char(c: char) -> Result<Tile, Box<Error>> {
        Ok(match c {
            '.' => Tile::Safe,
            '^' => Tile::Trap,
            _ => return Err(format!("unknown tile character {}", c).into()),
        })
    }
}

impl FromStr for Row {
    type Err = Box<Error>;

    fn from_str(s: &str) -> Result<Row, Self::Err> {
        s.chars().map(Tile::from_char).collect::<Result<_, _>>().map(Row)
    }
}

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

    #[test]
    fn safe() {
        assert_eq!(next_tile(Tile::Safe, Tile::Safe, Tile::Safe), Tile::Safe);
        assert_eq!(next_tile(Tile::Safe, Tile::Trap, Tile::Safe), Tile::Safe);
        assert_eq!(next_tile(Tile::Trap, Tile::Safe, Tile::Trap), Tile::Safe);
        assert_eq!(next_tile(Tile::Trap, Tile::Trap, Tile::Trap), Tile::Safe);
    }

    #[test]
    fn first_rule() {
        assert_eq!(next_tile(Tile::Trap, Tile::Trap, Tile::Safe), Tile::Trap);
    }

    #[test]
    fn second_rule() {
        assert_eq!(next_tile(Tile::Safe, Tile::Trap, Tile::Trap), Tile::Trap);
    }

    #[test]
    fn third_rule() {
        assert_eq!(next_tile(Tile::Trap, Tile::Safe, Tile::Safe), Tile::Trap);
    }

    #[test]
    fn fourth_rule() {
        assert_eq!(next_tile(Tile::Safe, Tile::Safe, Tile::Trap), Tile::Trap);
    }

    fn string_to_row(s: &str) -> Row {
        s.parse().expect("Couldn't create Row")
    }

    #[test]
    fn row_at_a_time() {
        assert_eq!(string_to_row("..^^.").next(), string_to_row(".^^^^"));
    }

}
<|endoftext|>