<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/. */

//! CSS handling for the computed value of
//! [`basic-shape`][basic-shape]s
//!
//! [basic-shape]: https://drafts.csswg.org/css-shapes/#typedef-basic-shape

use std::fmt;
use style_traits::ToCss;
use values::computed::LengthOrPercentage;
use values::generics::basic_shape::{BasicShape as GenericBasicShape, BorderRadius as GenericBorderRadius};
use values::generics::basic_shape::{Circle as GenericCircle, ClippingShape as GenericClippingShape};
use values::generics::basic_shape::{Ellipse as GenericEllipse, FloatAreaShape as GenericFloatAreaShape};
use values::generics::basic_shape::{InsetRect as GenericInsetRect, ShapeRadius as GenericShapeRadius};

/// A specified clipping shape.
pub type ClippingShape = GenericClippingShape<BasicShape>;

/// A specified float area shape.
pub type FloatAreaShape = GenericFloatAreaShape<BasicShape>;

/// A computed basic shape.
pub type BasicShape = GenericBasicShape<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;

/// The computed value of `inset()`
pub type InsetRect = GenericInsetRect<LengthOrPercentage>;

/// The computed value of `BorderRadius`
pub type BorderRadius = GenericBorderRadius<LengthOrPercentage>;

/// A computed circle.
pub type Circle = GenericCircle<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;

/// A computed ellipse.
pub type Ellipse = GenericEllipse<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;

/// The computed value of `ShapeRadius`
pub type ShapeRadius = GenericShapeRadius<LengthOrPercentage>;

impl ToCss for Circle {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        self.radius.to_css(dest)?;
        dest.write_str(" at ")?;
        self.position.to_css(dest)
    }
}

impl ToCss for Ellipse {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        dest.write_str("ellipse(")?;
        if (self.semiaxis_x, self.semiaxis_y) != Default::default() {
            self.semiaxis_x.to_css(dest)?;
            dest.write_str(" ")?;
            self.semiaxis_y.to_css(dest)?;
            dest.write_str(" ")?;
        }
        dest.write_str("at ")?;
        self.position.to_css(dest)?;
        dest.write_str(")")
    }
}
<commit_msg>Fix serialisation of computed circles<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/. */

//! CSS handling for the computed value of
//! [`basic-shape`][basic-shape]s
//!
//! [basic-shape]: https://drafts.csswg.org/css-shapes/#typedef-basic-shape

use std::fmt;
use style_traits::ToCss;
use values::computed::LengthOrPercentage;
use values::generics::basic_shape::{BasicShape as GenericBasicShape, BorderRadius as GenericBorderRadius};
use values::generics::basic_shape::{Circle as GenericCircle, ClippingShape as GenericClippingShape};
use values::generics::basic_shape::{Ellipse as GenericEllipse, FloatAreaShape as GenericFloatAreaShape};
use values::generics::basic_shape::{InsetRect as GenericInsetRect, ShapeRadius as GenericShapeRadius};

/// A specified clipping shape.
pub type ClippingShape = GenericClippingShape<BasicShape>;

/// A specified float area shape.
pub type FloatAreaShape = GenericFloatAreaShape<BasicShape>;

/// A computed basic shape.
pub type BasicShape = GenericBasicShape<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;

/// The computed value of `inset()`
pub type InsetRect = GenericInsetRect<LengthOrPercentage>;

/// The computed value of `BorderRadius`
pub type BorderRadius = GenericBorderRadius<LengthOrPercentage>;

/// A computed circle.
pub type Circle = GenericCircle<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;

/// A computed ellipse.
pub type Ellipse = GenericEllipse<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;

/// The computed value of `ShapeRadius`
pub type ShapeRadius = GenericShapeRadius<LengthOrPercentage>;

impl ToCss for Circle {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        dest.write_str("circle(")?;
        self.radius.to_css(dest)?;
        dest.write_str(" at ")?;
        self.position.to_css(dest)
    }
}

impl ToCss for Ellipse {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        dest.write_str("ellipse(")?;
        if (self.semiaxis_x, self.semiaxis_y) != Default::default() {
            self.semiaxis_x.to_css(dest)?;
            dest.write_str(" ")?;
            self.semiaxis_y.to_css(dest)?;
            dest.write_str(" ")?;
        }
        dest.write_str("at ")?;
        self.position.to_css(dest)?;
        dest.write_str(")")
    }
}
<|endoftext|>


<commit_before>use std::io::Read;

use crate::Solution;

#[derive(Default)]
pub struct Day17;

impl Solution for Day17 {
    fn part1(&mut self, _input: &mut dyn Read) -> String {
        todo!()
    }
}
<commit_msg>Implementation day 17 part 1.<commit_after>use std::collections::HashMap;
use std::collections::HashSet;
use std::io::Read;
use std::mem::swap;

use crate::common::Lines;
use crate::Solution;

type Space = HashSet<(i32, i32, i32)>;

fn read_input(input: &mut dyn Read) -> Space {
    let mut space = HashSet::new();

    for (y, line) in Lines::new(input).enumerate() {
        space.extend(line.chars().enumerate().filter_map(|(x, c)| {
            if c == '#' {
                Some((x as i32, y as i32, 0))
            } else {
                None
            }
        }))
    }

    space
}

fn advance(current: &Space, next: &mut Space) {
    let mut live_count = HashMap::new();

    for &(x, y, z) in current {
        for nx in (x - 1)..=(x + 1) {
            for ny in (y - 1)..=(y + 1) {
                for nz in (z - 1)..=(z + 1) {
                    if x != nx || y != ny || nz != z {
                        *live_count.entry((nx, ny, nz)).or_insert(0) += 1;
                    }
                }
            }
        }
    }

    next.clear();

    for (pos, neighbours) in live_count {
        if (neighbours == 2 && current.contains(&pos)) || neighbours == 3 {
            next.insert(pos);
        }
    }
}

#[allow(unused)]
fn print_state(space: &Space) {
    let mut xmin = i32::max_value();
    let mut xmax = i32::min_value();
    let mut ymin = xmin;
    let mut ymax = xmax;
    let mut zmin = xmin;
    let mut zmax = xmax;

    for &(x, y, z) in space {
        xmax = xmax.max(x);
        xmin = xmin.min(x);
        ymax = ymax.max(y);
        ymin = ymin.min(y);
        zmax = zmax.max(z);
        zmin = zmin.min(z);
    }

    for z in zmin..=zmax {
        println!("z={}", z);
        for y in ymin..=ymax {
            let line: String = (xmin..=xmax)
                .map(|x| if space.contains(&(x, y, z)) { '#' } else { '.' })
                .collect();

            println!("{}", line);
        }
        println!();
    }
}

#[derive(Default)]
pub struct Day17;

impl Solution for Day17 {
    fn part1(&mut self, input: &mut dyn Read) -> String {
        let mut space = read_input(input);
        let mut scratch_pad = Space::new();

        for _ in 0..6 {
            advance(&space, &mut scratch_pad);
            swap(&mut space, &mut scratch_pad);
        }

        space.len().to_string()
    }
}

#[cfg(test)]
mod tests {
    use crate::test_implementation;

    use super::*;

    const SAMPLE: &[u8] = include_bytes!("../samples/17.txt");

    #[test]
    fn sample_part1() {
        test_implementation!(Day17, 1, SAMPLE, 112);
    }
}
<|endoftext|>


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

//! All the rules required for a cryptocurrency to have reach consensus across
//! the whole network are complex and hard to completely isolate. Some can be
//! simple parameters (like block reward), others complex algorithms (like
//! Merkle sum trees or reorg rules). However, as long as they're simple
//! enough, consensus-relevant constants and short functions should be kept
//! here.

use std::cmp::{max, min};
use std::fmt;

use global;
use pow::Difficulty;

/// A grin is divisible to 10^9, following the SI prefixes
pub const GRIN_BASE: u64 = 1_000_000_000;
/// Milligrin, a thousand of a grin
pub const MILLI_GRIN: u64 = GRIN_BASE / 1_000;
/// Microgrin, a thousand of a milligrin
pub const MICRO_GRIN: u64 = MILLI_GRIN / 1_000;
/// Nanogrin, smallest unit, takes a billion to make a grin
pub const NANO_GRIN: u64 = 1;

/// The block subsidy amount, one grin per second on average
pub const REWARD: u64 = 60 * GRIN_BASE;

/// Actual block reward for a given total fee amount
pub fn reward(fee: u64) -> u64 {
	REWARD + fee
}

/// Block interval, in seconds, the network will tune its next_target for. Note
/// that we may reduce this value in the future as we get more data on mining
/// with Cuckoo Cycle, networks improve and block propagation is optimized
/// (adjusting the reward accordingly).
pub const BLOCK_TIME_SEC: u64 = 60;

/// Number of blocks before a coinbase matures and can be spent
/// set to nominal number of block in one day (1440 with 1-minute blocks)
pub const COINBASE_MATURITY: u64 = 24 * 60 * 60 / BLOCK_TIME_SEC;

/// Ratio the secondary proof of work should take over the primary, as a
/// function of block height (time). Starts at 90% losing a percent
/// approximately every week (10000 blocks). Represented as an integer
/// between 0 and 100.
pub fn secondary_pow_ratio(height: u64) -> u64 {
	90u64.saturating_sub(height / 10000)
}

/// Cuckoo-cycle proof size (cycle length)
pub const PROOFSIZE: usize = 42;

/// Default Cuckoo Cycle edge_bits, used for mining and validating.
pub const DEFAULT_MIN_EDGE_BITS: u8 = 30;

/// Secondary proof-of-work edge_bits, meant to be ASIC resistant.
pub const SECOND_POW_EDGE_BITS: u8 = 29;

/// Original reference edge_bits to compute difficulty factors for higher
/// Cuckoo graph sizes, changing this would hard fork
pub const BASE_EDGE_BITS: u8 = 24;

/// maximum scaling factor for secondary pow, enforced in diff retargetting
/// increasing scaling factor increases frequency of secondary blocks
/// ONLY IN TESTNET4 LIMITED TO ABOUT 8 TIMES THE NATURAL SCALE
pub const MAX_SECOND_POW_SCALE: u64 = 8 << 11;

/// Default number of blocks in the past when cross-block cut-through will start
/// happening. Needs to be long enough to not overlap with a long reorg.
/// Rational
/// behind the value is the longest bitcoin fork was about 30 blocks, so 5h. We
/// add an order of magnitude to be safe and round to 7x24h of blocks to make it
/// easier to reason about.
pub const CUT_THROUGH_HORIZON: u32 = 7 * 24 * 3600 / (BLOCK_TIME_SEC as u32);

/// Weight of an input when counted against the max block weight capacity
pub const BLOCK_INPUT_WEIGHT: usize = 1;

/// Weight of an output when counted against the max block weight capacity
pub const BLOCK_OUTPUT_WEIGHT: usize = 10;

/// Weight of a kernel when counted against the max block weight capacity
pub const BLOCK_KERNEL_WEIGHT: usize = 2;

/// Total maximum block weight. At current sizes, this means a maximum
/// theoretical size of:
/// * `(674 + 33 + 1) * 4_000 = 2_832_000` for a block with only outputs
/// * `(1 + 8 + 8 + 33 + 64) * 20_000 = 2_280_000` for a block with only kernels
/// * `(1 + 33) * 40_000 = 1_360_000` for a block with only inputs
///
/// Given that a block needs to have at least one kernel for the coinbase,
/// and one kernel for the transaction, practical maximum size is 2_831_440,
/// (ignoring the edge case of a miner producing a block with all coinbase
/// outputs and a single kernel).
///
/// A more "standard" block, filled with transactions of 2 inputs, 2 outputs
/// and one kernel, should be around 2_663_333 bytes.
pub const MAX_BLOCK_WEIGHT: usize = 40_000;

/// Fork every 250,000 blocks for first 2 years, simple number and just a
/// little less than 6 months.
pub const HARD_FORK_INTERVAL: u64 = 250_000;

/// Check whether the block version is valid at a given height, implements
/// 6 months interval scheduled hard forks for the first 2 years.
pub fn valid_header_version(height: u64, version: u16) -> bool {
	// uncomment below as we go from hard fork to hard fork
	if height < HARD_FORK_INTERVAL {
		version == 1
	/* } else if height < 2 * HARD_FORK_INTERVAL {
		version == 2
	} else if height < 3 * HARD_FORK_INTERVAL {
		version == 3
	} else if height < 4 * HARD_FORK_INTERVAL {
		version == 4
	} else if height >= 5 * HARD_FORK_INTERVAL {
		version > 4 */
	} else {
		false
	}
}

/// Time window in blocks to calculate block time median
pub const MEDIAN_TIME_WINDOW: u64 = 11;

/// Index at half the desired median
pub const MEDIAN_TIME_INDEX: u64 = MEDIAN_TIME_WINDOW / 2;

/// Number of blocks used to calculate difficulty adjustments
pub const DIFFICULTY_ADJUST_WINDOW: u64 = 60;

/// Average time span of the difficulty adjustment window
pub const BLOCK_TIME_WINDOW: u64 = DIFFICULTY_ADJUST_WINDOW * BLOCK_TIME_SEC;

/// Maximum size time window used for difficulty adjustments
pub const UPPER_TIME_BOUND: u64 = BLOCK_TIME_WINDOW * 2;

/// Minimum size time window used for difficulty adjustments
pub const LOWER_TIME_BOUND: u64 = BLOCK_TIME_WINDOW / 2;

/// Dampening factor to use for difficulty adjustment
pub const DAMP_FACTOR: u64 = 3;

/// The initial difficulty at launch. This should be over-estimated
/// and difficulty should come down at launch rather than up
/// Currently grossly over-estimated at 10% of current
/// ethereum GPUs (assuming 1GPU can solve a block at diff 1
/// in one block interval)
pub const INITIAL_DIFFICULTY: u64 = 1_000_000;

/// Consensus errors
#[derive(Clone, Debug, Eq, PartialEq, Fail)]
pub enum Error {
	/// Inputs/outputs/kernels must be sorted lexicographically.
	SortError,
}

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Sort Error")
	}
}

/// Minimal header information required for the Difficulty calculation to
/// take place
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HeaderInfo {
	/// Timestamp of the header, 1 when not used (returned info)
	pub timestamp: u64,
	/// Network difficulty or next difficulty to use
	pub difficulty: Difficulty,
	/// Network secondary PoW factor or factor to use
	pub secondary_scaling: u32,
	/// Whether the header is a secondary proof of work
	pub is_secondary: bool,
}

impl HeaderInfo {
	/// Default constructor
	pub fn new(
		timestamp: u64,
		difficulty: Difficulty,
		secondary_scaling: u32,
		is_secondary: bool,
	) -> HeaderInfo {
		HeaderInfo {
			timestamp,
			difficulty,
			secondary_scaling,
			is_secondary,
		}
	}

	/// Constructor from a timestamp and difficulty, setting a default secondary
	/// PoW factor
	pub fn from_ts_diff(timestamp: u64, difficulty: Difficulty) -> HeaderInfo {
		HeaderInfo {
			timestamp,
			difficulty,
			secondary_scaling: 1,
			is_secondary: false,
		}
	}

	/// Constructor from a difficulty and secondary factor, setting a default
	/// timestamp
	pub fn from_diff_scaling(difficulty: Difficulty, secondary_scaling: u32) -> HeaderInfo {
		HeaderInfo {
			timestamp: 1,
			difficulty,
			secondary_scaling,
			is_secondary: false,
		}
	}
}

/// Computes the proof-of-work difficulty that the next block should comply
/// with. Takes an iterator over past block headers information, from latest
/// (highest height) to oldest (lowest height).
///
/// The difficulty calculation is based on both Digishield and GravityWave
/// family of difficulty computation, coming to something very close to Zcash.
/// The reference difficulty is an average of the difficulty over a window of
/// DIFFICULTY_ADJUST_WINDOW blocks. The corresponding timespan is calculated
/// by using the difference between the median timestamps at the beginning
/// and the end of the window.
///
/// The secondary proof-of-work factor is calculated along the same lines, as
/// an adjustment on the deviation against the ideal value.
pub fn next_difficulty<T>(height: u64, cursor: T) -> HeaderInfo
where
	T: IntoIterator<Item = HeaderInfo>,
{
	// Create vector of difficulty data running from earliest
	// to latest, and pad with simulated pre-genesis data to allow earlier
	// adjustment if there isn't enough window data
	// length will be DIFFICULTY_ADJUST_WINDOW+MEDIAN_TIME_WINDOW
	let diff_data = global::difficulty_data_to_vector(cursor);

	// First, get the ratio of secondary PoW vs primary
	let sec_pow_scaling = secondary_pow_scaling(height, &diff_data);

	// Obtain the median window for the earlier time period
	// the first MEDIAN_TIME_WINDOW elements
	let earliest_ts = time_window_median(&diff_data, 0, MEDIAN_TIME_WINDOW as usize);

	// Obtain the median window for the latest time period
	// i.e. the last MEDIAN_TIME_WINDOW elements
	let latest_ts = time_window_median(
		&diff_data,
		DIFFICULTY_ADJUST_WINDOW as usize,
		MEDIAN_TIME_WINDOW as usize,
	);

	// median time delta
	let ts_delta = latest_ts - earliest_ts;

	// Get the difficulty sum of the last DIFFICULTY_ADJUST_WINDOW elements
	let diff_sum = diff_data
		.iter()
		.skip(MEDIAN_TIME_WINDOW as usize)
		.fold(0, |sum, d| sum + d.difficulty.to_num());

	// Apply dampening except when difficulty is near 1
	let ts_damp = if diff_sum < DAMP_FACTOR * DIFFICULTY_ADJUST_WINDOW {
		ts_delta
	} else {
		(1 * ts_delta + (DAMP_FACTOR - 1) * BLOCK_TIME_WINDOW) / DAMP_FACTOR
	};

	// Apply time bounds
	let adj_ts = if ts_damp < LOWER_TIME_BOUND {
		LOWER_TIME_BOUND
	} else if ts_damp > UPPER_TIME_BOUND {
		UPPER_TIME_BOUND
	} else {
		ts_damp
	};

	let difficulty = max(diff_sum * BLOCK_TIME_SEC / adj_ts, 1);

	HeaderInfo::from_diff_scaling(Difficulty::from_num(difficulty), sec_pow_scaling)
}

pub const MAX_SECONDARY_SCALING: u64 = (::std::u32::MAX / 70) as u64;

/// Factor by which the secondary proof of work difficulty will be adjusted
pub fn secondary_pow_scaling(height: u64, diff_data: &Vec<HeaderInfo>) -> u32 {
	// median of past scaling factors, scaling is 1 if none found
	let mut scalings = diff_data
		.iter()
		.map(|n| n.secondary_scaling)
		.collect::<Vec<_>>();
	if scalings.len() == 0 {
		return 1;
	}
	scalings.sort();
	let scaling_median = scalings[scalings.len() / 2] as u64;
	let secondary_count = max(diff_data.iter().filter(|n| n.is_secondary).count(), 1) as u64;

	// what's the ideal ratio at the current height
	let ratio = secondary_pow_ratio(height);

	// adjust the past median based on ideal ratio vs actual ratio
	let scaling = scaling_median * diff_data.len() as u64 * ratio / 100 / secondary_count as u64;

	// various bounds
	let bounded_scaling = if scaling < scaling_median / 4 || scaling == 0 {
		max(scaling_median / 4, 1)
	} else if scaling > MAX_SECONDARY_SCALING || scaling > scaling_median * 4 {
		min(MAX_SECONDARY_SCALING, scaling_median * 4)
	} else {
		scaling
	};
	bounded_scaling as u32
}

/// Median timestamp within the time window starting at `from` with the
/// provided `length`.
fn time_window_median(diff_data: &Vec<HeaderInfo>, from: usize, length: usize) -> u64 {
	let mut window_latest: Vec<u64> = diff_data
		.iter()
		.skip(from)
		.take(length)
		.map(|n| n.timestamp)
		.collect();
	// pick median
	window_latest.sort();
	window_latest[MEDIAN_TIME_INDEX as usize]
}

/// Consensus rule that collections of items are sorted lexicographically.
pub trait VerifySortOrder<T> {
	/// Verify a collection of items is sorted as required.
	fn verify_sort_order(&self) -> Result<(), Error>;
}
<commit_msg>Minor boundary adjustments for 2nd PoW scaling<commit_after>// Copyright 2018 The Grin Developers
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! All the rules required for a cryptocurrency to have reach consensus across
//! the whole network are complex and hard to completely isolate. Some can be
//! simple parameters (like block reward), others complex algorithms (like
//! Merkle sum trees or reorg rules). However, as long as they're simple
//! enough, consensus-relevant constants and short functions should be kept
//! here.

use std::cmp::{max, min};
use std::fmt;

use global;
use pow::Difficulty;

/// A grin is divisible to 10^9, following the SI prefixes
pub const GRIN_BASE: u64 = 1_000_000_000;
/// Milligrin, a thousand of a grin
pub const MILLI_GRIN: u64 = GRIN_BASE / 1_000;
/// Microgrin, a thousand of a milligrin
pub const MICRO_GRIN: u64 = MILLI_GRIN / 1_000;
/// Nanogrin, smallest unit, takes a billion to make a grin
pub const NANO_GRIN: u64 = 1;

/// The block subsidy amount, one grin per second on average
pub const REWARD: u64 = 60 * GRIN_BASE;

/// Actual block reward for a given total fee amount
pub fn reward(fee: u64) -> u64 {
	REWARD + fee
}

/// Block interval, in seconds, the network will tune its next_target for. Note
/// that we may reduce this value in the future as we get more data on mining
/// with Cuckoo Cycle, networks improve and block propagation is optimized
/// (adjusting the reward accordingly).
pub const BLOCK_TIME_SEC: u64 = 60;

/// Number of blocks before a coinbase matures and can be spent
/// set to nominal number of block in one day (1440 with 1-minute blocks)
pub const COINBASE_MATURITY: u64 = 24 * 60 * 60 / BLOCK_TIME_SEC;

/// Ratio the secondary proof of work should take over the primary, as a
/// function of block height (time). Starts at 90% losing a percent
/// approximately every week (10000 blocks). Represented as an integer
/// between 0 and 100.
pub fn secondary_pow_ratio(height: u64) -> u64 {
	90u64.saturating_sub(height / 10000)
}

/// Cuckoo-cycle proof size (cycle length)
pub const PROOFSIZE: usize = 42;

/// Default Cuckoo Cycle edge_bits, used for mining and validating.
pub const DEFAULT_MIN_EDGE_BITS: u8 = 30;

/// Secondary proof-of-work edge_bits, meant to be ASIC resistant.
pub const SECOND_POW_EDGE_BITS: u8 = 29;

/// Original reference edge_bits to compute difficulty factors for higher
/// Cuckoo graph sizes, changing this would hard fork
pub const BASE_EDGE_BITS: u8 = 24;

/// Maximum scaling factor for secondary pow, enforced in diff retargetting
/// increasing scaling factor increases frequency of secondary blocks
/// ONLY IN TESTNET4 LIMITED TO ABOUT 8 TIMES THE NATURAL SCALE
pub const MAX_SECONDARY_SCALING: u64 = 8 << 11;

/// Default number of blocks in the past when cross-block cut-through will start
/// happening. Needs to be long enough to not overlap with a long reorg.
/// Rational
/// behind the value is the longest bitcoin fork was about 30 blocks, so 5h. We
/// add an order of magnitude to be safe and round to 7x24h of blocks to make it
/// easier to reason about.
pub const CUT_THROUGH_HORIZON: u32 = 7 * 24 * 3600 / (BLOCK_TIME_SEC as u32);

/// Weight of an input when counted against the max block weight capacity
pub const BLOCK_INPUT_WEIGHT: usize = 1;

/// Weight of an output when counted against the max block weight capacity
pub const BLOCK_OUTPUT_WEIGHT: usize = 10;

/// Weight of a kernel when counted against the max block weight capacity
pub const BLOCK_KERNEL_WEIGHT: usize = 2;

/// Total maximum block weight. At current sizes, this means a maximum
/// theoretical size of:
/// * `(674 + 33 + 1) * 4_000 = 2_832_000` for a block with only outputs
/// * `(1 + 8 + 8 + 33 + 64) * 20_000 = 2_280_000` for a block with only kernels
/// * `(1 + 33) * 40_000 = 1_360_000` for a block with only inputs
///
/// Given that a block needs to have at least one kernel for the coinbase,
/// and one kernel for the transaction, practical maximum size is 2_831_440,
/// (ignoring the edge case of a miner producing a block with all coinbase
/// outputs and a single kernel).
///
/// A more "standard" block, filled with transactions of 2 inputs, 2 outputs
/// and one kernel, should be around 2_663_333 bytes.
pub const MAX_BLOCK_WEIGHT: usize = 40_000;

/// Fork every 250,000 blocks for first 2 years, simple number and just a
/// little less than 6 months.
pub const HARD_FORK_INTERVAL: u64 = 250_000;

/// Check whether the block version is valid at a given height, implements
/// 6 months interval scheduled hard forks for the first 2 years.
pub fn valid_header_version(height: u64, version: u16) -> bool {
	// uncomment below as we go from hard fork to hard fork
	if height < HARD_FORK_INTERVAL {
		version == 1
	/* } else if height < 2 * HARD_FORK_INTERVAL {
		version == 2
	} else if height < 3 * HARD_FORK_INTERVAL {
		version == 3
	} else if height < 4 * HARD_FORK_INTERVAL {
		version == 4
	} else if height >= 5 * HARD_FORK_INTERVAL {
		version > 4 */
	} else {
		false
	}
}

/// Time window in blocks to calculate block time median
pub const MEDIAN_TIME_WINDOW: u64 = 11;

/// Index at half the desired median
pub const MEDIAN_TIME_INDEX: u64 = MEDIAN_TIME_WINDOW / 2;

/// Number of blocks used to calculate difficulty adjustments
pub const DIFFICULTY_ADJUST_WINDOW: u64 = 60;

/// Average time span of the difficulty adjustment window
pub const BLOCK_TIME_WINDOW: u64 = DIFFICULTY_ADJUST_WINDOW * BLOCK_TIME_SEC;

/// Maximum size time window used for difficulty adjustments
pub const UPPER_TIME_BOUND: u64 = BLOCK_TIME_WINDOW * 2;

/// Minimum size time window used for difficulty adjustments
pub const LOWER_TIME_BOUND: u64 = BLOCK_TIME_WINDOW / 2;

/// Dampening factor to use for difficulty adjustment
pub const DAMP_FACTOR: u64 = 3;

/// The initial difficulty at launch. This should be over-estimated
/// and difficulty should come down at launch rather than up
/// Currently grossly over-estimated at 10% of current
/// ethereum GPUs (assuming 1GPU can solve a block at diff 1
/// in one block interval)
pub const INITIAL_DIFFICULTY: u64 = 1_000_000;

/// Consensus errors
#[derive(Clone, Debug, Eq, PartialEq, Fail)]
pub enum Error {
	/// Inputs/outputs/kernels must be sorted lexicographically.
	SortError,
}

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Sort Error")
	}
}

/// Minimal header information required for the Difficulty calculation to
/// take place
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HeaderInfo {
	/// Timestamp of the header, 1 when not used (returned info)
	pub timestamp: u64,
	/// Network difficulty or next difficulty to use
	pub difficulty: Difficulty,
	/// Network secondary PoW factor or factor to use
	pub secondary_scaling: u32,
	/// Whether the header is a secondary proof of work
	pub is_secondary: bool,
}

impl HeaderInfo {
	/// Default constructor
	pub fn new(
		timestamp: u64,
		difficulty: Difficulty,
		secondary_scaling: u32,
		is_secondary: bool,
	) -> HeaderInfo {
		HeaderInfo {
			timestamp,
			difficulty,
			secondary_scaling,
			is_secondary,
		}
	}

	/// Constructor from a timestamp and difficulty, setting a default secondary
	/// PoW factor
	pub fn from_ts_diff(timestamp: u64, difficulty: Difficulty) -> HeaderInfo {
		HeaderInfo {
			timestamp,
			difficulty,
			secondary_scaling: 1,
			is_secondary: false,
		}
	}

	/// Constructor from a difficulty and secondary factor, setting a default
	/// timestamp
	pub fn from_diff_scaling(difficulty: Difficulty, secondary_scaling: u32) -> HeaderInfo {
		HeaderInfo {
			timestamp: 1,
			difficulty,
			secondary_scaling,
			is_secondary: false,
		}
	}
}

/// Computes the proof-of-work difficulty that the next block should comply
/// with. Takes an iterator over past block headers information, from latest
/// (highest height) to oldest (lowest height).
///
/// The difficulty calculation is based on both Digishield and GravityWave
/// family of difficulty computation, coming to something very close to Zcash.
/// The reference difficulty is an average of the difficulty over a window of
/// DIFFICULTY_ADJUST_WINDOW blocks. The corresponding timespan is calculated
/// by using the difference between the median timestamps at the beginning
/// and the end of the window.
///
/// The secondary proof-of-work factor is calculated along the same lines, as
/// an adjustment on the deviation against the ideal value.
pub fn next_difficulty<T>(height: u64, cursor: T) -> HeaderInfo
where
	T: IntoIterator<Item = HeaderInfo>,
{
	// Create vector of difficulty data running from earliest
	// to latest, and pad with simulated pre-genesis data to allow earlier
	// adjustment if there isn't enough window data
	// length will be DIFFICULTY_ADJUST_WINDOW+MEDIAN_TIME_WINDOW
	let diff_data = global::difficulty_data_to_vector(cursor);

	// First, get the ratio of secondary PoW vs primary
	let sec_pow_scaling = secondary_pow_scaling(height, &diff_data);

	// Obtain the median window for the earlier time period
	// the first MEDIAN_TIME_WINDOW elements
	let earliest_ts = time_window_median(&diff_data, 0, MEDIAN_TIME_WINDOW as usize);

	// Obtain the median window for the latest time period
	// i.e. the last MEDIAN_TIME_WINDOW elements
	let latest_ts = time_window_median(
		&diff_data,
		DIFFICULTY_ADJUST_WINDOW as usize,
		MEDIAN_TIME_WINDOW as usize,
	);

	// median time delta
	let ts_delta = latest_ts - earliest_ts;

	// Get the difficulty sum of the last DIFFICULTY_ADJUST_WINDOW elements
	let diff_sum = diff_data
		.iter()
		.skip(MEDIAN_TIME_WINDOW as usize)
		.fold(0, |sum, d| sum + d.difficulty.to_num());

	// Apply dampening except when difficulty is near 1
	let ts_damp = if diff_sum < DAMP_FACTOR * DIFFICULTY_ADJUST_WINDOW {
		ts_delta
	} else {
		(1 * ts_delta + (DAMP_FACTOR - 1) * BLOCK_TIME_WINDOW) / DAMP_FACTOR
	};

	// Apply time bounds
	let adj_ts = if ts_damp < LOWER_TIME_BOUND {
		LOWER_TIME_BOUND
	} else if ts_damp > UPPER_TIME_BOUND {
		UPPER_TIME_BOUND
	} else {
		ts_damp
	};

	let difficulty = max(diff_sum * BLOCK_TIME_SEC / adj_ts, 1);

	HeaderInfo::from_diff_scaling(Difficulty::from_num(difficulty), sec_pow_scaling)
}

/// Factor by which the secondary proof of work difficulty will be adjusted
pub fn secondary_pow_scaling(height: u64, diff_data: &Vec<HeaderInfo>) -> u32 {
	// median of past scaling factors, scaling is 1 if none found
	let mut scalings = diff_data
		.iter()
		.map(|n| n.secondary_scaling)
		.collect::<Vec<_>>();
	if scalings.len() == 0 {
		return 1;
	}
	scalings.sort();
	let scaling_median = scalings[scalings.len() / 2] as u64;
	let secondary_count = max(diff_data.iter().filter(|n| n.is_secondary).count(), 1) as u64;

	// what's the ideal ratio at the current height
	let ratio = secondary_pow_ratio(height);

	// adjust the past median based on ideal ratio vs actual ratio
	let scaling = scaling_median * diff_data.len() as u64 * ratio / 100 / secondary_count as u64;

	// various bounds
	let bounded_scaling = if scaling < scaling_median / 2 || scaling == 0 {
		max(scaling_median / 2, 1)
	} else if scaling > MAX_SECONDARY_SCALING || scaling > scaling_median * 2 {
		min(MAX_SECONDARY_SCALING, scaling_median * 2)
	} else {
		scaling
	};
	bounded_scaling as u32
}

/// Median timestamp within the time window starting at `from` with the
/// provided `length`.
fn time_window_median(diff_data: &Vec<HeaderInfo>, from: usize, length: usize) -> u64 {
	let mut window_latest: Vec<u64> = diff_data
		.iter()
		.skip(from)
		.take(length)
		.map(|n| n.timestamp)
		.collect();
	// pick median
	window_latest.sort();
	window_latest[MEDIAN_TIME_INDEX as usize]
}

/// Consensus rule that collections of items are sorted lexicographically.
pub trait VerifySortOrder<T> {
	/// Verify a collection of items is sorted as required.
	fn verify_sort_order(&self) -> Result<(), Error>;
}
<|endoftext|>


<commit_before>// This should fail even without validation
// compile-flags: -Zmiri-disable-validation

static mut LEAK: usize = 0;

fn fill(v: &mut i32) {
    unsafe { LEAK = v as *mut _ as usize; }
}

fn evil() {
    let v = unsafe { &mut *(LEAK as *mut i32) }; //~ ERROR dangling pointer was dereferenced
    let _x = *v;
}

fn main() {
    let _y;
    {
        let mut x = 0i32;
        fill(&mut x);
        _y = x;
    }
    evil();
}
<commit_msg>remove dead code<commit_after>// This should fail even without validation
// compile-flags: -Zmiri-disable-validation

static mut LEAK: usize = 0;

fn fill(v: &mut i32) {
    unsafe { LEAK = v as *mut _ as usize; }
}

fn evil() {
    unsafe { &mut *(LEAK as *mut i32) }; //~ ERROR dangling pointer was dereferenced
}

fn main() {
    let _y;
    {
        let mut x = 0i32;
        fill(&mut x);
        _y = x;
    }
    evil();
}
<|endoftext|>


<commit_before>extern mod core_foundation;
extern mod core_graphics;

use libc::c_uint;

use cf = core_foundation;
use cf::string::UniChar;
use cf::base::CFIndex;

use cg = core_graphics;
use cg::base::{
    CGAffineTransform,
    CGFloat,
}
use cg::font::{
    CGGlyph,
    CGFontRef,
}
use cg::geometry::{
    CGRect,
    CGSize,
}

pub type CTFontRef = *u8;
pub type CTFontOrientation = u32;
pub type CTFontDescriptorRef = *u8;

pub const kCTFontDefaultOrientation: CTFontOrientation = 0;
pub const kCTFontHorizontalOrientation: CTFontOrientation = 1;
pub const kCTFontVerticalOrientation: CTFontOrientation = 2;

#[nolink]
#[link_args = "-framework ApplicationServices"]
extern {
    pub fn CTFontCreateWithGraphicsFont(graphicsFont: CGFontRef, size: CGFloat, matrix: *CGAffineTransform, attributes: CTFontDescriptorRef) -> CTFontRef;
    pub fn CTFontGetGlyphsForCharacters(font: CTFontRef, characters: *UniChar, glyphs: *CGGlyph, count: CFIndex) -> bool;
    pub fn CTFontGetAdvancesForGlyphs(font: CTFontRef, orientation: CTFontOrientation, glyphs: *CGGlyph, advances: *CGSize, count: CFIndex) -> libc::c_double;

    pub fn CTFontGetSize(font: CTFontRef) -> CGFloat;

    /* metrics API */
    pub fn CTFontGetAscent(font: CTFontRef) -> CGFloat;
    pub fn CTFontGetDescent(font: CTFontRef) -> CGFloat;
    pub fn CTFontGetLeading(font: CTFontRef) -> CGFloat;
    pub fn CTFontGetUnitsPerEm(font: CTFontRef) -> libc::c_uint;
    pub fn CTFontGetUnderlinePosition(font: CTFontRef) -> CGFloat;
    pub fn CTFontGetUnderlineThickness(font: CTFontRef) -> CGFloat;
    pub fn CTFontGetXHeight(font: CTFontRef) -> CGFloat;
    pub fn CTFontGetBoundingBox(font: CTFontRef) -> CGRect;
}
<commit_msg>Fix compilation errors.<commit_after>extern mod core_foundation;
extern mod core_graphics;

use libc::c_uint;

use cf = core_foundation;
use cf::string::UniChar;
use cf::base::CFIndex;

use cg = core_graphics;
use cg::base::{
    CGAffineTransform,
    CGFloat,
};
use cg::font::{
    CGGlyph,
    CGFontRef,
};
use cg::geometry::{
    CGRect,
    CGSize,
};

pub type CTFontRef = *u8;
pub type CTFontOrientation = u32;
pub type CTFontDescriptorRef = *u8;

pub const kCTFontDefaultOrientation: CTFontOrientation = 0;
pub const kCTFontHorizontalOrientation: CTFontOrientation = 1;
pub const kCTFontVerticalOrientation: CTFontOrientation = 2;

#[nolink]
#[link_args = "-framework ApplicationServices"]
extern {
    pub fn CTFontCreateWithGraphicsFont(graphicsFont: CGFontRef, size: CGFloat, matrix: *CGAffineTransform, attributes: CTFontDescriptorRef) -> CTFontRef;
    pub fn CTFontGetGlyphsForCharacters(font: CTFontRef, characters: *UniChar, glyphs: *CGGlyph, count: CFIndex) -> bool;
    pub fn CTFontGetAdvancesForGlyphs(font: CTFontRef, orientation: CTFontOrientation, glyphs: *CGGlyph, advances: *CGSize, count: CFIndex) -> libc::c_double;

    pub fn CTFontGetSize(font: CTFontRef) -> CGFloat;

    /* metrics API */
    pub fn CTFontGetAscent(font: CTFontRef) -> CGFloat;
    pub fn CTFontGetDescent(font: CTFontRef) -> CGFloat;
    pub fn CTFontGetLeading(font: CTFontRef) -> CGFloat;
    pub fn CTFontGetUnitsPerEm(font: CTFontRef) -> libc::c_uint;
    pub fn CTFontGetUnderlinePosition(font: CTFontRef) -> CGFloat;
    pub fn CTFontGetUnderlineThickness(font: CTFontRef) -> CGFloat;
    pub fn CTFontGetXHeight(font: CTFontRef) -> CGFloat;
    pub fn CTFontGetBoundingBox(font: CTFontRef) -> CGRect;
}
<|endoftext|>


<commit_before>

use super::libbzip::BzQuality;
use super::libflate::GzQuality;

use super::libbrotli::{
  Encode as BrEn,
  Builder as BrBuilder,
  Mode as BrMode
};

use super::libzstd::Encode as DzEn;

use super::liblz4::{
  Encode as LzEn,
  Builder as LzBuilder,
  BSize as Lz4BSize,
  BMode as Lz4BMode,
  Checksum as Lz4Checksum
};

use std::path::Path;
use std::io::{
  self,
  Read,
  Seek,
  SeekFrom,
};
use std::fs::OpenOptions;
use std::default::Default;

/*
 * Magic Numbers and Extentions
 *
 * This file attempts to codify and enumerate _all_
 * the various compression algorithms and their signatures
 *
 *  Most of the list is from:https://en.wikipedia.org/wiki/List_of_file_signatures
 *
 * Some are just from reading RFC/Standards:
 * Snappy: https://github.com/google/snappy/blob/master/framing_format.txt
 * XZ: http://tukaani.org/xz/xz-file-format.txt
 * Brotli: https://github.com/madler/brotli/blob/501e6a9d03bcc15f0bc8015f4f36054c30f699ca/br-format-v3.txt
 * Zstd: https://github.com/facebook/zstd
 * Zstd (cont.): https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md
 */

/// Describes the ratio/speed trade off
///
/// More or less these are fixed constants I've eyeballed for
/// the _new_ methods, while for Bzip2/Gzip they're effectively
/// standard values.
///
/// _Any_ input for `Format::Snappy` is ignored as it only has
/// 1 mode of operation.
///
/// #Brotli
///
///* `Quality::FastLow`: 2
///* `Quality::Default`: 5
///* `Quality::SlowHigh`: 8
///
/// #Zstd
///
///* `Quality::FastLow`: 1
///* `Quality::Default`: 10
///* `Quality::SlowHigh`: 21
///
/// #Lz4
///
///User input is ignored, default value is always used.
///
/// #Xz
///
///* `Quality::FastLow`: 0
///* `Quality::Default`: 3
///* `Quality::SlowHigh`: 7
#[derive(Clone,Debug)]
pub enum Quality {
  Default,
  FastLow,
  SlowHigh,

  /// Level ranges from 1 to 21
  ZstdSpecial(i32),

  /// Level ranges from 0 to 11
  BrotliSpecial(BrMode,u32,u32,u32),

  /// level ranges from 0 to 16
  Lz4Special(Lz4BSize,Lz4BMode,Lz4Checksum,u32)
}
impl Quality {

  /// Creates a closure which contructs the LZ4 encoder with
  /// the compression information in the enum
  pub fn into_lz4<W: io::Write>(self) -> Box<Fn(W) -> io::Result<LzEn<W>>> {
    match self {
      Quality::FastLow => Box::new(move |w| {
        let mut b = LzBuilder::new();
        b.level(1);
        b.checksum(Lz4Checksum::NoChecksum);
        b.build(w)
      }),
      Quality::SlowHigh => Box::new(move |w| {
        let mut b = LzBuilder::new();
        b.level(16);
        b.block_size(Lz4BSize::Max4MB);
        b.block_mode(Lz4BMode::Linked);
        b.checksum(Lz4Checksum::ChecksumEnabled);
        b.build(w)
      }),
      Quality::Lz4Special(bsize, bmode, csu, lvl) => Box::new(move |w| {
        let mut b = LzBuilder::new();
        b.level(lvl.clone());
        b.block_size(bsize);
        b.block_mode(bmode);
        b.checksum(csu);
        b.build(w)
      }),
      _ => Box::new(move |w| {
        LzBuilder::new().build(w)
      })
    }
  }

 /// Creates a closure which constructs the ZSTD encoder with
  /// the compression information in the enum
  pub fn into_zstd<W: io::Write>(self) -> Box<Fn(W) -> io::Result<DzEn<W>>> {
    match self {
      Quality::FastLow => Box::new(move |w| {
        DzEn::new(w,1)
      }),
      Quality::SlowHigh => Box::new(move |w| {
        DzEn::new(w,21)
      }),
      Quality::ZstdSpecial(qual) => Box::new(move |w| {
        DzEn::new(w,qual.clone())
      }),
      _ => Box::new(move |w| {
        DzEn::new(w,10)
      }),
    }
  }

  /// Creates a closure which constructs the Brotli encoder with
  /// the compression information in the enum
  pub fn into_brotli<W: io::Write>(self) -> Box<Fn(W) -> BrEn<W>> {
    match self {
      Quality::BrotliSpecial(mode, qual, win, block) => Box::new(move |w| {
        let brotli_mode = mode.clone();
        let quality = qual.clone();
        let window = win.clone();
        let block = block.clone();
        let mut c = BrBuilder::new();
        c.mode(brotli_mode);
        c.quality(quality);
        c.lgwin(window);
        c.lgblock(block);
        BrEn::from_params(w, &c)
      }),
      Quality::FastLow => Box::new(move |w| {
        BrEn::new(w, 2)
      }),
      Quality::SlowHigh => Box::new(move |w| {
        let mut c = BrBuilder::new();
        c.mode(BrMode::Text);
        c.quality(11);
        c.lgwin(24);
        c.lgblock(24);
        BrEn::from_params(w, &c)
      }),
      _ => Box::new(move |w| {
        BrEn::new(w, 5)
      })
    }
  }

  pub fn into_xz(self) -> u32 {
    match self {
      Quality::FastLow => 3,
      Quality::SlowHigh => 7,
      _ => 0
    }
  }

  pub fn into_bz(self) -> BzQuality {
    match self {
      Quality::FastLow => BzQuality::Fastest,
      Quality::SlowHigh => BzQuality::Best,
      _ => BzQuality::Default,

    }
  }

  pub fn into_gz(self) -> GzQuality {
    match self {
      Quality::FastLow => GzQuality::Fast,
      Quality::SlowHigh => GzQuality::Best,
      _ => GzQuality::Default,
    }
  }
}
impl Default for Quality {

  /// This returns `Quality::Default` which may suprrise you
  fn default() -> Self {
    Quality::Default
  }
}

/// Describes the compression algortim we're working with.
///
/// This can be detected, or set by the user depending on if
/// they're compressing or decompressing.
#[derive(Clone,Debug)]
pub enum Format {
  LZW(Quality),
	LZH(Quality),
	Gzip(Quality),
	Zip7(Quality),
  Bzip2(Quality),
  Xz(Quality),
  Brotli(Quality),
  Lz4(Quality),
  Snappy(Quality),
  Zstd(Quality),
  Tar(Quality),
}
impl Format {

	/// Returns the _suggested_ or _common_ extension for a file format
	/// this isn't a _hard and fast_ rule, some are identical.
	pub fn get_extension(&self) -> &'static str {
		match self {
			&Format::LZW(_) => "z",
			&Format::LZH(_) => "z",
			&Format::Zip7(_) => "7z",
			&Format::Gzip(_) => "gz",
			&Format::Bzip2(_) => "bz2",
			&Format::Xz(_) => "xz",
			&Format::Brotli(_) => "br",
			&Format::Lz4(_) => "lz4",
			&Format::Snappy(_) => "sz",
			&Format::Zstd(_) => "zst",
			&Format::Tar(_) => "tar"
		}
	}

  /// Try to find out the format of a file
  ///
  /// This will attempt to open the file at path and read the first 16bytes
  /// matching that against a known magic number.
  ///
  /// If the file's type is unknown this method will return `Err(InvalidInput)`
  pub fn from_path<P: AsRef<Path>>(p: P) -> io::Result<Format> {
    let mut f = OpenOptions::new().read(true).write(false).create(false).open(p)?;
    let mut v = Vec::with_capacity(16);
    unsafe{ v.set_len(10) };
    f.read_exact(v.as_mut_slice())?;
    let _ = f;
    match what_format(v.as_slice()) {
      Option::Some(f) => Ok(f),
      Option::None => Err(io::Error::new(io::ErrorKind::InvalidInput, "Unsupported file type"))
    }
  }

  /// A slightly more efficient way to find a file's type.
  ///
  /// This method will seek to the start, read 16 bytes, then
  /// seek back to the start. The goal of this is to avoid multiple open/close cycles
  ///
  /// If the file's type is unknown this method will return `Err(InvalidInput)`
  pub fn from_reader<R:Read+Seek>(r: &mut R) -> io::Result<Format> {
    let _ = r.seek(SeekFrom::Start(0))?;
    let mut v = Vec::with_capacity(16);
    unsafe{ v.set_len(16) };
    r.read_exact(v.as_mut_slice())?;
    let _ = r.seek(SeekFrom::Start(0))?;
    match what_format(v.as_slice()) {
      Option::Some(f) => Ok(f),
      Option::None => Err(io::Error::new(io::ErrorKind::InvalidInput, "Unsupported file type"))
    }
  }
}

/*
 * LOOK I WROTE A NICE PARSER TO DO THIS AND IT BROKE
 * BETWEEN STABLE-MSVC AND STABLE-GNU
 * SO YEAH IT IS RECURSIVE DECENT FUCK OFF
 */
fn what_format(x: &[u8]) -> Option<Format> {
  match &x[0..2] {
    b"\x1F\x9D" => return Some(Format::LZW(Quality::Default)),
    b"\x1F\xA0" => return Some(Format::LZH(Quality::Default)),
    b"\x1F\x8B" => return Some(Format::Gzip(Quality::Default)),
    b"\x30\x30" |
    b"\x20\x00" => return Some(Format::Tar(Quality::Default)),
    _ => { }
  };
  match &x[0..3] {
    b"\x37\x7A\xBC" |
    b"\xAF\x27\x1C" => return Some(Format::Xz(Quality::Default)),
    b"\x42\x5A\x68" => return Some(Format::Bzip2(Quality::Default)),
    b"\x75\x73\x74" |
    b"\x61\x72\x20" |
    b"\x61\x72\x00" => return Some(Format::Tar(Quality::Default)),
    _ => { }
  };
  match &x[0..4] {
    b"\x81\xCF\xB2\xCE" |
    b"\xCE\xB2\xCF\x81" => return Some(Format::Brotli(Quality::Default)),
    b"\x18\x4D\x22\x04" |
    b"\x04\x22\x4D\x18" => return Some(Format::Lz4(Quality::Default)),
    b"\x27\xB5\x2F\xFD" |
    b"\xFD\x2F\xB5\x27" |
    b"\x28\xB5\x2F\xFD" |
    b"\xFD\x2F\xB5\x28" => return Some(Format::Zstd(Quality::Default)),
    _ => { }
  };
  match &x[0..6] {
    b"\xFD\x37\x7A\x58\x5A\x00" => return Some(Format::Xz(Quality::Default)),
    _ => { }
  };
  match &x[0..9] {
    b"\xFF\x06\x00\x73\x4E\x61\x50\x70\x59" => return Some(Format::Snappy(Quality::Default)),
    _ => { }
  };
  None
}

<commit_msg>Update zstd detection and error message<commit_after>

use super::libbzip::BzQuality;
use super::libflate::GzQuality;

use super::libbrotli::{
  Encode as BrEn,
  Builder as BrBuilder,
  Mode as BrMode
};

use super::libzstd::Encode as DzEn;

use super::liblz4::{
  Encode as LzEn,
  Builder as LzBuilder,
  BSize as Lz4BSize,
  BMode as Lz4BMode,
  Checksum as Lz4Checksum
};

use std::path::Path;
use std::io::{
  self,
  Read,
  Seek,
  SeekFrom,
};
use std::fs::OpenOptions;
use std::default::Default;

/*
 * Magic Numbers and Extentions
 *
 * This file attempts to codify and enumerate _all_
 * the various compression algorithms and their signatures
 *
 *  Most of the list is from:https://en.wikipedia.org/wiki/List_of_file_signatures
 *
 * Some are just from reading RFC/Standards:
 * Snappy: https://github.com/google/snappy/blob/master/framing_format.txt
 * XZ: http://tukaani.org/xz/xz-file-format.txt
 * Brotli: https://github.com/madler/brotli/blob/501e6a9d03bcc15f0bc8015f4f36054c30f699ca/br-format-v3.txt
 * Zstd: https://github.com/facebook/zstd
 * Zstd (cont.): https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md
 */

/// Describes the ratio/speed trade off
///
/// More or less these are fixed constants I've eyeballed for
/// the _new_ methods, while for Bzip2/Gzip they're effectively
/// standard values.
///
/// _Any_ input for `Format::Snappy` is ignored as it only has
/// 1 mode of operation.
///
/// #Brotli
///
///* `Quality::FastLow`: 2
///* `Quality::Default`: 5
///* `Quality::SlowHigh`: 8
///
/// #Zstd
///
///* `Quality::FastLow`: 1
///* `Quality::Default`: 10
///* `Quality::SlowHigh`: 21
///
/// #Lz4
///
///User input is ignored, default value is always used.
///
/// #Xz
///
///* `Quality::FastLow`: 0
///* `Quality::Default`: 3
///* `Quality::SlowHigh`: 7
#[derive(Clone,Debug)]
pub enum Quality {
  Default,
  FastLow,
  SlowHigh,

  /// Level ranges from 1 to 21
  ZstdSpecial(i32),

  /// Level ranges from 0 to 11
  BrotliSpecial(BrMode,u32,u32,u32),

  /// level ranges from 0 to 16
  Lz4Special(Lz4BSize,Lz4BMode,Lz4Checksum,u32)
}
impl Quality {

  /// Creates a closure which contructs the LZ4 encoder with
  /// the compression information in the enum
  pub fn into_lz4<W: io::Write>(self) -> Box<Fn(W) -> io::Result<LzEn<W>>> {
    match self {
      Quality::FastLow => Box::new(move |w| {
        let mut b = LzBuilder::new();
        b.level(1);
        b.checksum(Lz4Checksum::NoChecksum);
        b.build(w)
      }),
      Quality::SlowHigh => Box::new(move |w| {
        let mut b = LzBuilder::new();
        b.level(16);
        b.block_size(Lz4BSize::Max4MB);
        b.block_mode(Lz4BMode::Linked);
        b.checksum(Lz4Checksum::ChecksumEnabled);
        b.build(w)
      }),
      Quality::Lz4Special(bsize, bmode, csu, lvl) => Box::new(move |w| {
        let mut b = LzBuilder::new();
        b.level(lvl.clone());
        b.block_size(bsize);
        b.block_mode(bmode);
        b.checksum(csu);
        b.build(w)
      }),
      _ => Box::new(move |w| {
        LzBuilder::new().build(w)
      })
    }
  }

 /// Creates a closure which constructs the ZSTD encoder with
  /// the compression information in the enum
  pub fn into_zstd<W: io::Write>(self) -> Box<Fn(W) -> io::Result<DzEn<W>>> {
    match self {
      Quality::FastLow => Box::new(move |w| {
        DzEn::new(w,1)
      }),
      Quality::SlowHigh => Box::new(move |w| {
        DzEn::new(w,21)
      }),
      Quality::ZstdSpecial(qual) => Box::new(move |w| {
        DzEn::new(w,qual.clone())
      }),
      _ => Box::new(move |w| {
        DzEn::new(w,10)
      }),
    }
  }

  /// Creates a closure which constructs the Brotli encoder with
  /// the compression information in the enum
  pub fn into_brotli<W: io::Write>(self) -> Box<Fn(W) -> BrEn<W>> {
    match self {
      Quality::BrotliSpecial(mode, qual, win, block) => Box::new(move |w| {
        let brotli_mode = mode.clone();
        let quality = qual.clone();
        let window = win.clone();
        let block = block.clone();
        let mut c = BrBuilder::new();
        c.mode(brotli_mode);
        c.quality(quality);
        c.lgwin(window);
        c.lgblock(block);
        BrEn::from_params(w, &c)
      }),
      Quality::FastLow => Box::new(move |w| {
        BrEn::new(w, 2)
      }),
      Quality::SlowHigh => Box::new(move |w| {
        let mut c = BrBuilder::new();
        c.mode(BrMode::Text);
        c.quality(11);
        c.lgwin(24);
        c.lgblock(24);
        BrEn::from_params(w, &c)
      }),
      _ => Box::new(move |w| {
        BrEn::new(w, 5)
      })
    }
  }

  pub fn into_xz(self) -> u32 {
    match self {
      Quality::FastLow => 3,
      Quality::SlowHigh => 7,
      _ => 0
    }
  }

  pub fn into_bz(self) -> BzQuality {
    match self {
      Quality::FastLow => BzQuality::Fastest,
      Quality::SlowHigh => BzQuality::Best,
      _ => BzQuality::Default,

    }
  }

  pub fn into_gz(self) -> GzQuality {
    match self {
      Quality::FastLow => GzQuality::Fast,
      Quality::SlowHigh => GzQuality::Best,
      _ => GzQuality::Default,
    }
  }
}
impl Default for Quality {

  /// This returns `Quality::Default` which may suprrise you
  fn default() -> Self {
    Quality::Default
  }
}

/// Describes the compression algortim we're working with.
///
/// This can be detected, or set by the user depending on if
/// they're compressing or decompressing.
#[derive(Clone,Debug)]
pub enum Format {
  LZW(Quality),
	LZH(Quality),
	Gzip(Quality),
	Zip7(Quality),
  Bzip2(Quality),
  Xz(Quality),
  Brotli(Quality),
  Lz4(Quality),
  Snappy(Quality),
  Zstd(Quality),
  Tar(Quality),
}
impl Format {

	/// Returns the _suggested_ or _common_ extension for a file format
	/// this isn't a _hard and fast_ rule, some are identical.
	pub fn get_extension(&self) -> &'static str {
		match self {
			&Format::LZW(_) => "z",
			&Format::LZH(_) => "z",
			&Format::Zip7(_) => "7z",
			&Format::Gzip(_) => "gz",
			&Format::Bzip2(_) => "bz2",
			&Format::Xz(_) => "xz",
			&Format::Brotli(_) => "br",
			&Format::Lz4(_) => "lz4",
			&Format::Snappy(_) => "sz",
			&Format::Zstd(_) => "zst",
			&Format::Tar(_) => "tar"
		}
	}

  /// Try to find out the format of a file
  ///
  /// This will attempt to open the file at path and read the first 16bytes
  /// matching that against a known magic number.
  ///
  /// If the file's type is unknown this method will return `Err(InvalidInput)`
  pub fn from_path<P: AsRef<Path>>(p: P) -> io::Result<Format> {
    let mut f = OpenOptions::new().read(true).write(false).create(false).open(p)?;
    let mut v = Vec::with_capacity(16);
    unsafe{ v.set_len(10) };
    f.read_exact(v.as_mut_slice())?;
    let _ = f;
    match what_format(v.as_slice()) {
      Option::Some(f) => Ok(f),
      Option::None => Err(io::Error::new(io::ErrorKind::InvalidInput, "Unsupported file type"))
    }
  }

  /// A slightly more efficient way to find a file's type.
  ///
  /// This method will seek to the start, read 16 bytes, then
  /// seek back to the start. The goal of this is to avoid multiple open/close cycles
  ///
  /// If the file's type is unknown this method will return `Err(InvalidInput)`
  pub fn from_reader<R:Read+Seek>(r: &mut R) -> io::Result<Format> {
    let _ = r.seek(SeekFrom::Start(0))?;
    let mut v = Vec::with_capacity(16);
    unsafe{ v.set_len(16) };
    let input = r.read(v.as_mut_slice())?;
    let _ = r.seek(SeekFrom::Start(0))?;
    unsafe { v.set_len(input) }
    match what_format(v.as_slice()) {
      Option::Some(f) => Ok(f),
      Option::None => {
        let kind = io::ErrorKind::InvalidInput;
        let msg = format!("Could not identify magic number {:?}", v.as_slice());
        Err(io::Error::new(kind, msg))
      }
    }
  }
}

/*
 * LOOK I WROTE A NICE PARSER TO DO THIS AND IT BROKE
 * BETWEEN STABLE-MSVC AND STABLE-GNU
 * SO YEAH IT IS RECURSIVE DECENT
 */
fn what_format(x: &[u8]) -> Option<Format> {
  match &x[0..2] {
    b"\x1F\x9D" => return Some(Format::LZW(Quality::Default)),
    b"\x1F\xA0" => return Some(Format::LZH(Quality::Default)),
    b"\x1F\x8B" => return Some(Format::Gzip(Quality::Default)),
    b"\x30\x30" |
    b"\x20\x00" => return Some(Format::Tar(Quality::Default)),
    _ => { }
  };
  match &x[0..3] {
    b"\x37\x7A\xBC" |
    b"\xAF\x27\x1C" => return Some(Format::Xz(Quality::Default)),
    b"\x42\x5A\x68" => return Some(Format::Bzip2(Quality::Default)),
    b"\x75\x73\x74" |
    b"\x61\x72\x20" |
    b"\x61\x72\x00" => return Some(Format::Tar(Quality::Default)),
    _ => { }
  };
  match &x[0..4] {
    b"\x81\xCF\xB2\xCE" |
    b"\xCE\xB2\xCF\x81" => return Some(Format::Brotli(Quality::Default)),
    b"\x18\x4D\x22\x04" |
    b"\x04\x22\x4D\x18" => return Some(Format::Lz4(Quality::Default)),
    b"\xB5\x28\xFD\x2F" | // Functionally _any_ block can start a zstd binary ball of joy
    b"\x28\xB5\x2F\xFD" | // this is rarely poorly documented
    b"\x27\xB5\x2F\xFD" | //
    b"\xFD\x2F\xB5\x27" | // I just add a new entry every time I see an error
    b"\x28\xB5\x2F\xFD" |
    b"\xFD\x2F\xB5\x28" => return Some(Format::Zstd(Quality::Default)),
    _ => { }
  };
  match &x[0..6] {
    b"\xFD\x37\x7A\x58\x5A\x00" => return Some(Format::Xz(Quality::Default)),
    _ => { }
  };
  match &x[0..9] {
    b"\xFF\x06\x00\x73\x4E\x61\x50\x70\x59" => return Some(Format::Snappy(Quality::Default)),
    _ => { }
  };
  None
}

<|endoftext|>


<commit_before>
fn main() {

    // formatted output
    println!("Hello, Rust!");
    println!("Integer number = {}", 23);
    println!("Float number = {}", 1.012);
    println!("Repeat printing: {0}, {1}, {1}, {3}, {2}", 2, 1, 44, 9);
    println!("Named arguments: {name}, {age}, {occupation}", age="24", name="Ann", occupation="Designer");
    println!("{:08b} XOR {:08b} = {:08b}", 3i8, 32i8, 3i8 ^ 34i8);
    println!("Floating point number {:?}", 2.910210);
    println!("Hex: {:08X}, {:08x}", 131342112, 131342112);
    // TODO find out why this doesn't work:
    //println!("{0:08X}, {0:08x}", 7661);

    // variables
    let integer = 3i32;
    let floatingPoint = 2.1137;

    let mut uInteger = 3u32;
    //integer += 1; error: an immutable variable
    uInteger += 1;

    println!("{}, {}, {}", integer, floatingPoint, uInteger);
    // TODO find out why snake case instead of camel case

    // shadowing
    let first_var = 4;
    {
        let first_var = 51;
        println!("first_var = {}", first_var);
    }
    println!("first_var = {}", first_var);

    // unitialized variables
    let uninit_var;
    //println!("uninit_var = {}", uninit_var); error: use of an init variable
    uninit_var = 231.2;
    println!("already initialized uninit_var = {}", uninit_var);

    // type casting
    let a_integer = 0x40_u8;
    let a_char = a_integer as char;
    println!("char cast from integer {}: {}", a_integer, a_char);

    let a_float = 8.45511;
    println!("integer cast from float {}: {}", a_float, a_float as i32);

    println!("Binary represntation of {}: {:08b}", -1_i8, -1_i8);
    println!("Binary represntation of {}: {:08b}", -2_i8, -2_i8);

    // aliases
    type FloatingPoint32 = f32;
    let a_float_2 : FloatingPoint32 = 3 as f32;
    println!("Type alias: {}, size of var {}", a_float_2, std::mem::size_of_val(&a_float_2));

    // expressions
    let expr = {
        let x = 4.09;
        let y = 1.28;
        println!("x = {}, y = {}", x, y);
        x / y
    };
    println!("expr = {}", expr);

    // if-statement (every if-statement is an expression too, which is really a cool thing)
    let speed = 10;
    let mass = 890;
    let consumption =
        if speed < 0 {
            -1.0
        }
        else if speed == 0 {
            0.8
        }
        else if speed > 0 && speed < 10 {
            18.52
        }
        else if speed >= 10 && speed < 30 {
            let x = mass / speed;
            (x as f32) * 0.05
        }
        else {
            11.71
        };
        println!("Speed = {}, consumption = {}", speed, consumption);

        // loop
        let mut count = 0u32;
        loop {
            println!("loop iteration #{}", count);
            count += 1;
            if count > 9 {
            break;
            }
        }

        count = 0;
        while count < 10 {
            println!("while loop iteration #{}", count);
            count += 1;
        }

        for n in 0u32..10 {
            println!("for loop iteration #{}", n);
        }

}
<commit_msg>Progress: matching (a very cool feature)<commit_after>
fn main() {

    // formatted output
    println!("Hello, Rust!");
    println!("Integer number = {}", 23);
    println!("Float number = {}", 1.012);
    println!("Repeat printing: {0}, {1}, {1}, {3}, {2}", 2, 1, 44, 9);
    println!("Named arguments: {name}, {age}, {occupation}", age="24", name="Ann", occupation="Designer");
    println!("{:08b} XOR {:08b} = {:08b}", 3i8, 32i8, 3i8 ^ 34i8);
    println!("Floating point number {:?}", 2.910210);
    println!("Hex: {:08X}, {:08x}", 131342112, 131342112);
    // TODO find out why this doesn't work:
    //println!("{0:08X}, {0:08x}", 7661);

    // variables
    let integer = 3i32;
    let floatingPoint = 2.1137;

    let mut uInteger = 3u32;
    //integer += 1; error: an immutable variable
    uInteger += 1;

    println!("{}, {}, {}", integer, floatingPoint, uInteger);
    // TODO find out why snake case instead of camel case

    // shadowing
    let first_var = 4;
    {
        let first_var = 51;
        println!("first_var = {}", first_var);
    }
    println!("first_var = {}", first_var);

    // unitialized variables
    let uninit_var;
    //println!("uninit_var = {}", uninit_var); error: use of an init variable
    uninit_var = 231.2;
    println!("already initialized uninit_var = {}", uninit_var);

    // type casting
    let a_integer = 0x40_u8;
    let a_char = a_integer as char;
    println!("char cast from integer {}: {}", a_integer, a_char);

    let a_float = 8.45511;
    println!("integer cast from float {}: {}", a_float, a_float as i32);

    println!("Binary represntation of {}: {:08b}", -1_i8, -1_i8);
    println!("Binary represntation of {}: {:08b}", -2_i8, -2_i8);

    // aliases
    type FloatingPoint32 = f32;
    let a_float_2 : FloatingPoint32 = 3 as f32;
    println!("Type alias: {}, size of var {}", a_float_2, std::mem::size_of_val(&a_float_2));

    // expressions
    let expr = {
        let x = 4.09;
        let y = 1.28;
        println!("x = {}, y = {}", x, y);
        x / y
    };
    println!("expr = {}", expr);

    // if-statement (every if-statement is an expression too, which is really a cool thing)
    let speed = 10;
    let mass = 890;
    let consumption =
        if speed < 0 {
            -1.0
        }
        else if speed == 0 {
            0.8
        }
        else if speed > 0 && speed < 10 {
            18.52
        }
        else if speed >= 10 && speed < 30 {
            let x = mass / speed;
            (x as f32) * 0.05
        }
        else {
            11.71
        };
        println!("Speed = {}, consumption = {}", speed, consumption);

        // loop
        let mut count = 0u32;
        loop {
            println!("loop iteration #{}", count);
            count += 1;
            if count > 9 {
            break;
            }
        }

        count = 0;
        while count < 10 {
            println!("while loop iteration #{}", count);
            count += 1;
        }

        for n in 0u32..10 {
            println!("for loop iteration #{}", n);
        }

        // matching
        let age = 19;
        match age {
            1  => println!("Seems like 1"),
            5  => println!("It's 5"),
            18 => println!("Exactly 18!"),
            _  => println!("I couldn't guess :("),
        }

        match age {
            a if a > 1 && a <= 9  => println!("The age is in range [1,9]"),
            a if a > 9 && a <= 19 => println!("The age is in range [10, 19]"),
            _                     => println!("Nothing, I don't know what range the age is in :("),
        }

        // the previous match is equivalent to the following:
        match age {
            a @ 1...9   => println!("The age is in range [1,9]"),
            a @ 10...19 => println!("The age is in range [10, 19]"),
            a           => println!("Nothing, I don't know what range the age is in :("),
        }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

// Marauder is turn-based strategy game with hex grid.

#[deny(non_camel_case_types)];
#[deny(non_uppercase_statics)];
#[deny(unnecessary_qualification)];
#[deny(unnecessary_typecast)];

extern mod native;
extern mod cgmath;
extern mod glfw;
extern mod gl;

use visualizer::Visualizer;

mod misc;
mod visualizer;
mod gl_helpers;
mod glfw_events;
mod camera;
mod map;
mod color;
mod geom;
mod tile_picker;

fn main() {
  let mut visualizer = Visualizer::new();
  while visualizer.is_running() {
    visualizer.handle_events();
    visualizer.pick_tile();
    visualizer.draw();
  }
}

#[start]
fn start(argc: int, argv: **u8) -> int {
  native::start(argc, argv, main)
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>main.rs: Removed useless comment<commit_after>// See LICENSE file for copyright and license details.

#[deny(non_camel_case_types)];
#[deny(non_uppercase_statics)];
#[deny(unnecessary_qualification)];
#[deny(unnecessary_typecast)];

extern mod native;
extern mod cgmath;
extern mod glfw;
extern mod gl;

use visualizer::Visualizer;

mod misc;
mod visualizer;
mod gl_helpers;
mod glfw_events;
mod camera;
mod map;
mod color;
mod geom;
mod tile_picker;

fn main() {
  let mut visualizer = Visualizer::new();
  while visualizer.is_running() {
    visualizer.handle_events();
    visualizer.pick_tile();
    visualizer.draw();
  }
}

#[start]
fn start(argc: int, argv: **u8) -> int {
  native::start(argc, argv, main)
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

// Marauder is grid-less turn-based strategy game.

extern mod glfw;
extern mod gl;
extern mod cgmath;

use gl::types::{
  GLenum,
  GLuint,
  GLint,
  GLchar,
  GLfloat,
  GLsizeiptr,
  GLboolean
};
use cgmath::matrix::{Matrix, Mat4, Mat3, ToMat4};
use cgmath::projection;
use cgmath::angle;
use cgmath::vector::{Vec3, Vec2};

#[link(name = "glfw")]
#[link(name = "m")]
extern {}

/// usage: let s = mvp_matrix; println(type_of(&s));
fn type_of<T>(_: &T) -> &'static str {
  unsafe {
    (*std::unstable::intrinsics::get_tydesc::<T>()).name
  }
}

fn print_mat4(name: &str, mat: Mat4<f32>) {
  print(name);
  print(":\n");
  for i in range(0u, 4) {
    for j in range(0u, 4) {
      print!("{} ", *mat.cr(i, j));
    }
    println("");
  }
  println("");
}

static mut MOUSE_POS: Vec2<f32> = Vec2{x: 0.0f32, y: 0.0};
static mut CAMERA_POS: Vec3<f32> = Vec3{x: 0.0f32, y: 0.0, z: 0.0};

static WIN_SIZE: Vec2<uint> = Vec2{x: 640, y: 480};
static VERTICES_COUNT: i32 = 3 * 2;

static VERTEX_DATA: [GLfloat, ..VERTICES_COUNT * 3] = [
   0.0,  1.0, 0.0,
   2.0, -1.0, 0.0,
  -2.0, -1.0, 0.0,

  0.0,  1.0,  0.0,
  0.0, -1.0,  2.0,
  0.0, -1.0, -2.0
];

static VERTEX_SHADER_SRC: &'static str = "\
  #version 130
  in vec3 position;
  uniform mat4 model_view_proj_matrix;
  void main() {
    vec4 v = vec4(position, 1);
    gl_Position = model_view_proj_matrix * v;
  }
";

static FRAGMENT_SHADER_SRC: &'static str = "\
  #version 130
  out vec4 out_color;
  void main() {
    out_color = vec4(1.0, 1.0, 1.0, 1.0);
  }
";

#[start]
fn start(argc: int, argv: **u8) -> int {
  std::rt::start_on_main_thread(argc, argv, main)
}

fn compile_shader(src: &str, ty: GLenum) -> GLuint {
  let shader = gl::CreateShader(ty);
  unsafe {
    // Attempt to compile the shader
    gl::ShaderSource(shader, 1, &src.to_c_str().unwrap(), std::ptr::null());
    gl::CompileShader(shader);

    // Get the compile status
    let mut status = gl::FALSE as GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

fn link_program(vs: GLuint, fs: GLuint) -> GLuint {
  let program = gl::CreateProgram();
  gl::AttachShader(program, vs);
  gl::AttachShader(program, fs);
  gl::LinkProgram(program);
  unsafe {
    // Get the link status
    let mut status = gl::FALSE as GLint;
    gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len: GLint = 0;
      gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

fn tr(m: Mat4<f32>, v: Vec3<f32>) -> Mat4<f32> {
  let mut t = Mat4::<f32>::identity();
  *t.mut_cr(3, 0) = v.x;
  *t.mut_cr(3, 1) = v.y;
  *t.mut_cr(3, 2) = v.z;
  m.mul_m(&t)
}

fn rot_x(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_x(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

fn rot_y(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_y(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

// change matrices
fn upd(programId: GLuint) {
  let fov = angle::deg(45.0f32);
  let ratio = 4.0 / 3.0;
  let display_range_min = 0.1;
  let display_range_max = 100.0;
  let projection_matrix = projection::perspective(
    fov, ratio, display_range_min, display_range_max
  );

  let mut mvp_matrix = projection_matrix;
  unsafe {
    mvp_matrix = tr(mvp_matrix, Vec3{x: 0.0f32, y: 0.0, z: -10.0f32});
    mvp_matrix = rot_x(mvp_matrix, MOUSE_POS.y / 100.0);
    mvp_matrix = rot_y(mvp_matrix, MOUSE_POS.x / 100.0);
    mvp_matrix = tr(mvp_matrix, CAMERA_POS);
  }

  unsafe {
    // Get a handle for our "model_view_proj_matrix" uniform.
    // Only at initialisation time.
    let matrixId = gl::GetUniformLocation(
      programId, "model_view_proj_matrix".to_c_str().unwrap());

    // Send our transformation to the currently bound shader,
    // in the "model_view_proj_matrix" uniform.
    // For each model you render, since the model_view_proj_matrix
    // will be different (at least the M part).
    gl::UniformMatrix4fv(matrixId, 1, gl::FALSE, mvp_matrix.cr(0, 0));
  }
}

fn main() {
  glfw::set_error_callback(~ErrorContext);

  do glfw::start {
    // glfw::window_hint::context_version(3, 2);

    let window = glfw::Window::create(
      WIN_SIZE.x, WIN_SIZE.y, "OpenGL", glfw::Windowed).unwrap();
    window.make_context_current();
    window.set_cursor_pos_callback(~CursorPosContext);
    window.set_key_callback(~KeyContext);

    // Load the OpenGL function pointers
    gl::load_with(glfw::get_proc_address);

    // Create GLSL shaders
    let vs = compile_shader(VERTEX_SHADER_SRC, gl::VERTEX_SHADER);
    let fs = compile_shader(FRAGMENT_SHADER_SRC, gl::FRAGMENT_SHADER);
    let program = link_program(vs, fs);

    let mut vertex_array_obj = 0;
    let mut vertex_buffer_obj = 0;

    unsafe {
      // Create Vertex Array Object
      gl::GenVertexArrays(1, &mut vertex_array_obj);
      gl::BindVertexArray(vertex_array_obj);

      // Create a Vertex Buffer Object and copy the vertex data to it
      gl::GenBuffers(1, &mut vertex_buffer_obj);
      gl::BindBuffer(gl::ARRAY_BUFFER, vertex_buffer_obj);
      let float_size = std::mem::size_of::<GLfloat>();
      let vertices_ptr = (VERTEX_DATA.len() * float_size) as GLsizeiptr;
      gl::BufferData(
        gl::ARRAY_BUFFER,
        vertices_ptr,
        std::cast::transmute(&VERTEX_DATA[0]),
        gl::STATIC_DRAW
      );

      gl::UseProgram(program);
      gl::BindFragDataLocation(program, 0, "out_color".to_c_str().unwrap());

      // Specify the layout of the vertex data
      let pos_attr = gl::GetAttribLocation(
        program, "position".to_c_str().unwrap()) as GLuint;
      gl::EnableVertexAttribArray(pos_attr);
      let size = 3;
      let normalized = gl::FALSE as GLboolean;
      let stride = 0;
      gl::VertexAttribPointer(
        pos_attr,
        size,
        gl::FLOAT,
        normalized,
        stride,
        std::ptr::null()
      );
    }

    while !window.should_close() {
      glfw::poll_events();

      upd(program);

      // Clear the screen to black
      gl::ClearColor(0.3, 0.3, 0.3, 1.0);
      gl::Clear(gl::COLOR_BUFFER_BIT);

      // Draw a triangle from the 3 vertices
      gl::DrawArrays(gl::TRIANGLES, 0, VERTICES_COUNT);

      window.swap_buffers();
    }

    // Cleanup
    gl::DeleteProgram(program);
    gl::DeleteShader(fs);
    gl::DeleteShader(vs);
    unsafe {
      gl::DeleteBuffers(1, &vertex_buffer_obj);
      gl::DeleteVertexArrays(1, &vertex_array_obj);
    }
  }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
  fn call(&self, w: &glfw::Window, xpos: f64, ypos: f64) {
    if w.get_mouse_button(glfw::MouseButtonRight) == glfw::Press {
      // println!("Cursor position: ({}, {})", xpos, ypos);
      unsafe {
        MOUSE_POS.x = xpos as f32;
        MOUSE_POS.y = ypos as f32;
      }
    }
  }
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
  fn call(&self, _: glfw::Error, description: ~str) {
    println!("GLFW Error: {:s}", description);
  }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
  fn call(
    &self,
    window: &glfw::Window,
    key:    glfw::Key,
    _:      std::libc::c_int,
    action: glfw::Action,
    _:      glfw::Modifiers
  ) {
    match (action, key) {
      (glfw::Press, glfw::KeyEscape) => {
        window.set_should_close(true)
      }
      (glfw::Press, glfw::KeySpace) => {
        println!("space")
      }
      (glfw::Press, glfw::KeyUp) => unsafe { CAMERA_POS.y -= 1.0f32 },
      (glfw::Press, glfw::KeyDown) => unsafe { CAMERA_POS.y += 1.0f32 },
      (glfw::Press, glfw::KeyRight) => unsafe { CAMERA_POS.x -= 1.0f32 },
      (glfw::Press, glfw::KeyLeft) => unsafe { CAMERA_POS.x += 1.0f32 },
      _ => {}
    }
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>Fixed style<commit_after>// See LICENSE file for copyright and license details.

// Marauder is grid-less turn-based strategy game.

extern mod glfw;
extern mod gl;
extern mod cgmath;

use gl::types::{
  GLenum,
  GLuint,
  GLint,
  GLchar,
  GLfloat,
  GLsizeiptr,
  GLboolean
};
use cgmath::matrix::{Matrix, Mat4, Mat3, ToMat4};
use cgmath::projection;
use cgmath::angle;
use cgmath::vector::{Vec3, Vec2};

#[link(name = "glfw")]
#[link(name = "m")]
extern {}

/// usage: let s = mvp_matrix; println(type_of(&s));
fn type_of<T>(_: &T) -> &'static str {
  unsafe {
    (*std::unstable::intrinsics::get_tydesc::<T>()).name
  }
}

fn print_mat4(name: &str, mat: Mat4<f32>) {
  println!("{}:", name);
  for i in range(0u, 4) {
    for j in range(0u, 4) {
      print!("{} ", *mat.cr(i, j));
    }
    println("");
  }
  println("");
}

static mut MOUSE_POS: Vec2<f32> = Vec2{x: 0.0f32, y: 0.0};
static mut CAMERA_POS: Vec3<f32> = Vec3{x: 0.0f32, y: 0.0, z: 0.0};

static WIN_SIZE: Vec2<uint> = Vec2{x: 640, y: 480};
static VERTICES_COUNT: i32 = 3 * 2;

static VERTEX_DATA: [GLfloat, ..VERTICES_COUNT * 3] = [
   0.0,  1.0, 0.0,
   2.0, -1.0, 0.0,
  -2.0, -1.0, 0.0,

  0.0,  1.0,  0.0,
  0.0, -1.0,  2.0,
  0.0, -1.0, -2.0
];

static VERTEX_SHADER_SRC: &'static str = "
  #version 130
  in vec3 position;
  uniform mat4 model_view_proj_matrix;
  void main() {
    vec4 v = vec4(position, 1);
    gl_Position = model_view_proj_matrix * v;
  }
";

static FRAGMENT_SHADER_SRC: &'static str = "
  #version 130
  out vec4 out_color;
  void main() {
    out_color = vec4(1.0, 1.0, 1.0, 1.0);
  }
";

#[start]
fn start(argc: int, argv: **u8) -> int {
  std::rt::start_on_main_thread(argc, argv, main)
}

fn compile_shader(src: &str, ty: GLenum) -> GLuint {
  let shader = gl::CreateShader(ty);
  unsafe {
    // Attempt to compile the shader
    gl::ShaderSource(shader, 1, &src.to_c_str().unwrap(), std::ptr::null());
    gl::CompileShader(shader);

    // Get the compile status
    let mut status = gl::FALSE as GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

fn link_program(vs: GLuint, fs: GLuint) -> GLuint {
  let program = gl::CreateProgram();
  gl::AttachShader(program, vs);
  gl::AttachShader(program, fs);
  gl::LinkProgram(program);
  unsafe {
    // Get the link status
    let mut status = gl::FALSE as GLint;
    gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len: GLint = 0;
      gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

fn tr(m: Mat4<f32>, v: Vec3<f32>) -> Mat4<f32> {
  let mut t = Mat4::<f32>::identity();
  *t.mut_cr(3, 0) = v.x;
  *t.mut_cr(3, 1) = v.y;
  *t.mut_cr(3, 2) = v.z;
  m.mul_m(&t)
}

fn rot_x(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_x(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

fn rot_y(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_y(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

// change matrices
fn upd(programId: GLuint) {
  let fov = angle::deg(45.0f32);
  let ratio = 4.0 / 3.0;
  let display_range_min = 0.1;
  let display_range_max = 100.0;
  let projection_matrix = projection::perspective(
    fov, ratio, display_range_min, display_range_max
  );

  let mut mvp_matrix = projection_matrix;
  unsafe {
    mvp_matrix = tr(mvp_matrix, Vec3{x: 0.0f32, y: 0.0, z: -10.0f32});
    mvp_matrix = rot_x(mvp_matrix, MOUSE_POS.y / 100.0);
    mvp_matrix = rot_y(mvp_matrix, MOUSE_POS.x / 100.0);
    mvp_matrix = tr(mvp_matrix, CAMERA_POS);
  }

  unsafe {
    // Get a handle for our "model_view_proj_matrix" uniform.
    // Only at initialisation time.
    let matrixId = gl::GetUniformLocation(
      programId, "model_view_proj_matrix".to_c_str().unwrap());

    // Send our transformation to the currently bound shader,
    // in the "model_view_proj_matrix" uniform.
    // For each model you render, since the model_view_proj_matrix
    // will be different (at least the M part).
    gl::UniformMatrix4fv(matrixId, 1, gl::FALSE, mvp_matrix.cr(0, 0));
  }
}

fn main() {
  glfw::set_error_callback(~ErrorContext);

  do glfw::start {
    // glfw::window_hint::context_version(3, 2);

    let window = glfw::Window::create(
      WIN_SIZE.x, WIN_SIZE.y, "OpenGL", glfw::Windowed).unwrap();
    window.make_context_current();
    window.set_cursor_pos_callback(~CursorPosContext);
    window.set_key_callback(~KeyContext);

    // Load the OpenGL function pointers
    gl::load_with(glfw::get_proc_address);

    // Create GLSL shaders
    let vs = compile_shader(VERTEX_SHADER_SRC, gl::VERTEX_SHADER);
    let fs = compile_shader(FRAGMENT_SHADER_SRC, gl::FRAGMENT_SHADER);
    let program = link_program(vs, fs);

    let mut vertex_array_obj = 0;
    let mut vertex_buffer_obj = 0;

    unsafe {
      // Create Vertex Array Object
      gl::GenVertexArrays(1, &mut vertex_array_obj);
      gl::BindVertexArray(vertex_array_obj);

      // Create a Vertex Buffer Object and copy the vertex data to it
      gl::GenBuffers(1, &mut vertex_buffer_obj);
      gl::BindBuffer(gl::ARRAY_BUFFER, vertex_buffer_obj);
      let float_size = std::mem::size_of::<GLfloat>();
      let vertices_ptr = (VERTEX_DATA.len() * float_size) as GLsizeiptr;
      gl::BufferData(
        gl::ARRAY_BUFFER,
        vertices_ptr,
        std::cast::transmute(&VERTEX_DATA[0]),
        gl::STATIC_DRAW
      );

      gl::UseProgram(program);
      gl::BindFragDataLocation(program, 0, "out_color".to_c_str().unwrap());

      // Specify the layout of the vertex data
      let pos_attr = gl::GetAttribLocation(
        program, "position".to_c_str().unwrap()) as GLuint;
      gl::EnableVertexAttribArray(pos_attr);
      let size = 3;
      let normalized = gl::FALSE as GLboolean;
      let stride = 0;
      gl::VertexAttribPointer(
        pos_attr,
        size,
        gl::FLOAT,
        normalized,
        stride,
        std::ptr::null()
      );
    }

    while !window.should_close() {
      glfw::poll_events();

      upd(program);

      // Clear the screen to black
      gl::ClearColor(0.3, 0.3, 0.3, 1.0);
      gl::Clear(gl::COLOR_BUFFER_BIT);

      // Draw a triangle from the 3 vertices
      gl::DrawArrays(gl::TRIANGLES, 0, VERTICES_COUNT);

      window.swap_buffers();
    }

    // Cleanup
    gl::DeleteProgram(program);
    gl::DeleteShader(fs);
    gl::DeleteShader(vs);
    unsafe {
      gl::DeleteBuffers(1, &vertex_buffer_obj);
      gl::DeleteVertexArrays(1, &vertex_array_obj);
    }
  }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
  fn call(&self, w: &glfw::Window, xpos: f64, ypos: f64) {
    if w.get_mouse_button(glfw::MouseButtonRight) == glfw::Press {
      // println!("Cursor position: ({}, {})", xpos, ypos);
      unsafe {
        MOUSE_POS.x = xpos as f32;
        MOUSE_POS.y = ypos as f32;
      }
    }
  }
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
  fn call(&self, _: glfw::Error, description: ~str) {
    println!("GLFW Error: {:s}", description);
  }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
  fn call(
    &self,
    window: &glfw::Window,
    key:    glfw::Key,
    _:      std::libc::c_int,
    action: glfw::Action,
    _:      glfw::Modifiers
  ) {
    match (action, key) {
      (glfw::Press, glfw::KeyEscape) => {
        window.set_should_close(true)
      }
      (glfw::Press, glfw::KeySpace) => {
        println!("space")
      }
      (glfw::Press, glfw::KeyUp) => unsafe { CAMERA_POS.y -= 1.0f32 },
      (glfw::Press, glfw::KeyDown) => unsafe { CAMERA_POS.y += 1.0f32 },
      (glfw::Press, glfw::KeyRight) => unsafe { CAMERA_POS.x -= 1.0f32 },
      (glfw::Press, glfw::KeyLeft) => unsafe { CAMERA_POS.x += 1.0f32 },
      _ => {}
    }
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<|endoftext|>


<commit_before>use clap::{App, Arg, ArgMatches, Values};

use crate::time::{human_time, seconds_since_build};

#[derive(Debug)]
pub struct Argument<'a> {
    arg: ArgMatches<'a>,
    pub force256color: bool,
    pub force8color: bool,
    pub login: bool,
    pub unicode: bool,
    pub force_unicode: bool,
    pub detach_on_destroy: bool,
    pub autofix: bool,
    pub inception: bool,
    pub debug: bool,
    pub usage: bool,
}

impl<'a> From<ArgMatches<'a>> for Argument<'a> {
    fn from(m: ArgMatches<'a>) -> Self {
        Argument {
            force256color: m.is_present(FORCE_256_COLOR),
            force8color: m.is_present(FORCE_8_COLOR),
            login: m.is_present(LOGIN),
            unicode: m.is_present(UNICODE),
            force_unicode: m.is_present(FORCE_UNICODE),
            detach_on_destroy: m.is_present(DETACH_ON_DESTROY),
            autofix: !m.is_present(NO_AUTOFIX),
            inception: m.is_present(INCEPTION),
            debug: m.is_present(DEBUG),
            usage: m.is_present(USAGE),
            arg: m,
        }
    }
}

impl<'a> Argument<'a> {
    pub fn tmux_args(&self) -> Values {
        self.arg.values_of(TMUX_ARG).unwrap_or_default()
    }

    pub fn socket(&self) -> &str {
        self.arg.value_of(SOCKET).unwrap()
    }
}

const FORCE_256_COLOR: &str = "FORCE_256_COLOR";
const FORCE_8_COLOR: &str = "FORCE_8_COLOR";
const SOCKET: &str = "SOCKET";
const LOGIN: &str = "LOGIN";
const UNICODE: &str = "UNICODE";
const FORCE_UNICODE: &str = "FORCE_UNICODE";
const DETACH_ON_DESTROY: &str = "DETACH_ON_DESTROY";
const NO_AUTOFIX: &str = "NO_AUTOFIX";
const INCEPTION: &str = "INCEPTION";
const DEBUG: &str = "DEBUG";
const TMUX_ARG: &str = "TMUX_ARG";
const USAGE: &str = "USAGE";

fn get_version() -> Option<String> {
    option_env!("SHORT_SHA").map(|short_sha| match seconds_since_build() {
        Some(secs) => format!("#{} ({} since last build)", short_sha, human_time(secs)),
        None => short_sha.to_string(),
    })
}

pub fn parse(unicode: &str) -> Argument {
    let version = get_version().unwrap_or_default();
    const NAME: &str = "nmk.rs";
    App::new(NAME)
        .bin_name(NAME)
        .version(version.as_str())
        .about("An entrypoint for nmk")
        .arg(Arg::with_name(FORCE_256_COLOR)
            .short("2")
            .help("Assume the terminal supports 256 colours")
        )
        .arg(Arg::with_name(FORCE_8_COLOR)
            .short("8")
            .help("Force 8 colours terminal")
        )
        .arg(Arg::with_name(SOCKET)
            .short("L")
            .long("socket")
            .default_value("nmk")
            .value_name("SOCKET")
            .takes_value(true)
            .help("Use a different tmux socket name")
        )
        .arg(Arg::with_name(LOGIN)
            .short("l")
            .long("login")
            .help("Start login shell")
        )
        .arg(Arg::with_name(UNICODE)
            .short("u")
            .long("unicode")
            .help(format!("LANG={}", unicode).as_str())
        )
        .arg(Arg::with_name(FORCE_UNICODE)
            .long("force-unicode")
            .help(format!("LC_ALL={}", unicode).as_str())
        )
        .arg(Arg::with_name(DETACH_ON_DESTROY)
            .long("detach-on-destroy")
            .help("Detach the client when the session is destroyed")
        )
        .arg(Arg::with_name(NO_AUTOFIX)
            .long("no-autofix")
            .help("Disable automatically fix")
        )
        .arg(Arg::with_name(INCEPTION)
            .long("inception")
            .help("Allow nested tmux sessions")
        )
        .arg(Arg::with_name(DEBUG)
            .short("d")
            .long("debug")
            .help("Display debug log")
        )
        .arg(Arg::with_name(USAGE)
            .long("usage")
            .help("Print usage time")
        )
        .arg(Arg::with_name(TMUX_ARG).multiple(true))
        .get_matches()
        .into()
}
<commit_msg>nmk.rs: show time since last built in all build<commit_after>use clap::{App, Arg, ArgMatches, Values};

use crate::time::{human_time, seconds_since_build};

#[derive(Debug)]
pub struct Argument<'a> {
    arg: ArgMatches<'a>,
    pub force256color: bool,
    pub force8color: bool,
    pub login: bool,
    pub unicode: bool,
    pub force_unicode: bool,
    pub detach_on_destroy: bool,
    pub autofix: bool,
    pub inception: bool,
    pub debug: bool,
    pub usage: bool,
}

impl<'a> From<ArgMatches<'a>> for Argument<'a> {
    fn from(m: ArgMatches<'a>) -> Self {
        Argument {
            force256color: m.is_present(FORCE_256_COLOR),
            force8color: m.is_present(FORCE_8_COLOR),
            login: m.is_present(LOGIN),
            unicode: m.is_present(UNICODE),
            force_unicode: m.is_present(FORCE_UNICODE),
            detach_on_destroy: m.is_present(DETACH_ON_DESTROY),
            autofix: !m.is_present(NO_AUTOFIX),
            inception: m.is_present(INCEPTION),
            debug: m.is_present(DEBUG),
            usage: m.is_present(USAGE),
            arg: m,
        }
    }
}

impl<'a> Argument<'a> {
    pub fn tmux_args(&self) -> Values {
        self.arg.values_of(TMUX_ARG).unwrap_or_default()
    }

    pub fn socket(&self) -> &str {
        self.arg.value_of(SOCKET).unwrap()
    }
}

const FORCE_256_COLOR: &str = "FORCE_256_COLOR";
const FORCE_8_COLOR: &str = "FORCE_8_COLOR";
const SOCKET: &str = "SOCKET";
const LOGIN: &str = "LOGIN";
const UNICODE: &str = "UNICODE";
const FORCE_UNICODE: &str = "FORCE_UNICODE";
const DETACH_ON_DESTROY: &str = "DETACH_ON_DESTROY";
const NO_AUTOFIX: &str = "NO_AUTOFIX";
const INCEPTION: &str = "INCEPTION";
const DEBUG: &str = "DEBUG";
const TMUX_ARG: &str = "TMUX_ARG";
const USAGE: &str = "USAGE";

fn get_version() -> Option<String> {
    match (seconds_since_build(), option_env!("SHORT_SHA")) {
        (Some(secs), Some(sha)) => Some(format!("#{} ({} since last build)", sha, human_time(secs))),
        (Some(secs), None) => Some(format!("({} since last build)", human_time(secs))),
        _ => None,
    }
}

pub fn parse(unicode: &str) -> Argument {
    let version = get_version().unwrap_or_default();
    const NAME: &str = "nmk.rs";
    App::new(NAME)
        .bin_name(NAME)
        .version(version.as_str())
        .about("An entrypoint for nmk")
        .arg(Arg::with_name(FORCE_256_COLOR)
            .short("2")
            .help("Assume the terminal supports 256 colours")
        )
        .arg(Arg::with_name(FORCE_8_COLOR)
            .short("8")
            .help("Force 8 colours terminal")
        )
        .arg(Arg::with_name(SOCKET)
            .short("L")
            .long("socket")
            .default_value("nmk")
            .value_name("SOCKET")
            .takes_value(true)
            .help("Use a different tmux socket name")
        )
        .arg(Arg::with_name(LOGIN)
            .short("l")
            .long("login")
            .help("Start login shell")
        )
        .arg(Arg::with_name(UNICODE)
            .short("u")
            .long("unicode")
            .help(format!("LANG={}", unicode).as_str())
        )
        .arg(Arg::with_name(FORCE_UNICODE)
            .long("force-unicode")
            .help(format!("LC_ALL={}", unicode).as_str())
        )
        .arg(Arg::with_name(DETACH_ON_DESTROY)
            .long("detach-on-destroy")
            .help("Detach the client when the session is destroyed")
        )
        .arg(Arg::with_name(NO_AUTOFIX)
            .long("no-autofix")
            .help("Disable automatically fix")
        )
        .arg(Arg::with_name(INCEPTION)
            .long("inception")
            .help("Allow nested tmux sessions")
        )
        .arg(Arg::with_name(DEBUG)
            .short("d")
            .long("debug")
            .help("Display debug log")
        )
        .arg(Arg::with_name(USAGE)
            .long("usage")
            .help("Print usage time")
        )
        .arg(Arg::with_name(TMUX_ARG).multiple(true))
        .get_matches()
        .into()
}
<|endoftext|>