<commit_before>use core::arch::x86_64 as arch;
use std::env;
use std::f64::consts::PI;
use std::fs::File;
use std::io::Read;
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::str;
use std::thread;
use std::time::Instant;
use std::vec;

/*mod laplace;
mod matmul;

pub use matmul::test_matmul_strassen;*/

#[inline]
fn get_timestamp_rdtscp() -> u64 {
	unsafe {
		let mut _aux = 0;
		let value = arch::__rdtscp(&mut _aux);
		arch::_mm_lfence();
		value
	}
}

pub fn thread_creation() -> Result<(), ()> {
	let n = 1000;

	// cache warmup
	let _ = get_timestamp_rdtscp();

	let mut sum: u64 = 0;
	for _ in 0..n {
		let builder = thread::Builder::new();
		let start = get_timestamp_rdtscp();
		let child = builder.spawn(|| get_timestamp_rdtscp()).unwrap();
		thread::yield_now();
		match child.join() {
			Ok(end) => {
				sum += end - start;
			}
			Err(_) => {
				println!("Unable to join thread!");
			}
		}
	}

	println!("Time to create a thread {} ticks", sum / n);

	Ok(())
}

pub fn bench_sched_one_thread() -> Result<(), ()> {
	let n = 1000000;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp_rdtscp();

	let start = get_timestamp_rdtscp();
	for _ in 0..n {
		thread::yield_now();
	}
	let ticks = get_timestamp_rdtscp() - start;

	println!("Scheduling time {} ticks (1 thread)", ticks / n);

	Ok(())
}

pub fn bench_sched_two_threads() -> Result<(), ()> {
	let n = 1000000;
	let nthreads = 2;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp_rdtscp();

	let start = get_timestamp_rdtscp();
	let threads: Vec<_> = (0..nthreads - 1)
		.map(|_| {
			thread::spawn(move || {
				for _ in 0..n {
					thread::yield_now();
				}
			})
		})
		.collect();

	for _ in 0..n {
		thread::yield_now();
	}

	let ticks = get_timestamp_rdtscp() - start;

	for t in threads {
		t.join().unwrap();
	}

	println!(
		"Scheduling time {} ticks (2 threads)",
		ticks / (nthreads * n)
	);

	Ok(())
}

pub fn pi_sequential(num_steps: u64) -> Result<(), ()> {
	let step = 1.0 / num_steps as f64;
	let mut sum = 0 as f64;

	for i in 0..num_steps {
		let x = (i as f64 + 0.5) * step;
		sum += 4.0 / (1.0 + x * x);
	}

	let mypi = sum * (1.0 / num_steps as f64);
	println!("Pi: {} (sequential)", mypi);

	if (mypi - PI).abs() < 0.00001 {
		Ok(())
	} else {
		Err(())
	}
}

pub fn pi_parallel(nthreads: u64, num_steps: u64) -> Result<(), ()> {
	let step = 1.0 / num_steps as f64;
	let mut sum = 0.0 as f64;

	let threads: Vec<_> = (0..nthreads)
		.map(|tid| {
			thread::spawn(move || {
				let mut partial_sum = 0 as f64;
				let start = (num_steps / nthreads) * tid;
				let end = (num_steps / nthreads) * (tid + 1);

				for i in start..end {
					let x = (i as f64 + 0.5) * step;
					partial_sum += 4.0 / (1.0 + x * x);
				}

				partial_sum
			})
		})
		.collect();

	for t in threads {
		sum += t.join().unwrap();
	}

	let mypi = sum * (1.0 / num_steps as f64);
	println!("Pi: {} (with {} threads)", mypi, nthreads);

	if (mypi - PI).abs() < 0.00001 {
		Ok(())
	} else {
		Err(())
	}
}

pub fn read_file() -> Result<(), std::io::Error> {
	let mut file = File::open("/etc/hostname")?;
	let mut contents = String::new();
	file.read_to_string(&mut contents)?;

	println!("Hostname: {}", contents);

	Ok(())
}

pub fn create_file() -> Result<(), std::io::Error> {
	{
		let mut file = File::create("/tmp/foo.txt")?;
		file.write_all(b"Hello, world!")?;
	}

	let contents = {
		let mut file = File::open("/tmp/foo.txt")?;
		let mut contents = String::new();
		file.read_to_string(&mut contents)?;
		contents
	};

	// delete temporary file
	std::fs::remove_file("/tmp/foo.txt")?;

	if contents == "Hello, world!" {
		Ok(())
	} else {
		let kind = std::io::ErrorKind::Other;
		Err(std::io::Error::from(kind))
	}
}

pub fn print_argv() -> Result<(), ()> {
	let args = env::args();

	// Prints each argument on a separate line
	for (i, argument) in args.enumerate() {
		println!("argument[{}] = {}", i, argument);
	}

	Ok(())
}

pub fn print_env() -> Result<(), ()> {
	let envs = env::vars();

	// We will iterate through the references to the element returned by
	// env::vars();
	for (key, value) in envs {
		println!("{}: {}", key, value);
	}

	Ok(())
}

pub fn hello() -> Result<(), ()> {
	println!("Hello, world!");

	Ok(())
}

pub fn threading() -> Result<(), ()> {
	// Make a vector to hold the children which are spawned.
	let mut children = vec![];

	for i in 0..2 {
		// Spin up another thread
		children.push(thread::spawn(move || {
			println!("this is thread number {}", i);
		}));
	}

	for child in children {
		// Wait for the thread to finish. Returns a result.
		let _ = child.join();
	}

	Ok(())
}

/*pub fn laplace(size_x: usize, size_y: usize) -> Result<(), ()> {
	let matrix = matrix_setup(size_x, size_y);

	let now = Instant::now();
	let (iterations, res) = laplace::compute(matrix, size_x, size_y);
	println!(
		"Time to solve {} s, iterations {}, residuum {}",
		now.elapsed().as_secs_f64(),
		iterations,
		res
	);

	if res < 0.01 {
		Ok(())
	} else {
		Err(())
	}
}

pub fn matrix_setup(size_x: usize, size_y: usize) -> (vec::Vec<vec::Vec<f64>>) {
	let mut matrix = vec![vec![0.0; size_x * size_y]; 2];

	// top row
	for x in 0..size_x {
		matrix[0][x] = 1.0;
		matrix[1][x] = 1.0;
	}

	// bottom row
	for x in 0..size_x {
		matrix[0][(size_y - 1) * size_x + x] = 1.0;
		matrix[1][(size_y - 1) * size_x + x] = 1.0;
	}

	// left row
	for y in 0..size_y {
		matrix[0][y * size_x] = 1.0;
		matrix[1][y * size_x] = 1.0;
	}

	// right row
	for y in 0..size_y {
		matrix[0][y * size_x + size_x - 1] = 1.0;
		matrix[1][y * size_x + size_x - 1] = 1.0;
	}

	matrix
}*/

fn send_http_rquest() -> Result<Vec<u8>, std::io::Error> {
	let mut stream = TcpStream::connect("10.0.5.1:7878")?;
	let buf = b"GET / HTTP/1.1\r\nHost: 10.0.5.1\r\nUser-Agent: hermit/0.3.16\r\nAccept: */*\r\n\r\n";
	stream.write_all(buf)?;

	let mut buf = Vec::new();
	stream.read_to_end(&mut buf)?;

	Ok(buf)
}

pub fn test_http_request() -> Result<(), std::io::Error> {
	let buf = send_http_rquest()?;
	let result = str::from_utf8(&buf)
		.unwrap()
		.to_owned()
		.starts_with("HTTP/1.1 200 OK");

	match result {
		true => println!("Ckeck http response... ok"),
		_ => println!("Ckeck http response... failed!"),
	};

	Ok(())
}
<commit_msg>remove typos<commit_after>use core::arch::x86_64 as arch;
use std::env;
use std::f64::consts::PI;
use std::fs::File;
use std::io::Read;
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::str;
use std::thread;
use std::time::Instant;
use std::vec;

/*mod laplace;
mod matmul;

pub use matmul::test_matmul_strassen;*/

#[inline]
fn get_timestamp_rdtscp() -> u64 {
	unsafe {
		let mut _aux = 0;
		let value = arch::__rdtscp(&mut _aux);
		arch::_mm_lfence();
		value
	}
}

pub fn thread_creation() -> Result<(), ()> {
	let n = 1000;

	// cache warmup
	let _ = get_timestamp_rdtscp();

	let mut sum: u64 = 0;
	for _ in 0..n {
		let builder = thread::Builder::new();
		let start = get_timestamp_rdtscp();
		let child = builder.spawn(|| get_timestamp_rdtscp()).unwrap();
		thread::yield_now();
		match child.join() {
			Ok(end) => {
				sum += end - start;
			}
			Err(_) => {
				println!("Unable to join thread!");
			}
		}
	}

	println!("Time to create a thread {} ticks", sum / n);

	Ok(())
}

pub fn bench_sched_one_thread() -> Result<(), ()> {
	let n = 1000000;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp_rdtscp();

	let start = get_timestamp_rdtscp();
	for _ in 0..n {
		thread::yield_now();
	}
	let ticks = get_timestamp_rdtscp() - start;

	println!("Scheduling time {} ticks (1 thread)", ticks / n);

	Ok(())
}

pub fn bench_sched_two_threads() -> Result<(), ()> {
	let n = 1000000;
	let nthreads = 2;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp_rdtscp();

	let start = get_timestamp_rdtscp();
	let threads: Vec<_> = (0..nthreads - 1)
		.map(|_| {
			thread::spawn(move || {
				for _ in 0..n {
					thread::yield_now();
				}
			})
		})
		.collect();

	for _ in 0..n {
		thread::yield_now();
	}

	let ticks = get_timestamp_rdtscp() - start;

	for t in threads {
		t.join().unwrap();
	}

	println!(
		"Scheduling time {} ticks (2 threads)",
		ticks / (nthreads * n)
	);

	Ok(())
}

pub fn pi_sequential(num_steps: u64) -> Result<(), ()> {
	let step = 1.0 / num_steps as f64;
	let mut sum = 0 as f64;

	for i in 0..num_steps {
		let x = (i as f64 + 0.5) * step;
		sum += 4.0 / (1.0 + x * x);
	}

	let mypi = sum * (1.0 / num_steps as f64);
	println!("Pi: {} (sequential)", mypi);

	if (mypi - PI).abs() < 0.00001 {
		Ok(())
	} else {
		Err(())
	}
}

pub fn pi_parallel(nthreads: u64, num_steps: u64) -> Result<(), ()> {
	let step = 1.0 / num_steps as f64;
	let mut sum = 0.0 as f64;

	let threads: Vec<_> = (0..nthreads)
		.map(|tid| {
			thread::spawn(move || {
				let mut partial_sum = 0 as f64;
				let start = (num_steps / nthreads) * tid;
				let end = (num_steps / nthreads) * (tid + 1);

				for i in start..end {
					let x = (i as f64 + 0.5) * step;
					partial_sum += 4.0 / (1.0 + x * x);
				}

				partial_sum
			})
		})
		.collect();

	for t in threads {
		sum += t.join().unwrap();
	}

	let mypi = sum * (1.0 / num_steps as f64);
	println!("Pi: {} (with {} threads)", mypi, nthreads);

	if (mypi - PI).abs() < 0.00001 {
		Ok(())
	} else {
		Err(())
	}
}

pub fn read_file() -> Result<(), std::io::Error> {
	let mut file = File::open("/etc/hostname")?;
	let mut contents = String::new();
	file.read_to_string(&mut contents)?;

	println!("Hostname: {}", contents);

	Ok(())
}

pub fn create_file() -> Result<(), std::io::Error> {
	{
		let mut file = File::create("/tmp/foo.txt")?;
		file.write_all(b"Hello, world!")?;
	}

	let contents = {
		let mut file = File::open("/tmp/foo.txt")?;
		let mut contents = String::new();
		file.read_to_string(&mut contents)?;
		contents
	};

	// delete temporary file
	std::fs::remove_file("/tmp/foo.txt")?;

	if contents == "Hello, world!" {
		Ok(())
	} else {
		let kind = std::io::ErrorKind::Other;
		Err(std::io::Error::from(kind))
	}
}

pub fn print_argv() -> Result<(), ()> {
	let args = env::args();

	// Prints each argument on a separate line
	for (i, argument) in args.enumerate() {
		println!("argument[{}] = {}", i, argument);
	}

	Ok(())
}

pub fn print_env() -> Result<(), ()> {
	let envs = env::vars();

	// We will iterate through the references to the element returned by
	// env::vars();
	for (key, value) in envs {
		println!("{}: {}", key, value);
	}

	Ok(())
}

pub fn hello() -> Result<(), ()> {
	println!("Hello, world!");

	Ok(())
}

pub fn threading() -> Result<(), ()> {
	// Make a vector to hold the children which are spawned.
	let mut children = vec![];

	for i in 0..2 {
		// Spin up another thread
		children.push(thread::spawn(move || {
			println!("this is thread number {}", i);
		}));
	}

	for child in children {
		// Wait for the thread to finish. Returns a result.
		let _ = child.join();
	}

	Ok(())
}

/*pub fn laplace(size_x: usize, size_y: usize) -> Result<(), ()> {
	let matrix = matrix_setup(size_x, size_y);

	let now = Instant::now();
	let (iterations, res) = laplace::compute(matrix, size_x, size_y);
	println!(
		"Time to solve {} s, iterations {}, residuum {}",
		now.elapsed().as_secs_f64(),
		iterations,
		res
	);

	if res < 0.01 {
		Ok(())
	} else {
		Err(())
	}
}

pub fn matrix_setup(size_x: usize, size_y: usize) -> (vec::Vec<vec::Vec<f64>>) {
	let mut matrix = vec![vec![0.0; size_x * size_y]; 2];

	// top row
	for x in 0..size_x {
		matrix[0][x] = 1.0;
		matrix[1][x] = 1.0;
	}

	// bottom row
	for x in 0..size_x {
		matrix[0][(size_y - 1) * size_x + x] = 1.0;
		matrix[1][(size_y - 1) * size_x + x] = 1.0;
	}

	// left row
	for y in 0..size_y {
		matrix[0][y * size_x] = 1.0;
		matrix[1][y * size_x] = 1.0;
	}

	// right row
	for y in 0..size_y {
		matrix[0][y * size_x + size_x - 1] = 1.0;
		matrix[1][y * size_x + size_x - 1] = 1.0;
	}

	matrix
}*/

fn send_http_rquest() -> Result<Vec<u8>, std::io::Error> {
	let mut stream = TcpStream::connect("10.0.5.1:7878")?;
	let buf = b"GET / HTTP/1.1\r\nHost: 10.0.5.1\r\nUser-Agent: hermit/0.3.16\r\nAccept: */*\r\n\r\n";
	stream.write_all(buf)?;

	let mut buf = Vec::new();
	stream.read_to_end(&mut buf)?;

	Ok(buf)
}

pub fn test_http_request() -> Result<(), std::io::Error> {
	let buf = send_http_rquest()?;
	let result = str::from_utf8(&buf)
		.unwrap()
		.to_owned()
		.starts_with("HTTP/1.1 200 OK");

	match result {
		true => println!("Check http response... ok"),
		_ => println!("Check http response... failed!"),
	};

	Ok(())
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, WriteBytesExt};
use std::io::{self, Write};

use color;

/// The representation of a BMP encoder.
pub struct BMPEncoder<'a, W: 'a> {
    writer: &'a mut W,
}

impl<'a, W: Write + 'a> BMPEncoder<'a, W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: &'a mut W) -> Self {
        BMPEncoder { writer: w }
    }

    /// Encodes the image ```image```
    /// that has dimensions ```width``` and ```height```
    /// and ```ColorType``` ```c```.
    pub fn encode(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        c: color::ColorType,
    ) -> io::Result<()> {
        let bmp_header_size = 14;
        let dib_header_size = 40; // using BITMAPINFOHEADER

        let (raw_pixel_size, written_pixel_size, palette_color_count) = try!(get_pixel_info(c));
        let row_pad_size = (4 - (width * written_pixel_size) % 4) % 4; // each row must be padded to a multiple of 4 bytes

        let image_size = width * height * written_pixel_size + (height * row_pad_size);
        let palette_size = palette_color_count * 4; // all palette colors are BGRA
        let file_size = bmp_header_size + dib_header_size + palette_size + image_size;

        // write BMP header
        try!(self.writer.write_u8(b'B'));
        try!(self.writer.write_u8(b'M'));
        try!(self.writer.write_u32::<LittleEndian>(file_size)); // file size
        try!(self.writer.write_u16::<LittleEndian>(0)); // reserved 1
        try!(self.writer.write_u16::<LittleEndian>(0)); // reserved 2
        try!(
            self.writer
                .write_u32::<LittleEndian>(bmp_header_size + dib_header_size + palette_size)
        ); // image data offset

        // write DIB header
        try!(self.writer.write_u32::<LittleEndian>(dib_header_size));
        try!(self.writer.write_i32::<LittleEndian>(width as i32));
        try!(self.writer.write_i32::<LittleEndian>(height as i32));
        try!(self.writer.write_u16::<LittleEndian>(1)); // color planes
        try!(
            self.writer
                .write_u16::<LittleEndian>((written_pixel_size * 8) as u16)
        ); // bits per pixel
        try!(self.writer.write_u32::<LittleEndian>(0)); // compression method - no compression
        try!(self.writer.write_u32::<LittleEndian>(image_size));
        try!(self.writer.write_i32::<LittleEndian>(0)); // horizontal ppm
        try!(self.writer.write_i32::<LittleEndian>(0)); // vertical ppm
        try!(self.writer.write_u32::<LittleEndian>(palette_color_count));
        try!(self.writer.write_u32::<LittleEndian>(0)); // all colors are important

        // write image data
        match c {
            color::ColorType::RGB(8) | color::ColorType::RGBA(8) => {
                try!(self.encode_rgb(image, width, height, row_pad_size, raw_pixel_size))
            }
            color::ColorType::Gray(8) | color::ColorType::GrayA(8) => {
                try!(self.encode_gray(image, width, height, row_pad_size, raw_pixel_size))
            }
            _ => {
                return Err(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    &get_unsupported_error_message(c)[..],
                ))
            }
        }

        Ok(())
    }

    fn encode_rgb(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                let r = image[pixel_start];
                let g = image[pixel_start + 1];
                let b = image[pixel_start + 2];
                // written as BGR
                try!(self.writer.write_u8(b));
                try!(self.writer.write_u8(g));
                try!(self.writer.write_u8(r));
                // alpha is never written as it's not widely supported
            }

            try!(self.write_row_pad(row_pad_size));
        }

        Ok(())
    }

    fn encode_gray(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        // write grayscale palette
        for val in 0..256 {
            // each color is written as BGRA, where A is always 0 and since only grayscale is being written, B = G = R = index
            let val = val as u8;
            try!(self.writer.write_u8(val));
            try!(self.writer.write_u8(val));
            try!(self.writer.write_u8(val));
            try!(self.writer.write_u8(0));
        }

        // write image data
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                // color value is equal to the palette index
                try!(self.writer.write_u8(image[pixel_start]));
                // alpha is never written as it's not widely supported
            }

            try!(self.write_row_pad(row_pad_size));
        }

        Ok(())
    }

    fn write_row_pad(&mut self, row_pad_size: u32) -> io::Result<()> {
        for _ in 0..row_pad_size {
            try!(self.writer.write_u8(0));
        }

        Ok(())
    }
}

fn get_unsupported_error_message(c: color::ColorType) -> String {
    format!(
        "Unsupported color type {:?}.  Supported types: RGB(8), RGBA(8), Gray(8), GrayA(8).",
        c
    )
}

/// Returns a tuple representing: (raw pixel size, written pixel size, palette color count).
fn get_pixel_info(c: color::ColorType) -> io::Result<(u32, u32, u32)> {
    let sizes = match c {
        color::ColorType::RGB(8) => (3, 3, 0),
        color::ColorType::RGBA(8) => (4, 3, 0),
        color::ColorType::Gray(8) => (1, 1, 256),
        color::ColorType::GrayA(8) => (2, 1, 256),
        _ => {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                &get_unsupported_error_message(c)[..],
            ))
        }
    };

    Ok(sizes)
}

#[cfg(test)]
mod tests {
    use super::super::BMPDecoder;
    use super::BMPEncoder;
    use color::ColorType;
    use image::ImageDecoder;
    use std::io::Cursor;

    fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec<u8> {
        let mut encoded_data = Vec::new();
        {
            let mut encoder = BMPEncoder::new(&mut encoded_data);
            encoder
                .encode(&image, width, height, c)
                .expect("could not encode image");
        }

        let decoder = BMPDecoder::new(Cursor::new(&encoded_data)).expect("failed to decode");
        decoder.read_image().expect("failed to decode")
    }

    #[test]
    fn round_trip_single_pixel_rgb() {
        let image = [255u8, 0, 0]; // single red pixel
        let decoded = round_trip_image(&image, 1, 1, ColorType::RGB(8));
        assert_eq!(3, decoded.len());
        assert_eq!(255, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
    }

    #[test]
    fn round_trip_single_pixel_rgba() {
        let image = [255u8, 0, 0, 0]; // single red pixel
        let decoded = round_trip_image(&image, 1, 1, ColorType::RGBA(8));
        assert_eq!(3, decoded.len());
        assert_eq!(255, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
    }

    #[test]
    fn round_trip_3px_rgb() {
        let image = [0u8; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel
        let _decoded = round_trip_image(&image, 3, 3, ColorType::RGB(8));
    }

    #[test]
    fn round_trip_gray() {
        let image = [0u8, 1, 2]; // 3 pixels
        let decoded = round_trip_image(&image, 3, 1, ColorType::Gray(8));
        // should be read back as 3 RGB pixels
        assert_eq!(9, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
        assert_eq!(1, decoded[3]);
        assert_eq!(1, decoded[4]);
        assert_eq!(1, decoded[5]);
        assert_eq!(2, decoded[6]);
        assert_eq!(2, decoded[7]);
        assert_eq!(2, decoded[8]);
    }

    #[test]
    fn round_trip_graya() {
        let image = [0u8, 0, 1, 0, 2, 0]; // 3 pixels, each with an alpha channel
        let decoded = round_trip_image(&image, 1, 3, ColorType::GrayA(8));
        // should be read back as 3 RGB pixels
        assert_eq!(9, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
        assert_eq!(1, decoded[3]);
        assert_eq!(1, decoded[4]);
        assert_eq!(1, decoded[5]);
        assert_eq!(2, decoded[6]);
        assert_eq!(2, decoded[7]);
        assert_eq!(2, decoded[8]);
    }
}
<commit_msg>bmp/encoder: encode RGBA using bitfields with alpha mask<commit_after>use byteorder::{LittleEndian, WriteBytesExt};
use std::io::{self, Write};

use color;

const BITMAPFILEHEADER_SIZE: u32 = 14;
const BITMAPINFOHEADER_SIZE: u32 = 40;
const BITMAPV4HEADER_SIZE: u32 = 108;

/// The representation of a BMP encoder.
pub struct BMPEncoder<'a, W: 'a> {
    writer: &'a mut W,
}

impl<'a, W: Write + 'a> BMPEncoder<'a, W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: &'a mut W) -> Self {
        BMPEncoder { writer: w }
    }

    /// Encodes the image ```image```
    /// that has dimensions ```width``` and ```height```
    /// and ```ColorType``` ```c```.
    pub fn encode(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        c: color::ColorType,
    ) -> io::Result<()> {
        let bmp_header_size = BITMAPFILEHEADER_SIZE;

        let (dib_header_size, written_pixel_size, palette_color_count) = try!(get_pixel_info(c));
        let row_pad_size = (4 - (width * written_pixel_size) % 4) % 4; // each row must be padded to a multiple of 4 bytes

        let image_size = width * height * written_pixel_size + (height * row_pad_size);
        let palette_size = palette_color_count * 4; // all palette colors are BGRA
        let file_size = bmp_header_size + dib_header_size + palette_size + image_size;

        // write BMP header
        try!(self.writer.write_u8(b'B'));
        try!(self.writer.write_u8(b'M'));
        try!(self.writer.write_u32::<LittleEndian>(file_size)); // file size
        try!(self.writer.write_u16::<LittleEndian>(0)); // reserved 1
        try!(self.writer.write_u16::<LittleEndian>(0)); // reserved 2
        try!(
            self.writer
                .write_u32::<LittleEndian>(bmp_header_size + dib_header_size + palette_size)
        ); // image data offset

        // write DIB header
        try!(self.writer.write_u32::<LittleEndian>(dib_header_size));
        try!(self.writer.write_i32::<LittleEndian>(width as i32));
        try!(self.writer.write_i32::<LittleEndian>(height as i32));
        try!(self.writer.write_u16::<LittleEndian>(1)); // color planes
        try!(
            self.writer
                .write_u16::<LittleEndian>((written_pixel_size * 8) as u16)
        ); // bits per pixel
        if dib_header_size >= BITMAPV4HEADER_SIZE {
            // Assume BGRA32
            try!(self.writer.write_u32::<LittleEndian>(3)); // compression method - bitfields
        } else {
            try!(self.writer.write_u32::<LittleEndian>(0)); // compression method - no compression
        }
        try!(self.writer.write_u32::<LittleEndian>(image_size));
        try!(self.writer.write_i32::<LittleEndian>(0)); // horizontal ppm
        try!(self.writer.write_i32::<LittleEndian>(0)); // vertical ppm
        try!(self.writer.write_u32::<LittleEndian>(palette_color_count));
        try!(self.writer.write_u32::<LittleEndian>(0)); // all colors are important
        if dib_header_size >= BITMAPV4HEADER_SIZE {
            // Assume BGRA32
            try!(self.writer.write_u32::<LittleEndian>(0xff << 16)); // red mask
            try!(self.writer.write_u32::<LittleEndian>(0xff << 8)); // green mask
            try!(self.writer.write_u32::<LittleEndian>(0xff << 0)); // blue mask
            try!(self.writer.write_u32::<LittleEndian>(0xff << 24)); // alpha mask
            try!(self.writer.write_u32::<LittleEndian>(0x73524742)); // colorspace - sRGB
            // endpoints (3x3) and gamma (3)
            for _ in 0..12 {
                try!(self.writer.write_u32::<LittleEndian>(0));
            }
        }

        // write image data
        match c {
            color::ColorType::RGB(8) => {
                try!(self.encode_rgb(image, width, height, row_pad_size, 3))
            }
            color::ColorType::RGBA(8) => {
                try!(self.encode_rgba(image, width, height, row_pad_size, 4))
            }
            color::ColorType::Gray(8) => {
                try!(self.encode_gray(image, width, height, row_pad_size, 1))
            }
            color::ColorType::GrayA(8) => {
                try!(self.encode_gray(image, width, height, row_pad_size, 2))
            }
            _ => {
                return Err(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    &get_unsupported_error_message(c)[..],
                ))
            }
        }

        Ok(())
    }

    fn encode_rgb(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                let r = image[pixel_start];
                let g = image[pixel_start + 1];
                let b = image[pixel_start + 2];
                // written as BGR
                try!(self.writer.write_u8(b));
                try!(self.writer.write_u8(g));
                try!(self.writer.write_u8(r));
                // alpha is never written as it's not widely supported
            }

            try!(self.write_row_pad(row_pad_size));
        }

        Ok(())
    }

    fn encode_rgba(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                let r = image[pixel_start];
                let g = image[pixel_start + 1];
                let b = image[pixel_start + 2];
                let a = image[pixel_start + 3];
                // written as BGRA
                try!(self.writer.write_u8(b));
                try!(self.writer.write_u8(g));
                try!(self.writer.write_u8(r));
                try!(self.writer.write_u8(a));
            }

            try!(self.write_row_pad(row_pad_size));
        }

        Ok(())
    }

    fn encode_gray(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        // write grayscale palette
        for val in 0..256 {
            // each color is written as BGRA, where A is always 0 and since only grayscale is being written, B = G = R = index
            let val = val as u8;
            try!(self.writer.write_u8(val));
            try!(self.writer.write_u8(val));
            try!(self.writer.write_u8(val));
            try!(self.writer.write_u8(0));
        }

        // write image data
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                // color value is equal to the palette index
                try!(self.writer.write_u8(image[pixel_start]));
                // alpha is never written as it's not widely supported
            }

            try!(self.write_row_pad(row_pad_size));
        }

        Ok(())
    }

    fn write_row_pad(&mut self, row_pad_size: u32) -> io::Result<()> {
        for _ in 0..row_pad_size {
            try!(self.writer.write_u8(0));
        }

        Ok(())
    }
}

fn get_unsupported_error_message(c: color::ColorType) -> String {
    format!(
        "Unsupported color type {:?}.  Supported types: RGB(8), RGBA(8), Gray(8), GrayA(8).",
        c
    )
}

/// Returns a tuple representing: (dib header size, written pixel size, palette color count).
fn get_pixel_info(c: color::ColorType) -> io::Result<(u32, u32, u32)> {
    let sizes = match c {
        color::ColorType::RGB(8) => (BITMAPINFOHEADER_SIZE, 3, 0),
        color::ColorType::RGBA(8) => (BITMAPV4HEADER_SIZE, 4, 0),
        color::ColorType::Gray(8) => (BITMAPINFOHEADER_SIZE, 1, 256),
        color::ColorType::GrayA(8) => (BITMAPINFOHEADER_SIZE, 1, 256),
        _ => {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                &get_unsupported_error_message(c)[..],
            ))
        }
    };

    Ok(sizes)
}

#[cfg(test)]
mod tests {
    use super::super::BMPDecoder;
    use super::BMPEncoder;
    use color::ColorType;
    use image::ImageDecoder;
    use std::io::Cursor;

    fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec<u8> {
        let mut encoded_data = Vec::new();
        {
            let mut encoder = BMPEncoder::new(&mut encoded_data);
            encoder
                .encode(&image, width, height, c)
                .expect("could not encode image");
        }

        let decoder = BMPDecoder::new(Cursor::new(&encoded_data)).expect("failed to decode");
        decoder.read_image().expect("failed to decode")
    }

    #[test]
    fn round_trip_single_pixel_rgb() {
        let image = [255u8, 0, 0]; // single red pixel
        let decoded = round_trip_image(&image, 1, 1, ColorType::RGB(8));
        assert_eq!(3, decoded.len());
        assert_eq!(255, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
    }

    #[test]
    fn round_trip_single_pixel_rgba() {
        let image = [1, 2, 3, 4];
        let decoded = round_trip_image(&image, 1, 1, ColorType::RGBA(8));
        assert_eq!(&decoded[..], &image[..]);
    }

    #[test]
    fn round_trip_3px_rgb() {
        let image = [0u8; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel
        let _decoded = round_trip_image(&image, 3, 3, ColorType::RGB(8));
    }

    #[test]
    fn round_trip_gray() {
        let image = [0u8, 1, 2]; // 3 pixels
        let decoded = round_trip_image(&image, 3, 1, ColorType::Gray(8));
        // should be read back as 3 RGB pixels
        assert_eq!(9, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
        assert_eq!(1, decoded[3]);
        assert_eq!(1, decoded[4]);
        assert_eq!(1, decoded[5]);
        assert_eq!(2, decoded[6]);
        assert_eq!(2, decoded[7]);
        assert_eq!(2, decoded[8]);
    }

    #[test]
    fn round_trip_graya() {
        let image = [0u8, 0, 1, 0, 2, 0]; // 3 pixels, each with an alpha channel
        let decoded = round_trip_image(&image, 1, 3, ColorType::GrayA(8));
        // should be read back as 3 RGB pixels
        assert_eq!(9, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
        assert_eq!(1, decoded[3]);
        assert_eq!(1, decoded[4]);
        assert_eq!(1, decoded[5]);
        assert_eq!(2, decoded[6]);
        assert_eq!(2, decoded[7]);
        assert_eq!(2, decoded[8]);
    }
}
<|endoftext|>


<commit_before>use crate::cli::valid_fully_qualified_ident;
use configopt::{self,
                ConfigOpt};
use habitat_common::types::ListenCtlAddr;
use habitat_core::{crypto::CACHE_KEY_PATH_ENV_VAR,
                   fs as hab_core_fs,
                   package::PackageIdent};
use lazy_static::lazy_static;
use std::{fmt,
          io,
          net::{SocketAddr,
                ToSocketAddrs},
          num::ParseIntError,
          path::PathBuf,
          str::FromStr,
          time::Duration};
use structopt::StructOpt;
use url::Url;

#[derive(ConfigOpt, StructOpt)]
#[structopt(no_version)]
#[allow(dead_code)]
pub struct AuthToken {
    /// Authentication token for Builder
    #[structopt(name = "AUTH_TOKEN", short = "z", long = "auth")]
    auth_token: Option<String>,
}

#[derive(ConfigOpt, StructOpt, Deserialize)]
#[structopt(no_version)]
#[allow(dead_code)]
pub struct BldrUrl {
    /// Specify an alternate Builder endpoint. If not specified, the value will be taken from
    /// the HAB_BLDR_URL environment variable if defined. (default: https://bldr.habitat.sh)
    // TODO (DM): This should probably use `env` and `default_value`
    #[structopt(name = "BLDR_URL", short = "u", long = "url")]
    bldr_url: Option<Url>,
}

lazy_static! {
    pub static ref CACHE_KEY_PATH_DEFAULT: String =
        hab_core_fs::CACHE_KEY_PATH.to_string_lossy().to_string();
}

#[derive(ConfigOpt, StructOpt, Debug, Deserialize)]
#[configopt(derive(Debug), attrs(serde))]
#[serde(deny_unknown_fields)]
#[structopt(no_version, rename_all = "screamingsnake")]
pub struct CacheKeyPath {
    /// Cache for creating and searching for encryption keys
    #[structopt(long = "cache-key-path",
                env = CACHE_KEY_PATH_ENV_VAR,
                default_value = &*CACHE_KEY_PATH_DEFAULT)]
    pub cache_key_path: PathBuf,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(try_from = "&str", into = "String")]
struct PkgIdentStringySerde(PackageIdent);

impl FromStr for PkgIdentStringySerde {
    type Err = habitat_core::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> { Ok(Self(s.parse()?)) }
}

impl std::convert::TryFrom<&str> for PkgIdentStringySerde {
    type Error = habitat_core::Error;

    fn try_from(s: &str) -> Result<Self, Self::Error> { Self::from_str(s) }
}

impl std::fmt::Display for PkgIdentStringySerde {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.0) }
}

impl From<PkgIdentStringySerde> for String {
    fn from(pkg_ident: PkgIdentStringySerde) -> Self { pkg_ident.to_string() }
}

#[derive(Clone, ConfigOpt, Debug, StructOpt, Deserialize, Serialize)]
#[configopt(derive(Clone, Serialize, Debug), attrs(serde))]
#[structopt(no_version)]
#[serde(transparent)]
pub struct PkgIdent {
    /// A package identifier (ex: core/redis, core/busybox-static/1.42.2)
    #[structopt(name = "PKG_IDENT")]
    pkg_ident: PkgIdentStringySerde,
}

impl PkgIdent {
    pub fn pkg_ident(self) -> PackageIdent { self.pkg_ident.0 }
}

#[derive(ConfigOpt, StructOpt)]
#[structopt(no_version)]
#[allow(dead_code)]
pub struct FullyQualifiedPkgIdent {
    /// A fully qualified package identifier (ex: core/busybox-static/1.42.2/20170513215502)
    #[structopt(name = "PKG_IDENT", validator = valid_fully_qualified_ident)]
    pkg_ident: PackageIdent,
}

#[derive(ConfigOpt, StructOpt, Deserialize, Debug)]
#[configopt(derive(Clone, Debug))]
#[structopt(no_version)]
pub struct RemoteSup {
    /// Address to a remote Supervisor's Control Gateway
    #[structopt(name = "REMOTE_SUP",
                long = "remote-sup",
                short = "r",
                default_value = ListenCtlAddr::default_as_str())]
    #[serde(default)]
    remote_sup: ListenCtlAddr,
}

impl RemoteSup {
    pub fn to_listen_ctl_addr(&self) -> ListenCtlAddr { self.remote_sup }
}

pub fn socket_addr_with_default_port<S: AsRef<str>>(addr: S,
                                                    default_port: u16)
                                                    -> io::Result<SocketAddr> {
    let addr = addr.as_ref();
    let mut iter = if addr.find(':').is_some() {
        addr.to_socket_addrs()
    } else {
        (addr, default_port).to_socket_addrs()
    }?;
    // We expect exactly one address
    iter.next().ok_or_else(|| {
                   io::Error::new(io::ErrorKind::InvalidInput,
                                  "input did not resolve to SocketAddr or error")
               })
}

pub fn socket_addrs_with_default_port<I>(addrs: I, default_port: u16) -> io::Result<Vec<SocketAddr>>
    where I: IntoIterator,
          I::Item: AsRef<str>
{
    addrs.into_iter()
         .map(|a| socket_addr_with_default_port(a, default_port))
         .collect()
}

#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(from = "u64", into = "u64")]
pub struct DurationProxy(Duration);

impl From<DurationProxy> for u64 {
    fn from(d: DurationProxy) -> Self { d.0.as_secs() }
}

impl From<u64> for DurationProxy {
    fn from(n: u64) -> Self { Self(Duration::from_secs(n)) }
}

impl From<DurationProxy> for Duration {
    fn from(d: DurationProxy) -> Self { d.0 }
}

impl From<Duration> for DurationProxy {
    fn from(d: Duration) -> Self { Self(d) }
}

impl FromStr for DurationProxy {
    type Err = ParseIntError;

    fn from_str(s: &str) -> Result<Self, Self::Err> { Ok(s.parse::<u64>()?.into()) }
}

impl fmt::Display for DurationProxy {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", u64::from(*self)) }
}

#[cfg(test)]
mod test {
    use super::{socket_addr_with_default_port,
                socket_addrs_with_default_port};

    #[test]
    fn test_socket_addrs_with_default_port() {
        assert_eq!(socket_addr_with_default_port("127.0.0.1", 89).unwrap(),
                   "127.0.0.1:89".parse().expect(""));
        assert_eq!(socket_addr_with_default_port("1.2.3.4:1500", 89).unwrap(),
                   "1.2.3.4:1500".parse().expect(""));
        assert!(socket_addr_with_default_port("an_invalid_address", 89).is_err());

        let expected = vec!["1.2.3.4:1500".parse().expect(""),
                            "0.0.0.0:5567".parse().expect(""),
                            "127.0.0.1:5567".parse().expect("")];
        assert_eq!(socket_addrs_with_default_port(&["1.2.3.4:1500", "0.0.0.0", "127.0.0.1"], 5567).unwrap(),
                   expected);
        assert!(socket_addrs_with_default_port(&["1.2.3.4:1500",
                                                 "0.0.0.0",
                                                 "an_error",
                                                 "127.0.0.1"],
                                               5567).is_err(),);
    }
}
<commit_msg>[FIX] Ensure --remote-sup option is parsed properly<commit_after>use crate::cli::valid_fully_qualified_ident;
use configopt::{self,
                ConfigOpt};
use habitat_common::types::ListenCtlAddr;
use habitat_core::{crypto::CACHE_KEY_PATH_ENV_VAR,
                   fs as hab_core_fs,
                   package::PackageIdent};
use lazy_static::lazy_static;
use std::{fmt,
          io,
          net::{SocketAddr,
                ToSocketAddrs},
          num::ParseIntError,
          path::PathBuf,
          str::FromStr,
          time::Duration};
use structopt::StructOpt;
use url::Url;

#[derive(ConfigOpt, StructOpt)]
#[structopt(no_version)]
#[allow(dead_code)]
pub struct AuthToken {
    /// Authentication token for Builder
    #[structopt(name = "AUTH_TOKEN", short = "z", long = "auth")]
    auth_token: Option<String>,
}

#[derive(ConfigOpt, StructOpt, Deserialize)]
#[structopt(no_version)]
#[allow(dead_code)]
pub struct BldrUrl {
    /// Specify an alternate Builder endpoint. If not specified, the value will be taken from
    /// the HAB_BLDR_URL environment variable if defined. (default: https://bldr.habitat.sh)
    // TODO (DM): This should probably use `env` and `default_value`
    #[structopt(name = "BLDR_URL", short = "u", long = "url")]
    bldr_url: Option<Url>,
}

lazy_static! {
    pub static ref CACHE_KEY_PATH_DEFAULT: String =
        hab_core_fs::CACHE_KEY_PATH.to_string_lossy().to_string();
}

#[derive(ConfigOpt, StructOpt, Debug, Deserialize)]
#[configopt(derive(Debug), attrs(serde))]
#[serde(deny_unknown_fields)]
#[structopt(no_version, rename_all = "screamingsnake")]
pub struct CacheKeyPath {
    /// Cache for creating and searching for encryption keys
    #[structopt(long = "cache-key-path",
                env = CACHE_KEY_PATH_ENV_VAR,
                default_value = &*CACHE_KEY_PATH_DEFAULT)]
    pub cache_key_path: PathBuf,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(try_from = "&str", into = "String")]
struct PkgIdentStringySerde(PackageIdent);

impl FromStr for PkgIdentStringySerde {
    type Err = habitat_core::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> { Ok(Self(s.parse()?)) }
}

impl std::convert::TryFrom<&str> for PkgIdentStringySerde {
    type Error = habitat_core::Error;

    fn try_from(s: &str) -> Result<Self, Self::Error> { Self::from_str(s) }
}

impl std::fmt::Display for PkgIdentStringySerde {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.0) }
}

impl From<PkgIdentStringySerde> for String {
    fn from(pkg_ident: PkgIdentStringySerde) -> Self { pkg_ident.to_string() }
}

#[derive(Clone, ConfigOpt, Debug, StructOpt, Deserialize, Serialize)]
#[configopt(derive(Clone, Serialize, Debug), attrs(serde))]
#[structopt(no_version)]
#[serde(transparent)]
pub struct PkgIdent {
    /// A package identifier (ex: core/redis, core/busybox-static/1.42.2)
    #[structopt(name = "PKG_IDENT")]
    pkg_ident: PkgIdentStringySerde,
}

impl PkgIdent {
    pub fn pkg_ident(self) -> PackageIdent { self.pkg_ident.0 }
}

#[derive(ConfigOpt, StructOpt)]
#[structopt(no_version)]
#[allow(dead_code)]
pub struct FullyQualifiedPkgIdent {
    /// A fully qualified package identifier (ex: core/busybox-static/1.42.2/20170513215502)
    #[structopt(name = "PKG_IDENT", validator = valid_fully_qualified_ident)]
    pkg_ident: PackageIdent,
}

#[derive(ConfigOpt, StructOpt, Deserialize, Debug)]
#[configopt(derive(Clone, Debug))]
#[structopt(no_version)]
pub struct RemoteSup {
    /// Address to a remote Supervisor's Control Gateway
    #[structopt(name = "REMOTE_SUP",
                long = "remote-sup",
                short = "r",
                default_value = ListenCtlAddr::default_as_str(),
                parse(try_from_str = ListenCtlAddr::resolve_listen_ctl_addr))]
    #[serde(default)]
    remote_sup: ListenCtlAddr,
}

impl RemoteSup {
    pub fn to_listen_ctl_addr(&self) -> ListenCtlAddr { self.remote_sup }
}

pub fn socket_addr_with_default_port<S: AsRef<str>>(addr: S,
                                                    default_port: u16)
                                                    -> io::Result<SocketAddr> {
    let addr = addr.as_ref();
    let mut iter = if addr.find(':').is_some() {
        addr.to_socket_addrs()
    } else {
        (addr, default_port).to_socket_addrs()
    }?;
    // We expect exactly one address
    iter.next().ok_or_else(|| {
                   io::Error::new(io::ErrorKind::InvalidInput,
                                  "input did not resolve to SocketAddr or error")
               })
}

pub fn socket_addrs_with_default_port<I>(addrs: I, default_port: u16) -> io::Result<Vec<SocketAddr>>
    where I: IntoIterator,
          I::Item: AsRef<str>
{
    addrs.into_iter()
         .map(|a| socket_addr_with_default_port(a, default_port))
         .collect()
}

#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(from = "u64", into = "u64")]
pub struct DurationProxy(Duration);

impl From<DurationProxy> for u64 {
    fn from(d: DurationProxy) -> Self { d.0.as_secs() }
}

impl From<u64> for DurationProxy {
    fn from(n: u64) -> Self { Self(Duration::from_secs(n)) }
}

impl From<DurationProxy> for Duration {
    fn from(d: DurationProxy) -> Self { d.0 }
}

impl From<Duration> for DurationProxy {
    fn from(d: Duration) -> Self { Self(d) }
}

impl FromStr for DurationProxy {
    type Err = ParseIntError;

    fn from_str(s: &str) -> Result<Self, Self::Err> { Ok(s.parse::<u64>()?.into()) }
}

impl fmt::Display for DurationProxy {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", u64::from(*self)) }
}

#[cfg(test)]
mod test {
    use super::{socket_addr_with_default_port,
                socket_addrs_with_default_port};

    #[test]
    fn test_socket_addrs_with_default_port() {
        assert_eq!(socket_addr_with_default_port("127.0.0.1", 89).unwrap(),
                   "127.0.0.1:89".parse().expect(""));
        assert_eq!(socket_addr_with_default_port("1.2.3.4:1500", 89).unwrap(),
                   "1.2.3.4:1500".parse().expect(""));
        assert!(socket_addr_with_default_port("an_invalid_address", 89).is_err());

        let expected = vec!["1.2.3.4:1500".parse().expect(""),
                            "0.0.0.0:5567".parse().expect(""),
                            "127.0.0.1:5567".parse().expect("")];
        assert_eq!(socket_addrs_with_default_port(&["1.2.3.4:1500", "0.0.0.0", "127.0.0.1"], 5567).unwrap(),
                   expected);
        assert!(socket_addrs_with_default_port(&["1.2.3.4:1500",
                                                 "0.0.0.0",
                                                 "an_error",
                                                 "127.0.0.1"],
                                               5567).is_err(),);
    }
}
<|endoftext|>


<commit_before>//! This module defines the metadata on devices and services.
//!
//! Note that all the data structures in this module represent
//! snapshots of subsets of the devices available. None of these data
//! structures are live, so there is always the possibility that
//! devices may have been added or removed from the FoxBox by the time
//! these data structures are read.

use values::*;

use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error};

/// The unique Id of a node on the network.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Hash, Eq)]
pub struct NodeId(String);
impl NodeId {
    pub fn new(id: String) -> Self {
        NodeId(id)
    }
    pub fn as_string(&self) -> &String {
        &self.0
    }
}

/// Metadata on a node. A node is a device or collection of devices
/// that may offer services. The FoxBox itself a node offering
/// services such as a clock, communication with the user through her
/// smart devices, etc.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Node {
    /// Tags describing the node.
    ///
    /// These tags can be set by the user, adapters or
    /// applications. They are used by applications to find nodes and
    /// services.
    ///
    /// For instance, a user may set tag "entrance" to all nodes
    /// placed in the entrance of his house, or a tag "blue" to a node
    /// controlling blue lights. An adapter may set tags "plugged" or
    /// "battery" to devices that respectively depend on a plugged
    /// power source or on a battery.
    pub tags: Vec<String>,

    /// An id unique to this node.
    pub id: NodeId,

    /// Services connected directly to this node.
    pub inputs: Vec<Service<Input>>,
    pub outputs: Vec<Service<Output>>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

/// The unique Id of a service on the network.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Hash, Eq)]
pub struct ServiceId(String);
impl ServiceId {
    pub fn new(id: String) -> Self {
        ServiceId(id)
    }
    pub fn as_string(&self) -> &String {
        &self.0
    }
}

/// The kind of the service, i.e. a strongly-typed description of
/// _what_ the service can do. Used both for locating services
/// (e.g. "I need a clock" or "I need something that can provide
/// pictures") and for determining the data structure that these
/// services can provide or consume.
///
/// A number of service kinds are standardized, and provided as a set
/// of strongly-typed enum constructors. It is clear, however, that
/// many devices will offer services that cannot be described by
/// pre-existing constructors. For this purpose, this enumeration
/// offers a constructor `Extension`, designed to describe novel
/// services.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ServiceKind {
    ///
    /// # No payload
    ///

    /// The service is ready. Used for instance once a countdown has
    /// reached completion.
    Ready,

    ///
    /// # Boolean
    ///

    /// The service is used to detect or decide whether some device
    /// is on or off.
    OnOff,

    /// The service is used to detect or decide whether some device
    /// is open or closed.
    OpenClosed,

    ///
    /// # Time
    ///

    /// The service is used to read or set the current absolute time.
    /// Used for instance to wait until a specific time and day before
    /// triggering an action, or to set the appropriate time on a new
    /// device.
    CurrentTime,

    /// The service is used to read or set the current time of day.
    /// Used for instance to trigger an action at a specific hour
    /// every day.
    CurrentTimeOfDay,

    /// The service is part of a countdown. This is the time
    /// remaining until the countdown is elapsed.
    RemainingTime,

    ///
    /// # Temperature
    ///

    Thermostat,
    ActualTemperature,

    /// TODO: Add more

    /// An operation of a kind that has not been standardized yet.
    Extension {
        /// The vendor. Used for namespacing purposes, to avoid
        /// confusing two incompatible extensions with similar
        /// names. For instance, "foxlink@mozilla.com".
        vendor: String,

        /// Identification of the adapter introducing this operation.
        /// Designed to aid with tracing and debugging.
        adapter: String,

        /// A string describing the nature of the value, designed to
        /// let applications discover the devices.
        ///
        /// Examples: `"GroundHumidity"`.
        kind: String,

        /// The data type of the value.
        typ: Type
    }
}

impl ServiceKind {
    /// Get the type of values used to communicate with this service.
    pub fn get_type(&self) -> Type {
        use self::ServiceKind::*;
        use values::Type::*;
        match *self {
            Ready => Unit,
            OnOff | OpenClosed => Bool,
            CurrentTime => TimeStamp,
            CurrentTimeOfDay | RemainingTime => Duration,
            Thermostat | ActualTemperature => Temperature,
            Extension { ref typ, ..} => typ.clone(),
        }
    }
}

/// An input operation available on an service.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Input {
    /// The kind of value that can be obtained from this service.
    pub kind: ServiceKind,

    /// If `Some(duration)`, this service can be polled, i.e. it
    /// will respond when the FoxBox requests the latest value.
    /// Parameter `duration` indicates the smallest interval
    /// between two updates.
    ///
    /// Otherwise, the service cannot be polled and will push
    /// data to the FoxBox when it is available.
    ///
    /// # Examples
    ///
    /// - Long-running pollution or humidity sensors typically
    ///   do not accept requests and rather send batches of
    ///   data every 24h.
    #[serde(default)]
    pub poll: Option<ValDuration>,

    /// If `Some(duration)`, this service can send the data to
    /// the FoxBox whenever it is updated. Parameter `duration`
    /// indicates the smallest interval between two updates.
    ///
    /// Otherwise, the service cannot send data to the FoxBox
    /// and needs to be polled.
    #[serde(default)]
    pub trigger: Option<ValDuration>,

    /// Date at which the latest value was received, whether through
    /// polling or through a trigger.
    pub updated: TimeStamp,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}
impl IOMechanism for Input {
}

/// An output operation available on an service.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Output {
    /// The kind of value that can be sent to this service.
    pub kind: ServiceKind,

    /// If `Some(duration)`, this service supports pushing,
    /// i.e. the FoxBox can send values.
    #[serde(default)]
    pub push: Option<ValDuration>,

    /// Date at which the latest value was sent to the service.
    pub updated: TimeStamp,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}
impl IOMechanism for Output {
}

/// An service represents a single place where data can enter or
/// leave a device. Note that services support either a single kind
/// of input or a single kind of output. Devices that support both
/// inputs or outputs, or several kinds of inputs, or several kinds of
/// outputs, are represented as nodes containing several services.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Service<IO> where IO: IOMechanism {
    /// Tags describing the service.
    ///
    /// These tags can be set by the user, adapters or
    /// applications. They are used to regroup services for rules.
    ///
    /// For instance "entrance".
    #[serde(default)]
    pub tags: Vec<String>,

    /// An id unique to this service.
    pub id: ServiceId,

    /// The node owning this service.
    pub node: NodeId,

    /// The update mechanism for this service.
    pub mechanism: IO,

    /// The last time the device was seen.
    pub last_seen: TimeStamp,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

/// A mechanism used for communicating between the application and the
/// service.
pub trait IOMechanism: Deserialize + Serialize {
}

<commit_msg>[fxbox/taxonomy] Updated and last_seen are now optional<commit_after>//! This module defines the metadata on devices and services.
//!
//! Note that all the data structures in this module represent
//! snapshots of subsets of the devices available. None of these data
//! structures are live, so there is always the possibility that
//! devices may have been added or removed from the FoxBox by the time
//! these data structures are read.

use values::*;

use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error};

/// The unique Id of a node on the network.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Hash, Eq)]
pub struct NodeId(String);
impl NodeId {
    pub fn new(id: String) -> Self {
        NodeId(id)
    }
    pub fn as_string(&self) -> &String {
        &self.0
    }
}

/// Metadata on a node. A node is a device or collection of devices
/// that may offer services. The FoxBox itself a node offering
/// services such as a clock, communication with the user through her
/// smart devices, etc.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Node {
    /// Tags describing the node.
    ///
    /// These tags can be set by the user, adapters or
    /// applications. They are used by applications to find nodes and
    /// services.
    ///
    /// For instance, a user may set tag "entrance" to all nodes
    /// placed in the entrance of his house, or a tag "blue" to a node
    /// controlling blue lights. An adapter may set tags "plugged" or
    /// "battery" to devices that respectively depend on a plugged
    /// power source or on a battery.
    pub tags: Vec<String>,

    /// An id unique to this node.
    pub id: NodeId,

    /// Services connected directly to this node.
    pub inputs: Vec<Service<Input>>,
    pub outputs: Vec<Service<Output>>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

/// The unique Id of a service on the network.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Hash, Eq)]
pub struct ServiceId(String);
impl ServiceId {
    pub fn new(id: String) -> Self {
        ServiceId(id)
    }
    pub fn as_string(&self) -> &String {
        &self.0
    }
}

/// The kind of the service, i.e. a strongly-typed description of
/// _what_ the service can do. Used both for locating services
/// (e.g. "I need a clock" or "I need something that can provide
/// pictures") and for determining the data structure that these
/// services can provide or consume.
///
/// A number of service kinds are standardized, and provided as a set
/// of strongly-typed enum constructors. It is clear, however, that
/// many devices will offer services that cannot be described by
/// pre-existing constructors. For this purpose, this enumeration
/// offers a constructor `Extension`, designed to describe novel
/// services.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ServiceKind {
    ///
    /// # No payload
    ///

    /// The service is ready. Used for instance once a countdown has
    /// reached completion.
    Ready,

    ///
    /// # Boolean
    ///

    /// The service is used to detect or decide whether some device
    /// is on or off.
    OnOff,

    /// The service is used to detect or decide whether some device
    /// is open or closed.
    OpenClosed,

    ///
    /// # Time
    ///

    /// The service is used to read or set the current absolute time.
    /// Used for instance to wait until a specific time and day before
    /// triggering an action, or to set the appropriate time on a new
    /// device.
    CurrentTime,

    /// The service is used to read or set the current time of day.
    /// Used for instance to trigger an action at a specific hour
    /// every day.
    CurrentTimeOfDay,

    /// The service is part of a countdown. This is the time
    /// remaining until the countdown is elapsed.
    RemainingTime,

    ///
    /// # Temperature
    ///

    Thermostat,
    ActualTemperature,

    /// TODO: Add more

    /// An operation of a kind that has not been standardized yet.
    Extension {
        /// The vendor. Used for namespacing purposes, to avoid
        /// confusing two incompatible extensions with similar
        /// names. For instance, "foxlink@mozilla.com".
        vendor: String,

        /// Identification of the adapter introducing this operation.
        /// Designed to aid with tracing and debugging.
        adapter: String,

        /// A string describing the nature of the value, designed to
        /// let applications discover the devices.
        ///
        /// Examples: `"GroundHumidity"`.
        kind: String,

        /// The data type of the value.
        typ: Type
    }
}

impl ServiceKind {
    /// Get the type of values used to communicate with this service.
    pub fn get_type(&self) -> Type {
        use self::ServiceKind::*;
        use values::Type::*;
        match *self {
            Ready => Unit,
            OnOff | OpenClosed => Bool,
            CurrentTime => TimeStamp,
            CurrentTimeOfDay | RemainingTime => Duration,
            Thermostat | ActualTemperature => Temperature,
            Extension { ref typ, ..} => typ.clone(),
        }
    }
}

/// An input operation available on an service.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Input {
    /// The kind of value that can be obtained from this service.
    pub kind: ServiceKind,

    /// If `Some(duration)`, this service can be polled, i.e. it
    /// will respond when the FoxBox requests the latest value.
    /// Parameter `duration` indicates the smallest interval
    /// between two updates.
    ///
    /// Otherwise, the service cannot be polled and will push
    /// data to the FoxBox when it is available.
    ///
    /// # Examples
    ///
    /// - Long-running pollution or humidity sensors typically
    ///   do not accept requests and rather send batches of
    ///   data every 24h.
    #[serde(default)]
    pub poll: Option<ValDuration>,

    /// If `Some(duration)`, this service can send the data to
    /// the FoxBox whenever it is updated. Parameter `duration`
    /// indicates the smallest interval between two updates.
    ///
    /// Otherwise, the service cannot send data to the FoxBox
    /// and needs to be polled.
    #[serde(default)]
    pub trigger: Option<ValDuration>,

    /// Date at which the latest value was received, whether through
    /// polling or through a trigger.
    pub updated: Option<TimeStamp>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}
impl IOMechanism for Input {
}

/// An output operation available on an service.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Output {
    /// The kind of value that can be sent to this service.
    pub kind: ServiceKind,

    /// If `Some(duration)`, this service supports pushing,
    /// i.e. the FoxBox can send values.
    #[serde(default)]
    pub push: Option<ValDuration>,

    /// Date at which the latest value was sent to the service.
    #[serde(default)]
    pub updated: Option<TimeStamp>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}
impl IOMechanism for Output {
}

/// An service represents a single place where data can enter or
/// leave a device. Note that services support either a single kind
/// of input or a single kind of output. Devices that support both
/// inputs or outputs, or several kinds of inputs, or several kinds of
/// outputs, are represented as nodes containing several services.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Service<IO> where IO: IOMechanism {
    /// Tags describing the service.
    ///
    /// These tags can be set by the user, adapters or
    /// applications. They are used to regroup services for rules.
    ///
    /// For instance "entrance".
    #[serde(default)]
    pub tags: Vec<String>,

    /// An id unique to this service.
    pub id: ServiceId,

    /// The node owning this service.
    pub node: NodeId,

    /// The update mechanism for this service.
    pub mechanism: IO,

    /// The last time the device was seen.
    #[serde(default)]
    pub last_seen: Option<TimeStamp>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

/// A mechanism used for communicating between the application and the
/// service.
pub trait IOMechanism: Deserialize + Serialize {
}

<|endoftext|>


<commit_before>extern crate pkg_config;

fn main() {
    pkg_config::Config::new().atleast_version("1.11.0").probe("hwloc").unwrap();
}
<commit_msg>don't fail if lib not found in pkg<commit_after>extern crate pkg_config;

fn main() {
    let probed = pkg_config::Config::new().atleast_version("1.11.0").probe("hwloc");
    if probed.is_ok() {
        return;
    }
}
<|endoftext|>


<commit_before>extern crate syntex;
extern crate serde_codegen;

use std::env;
use std::path::Path;

fn main() {
    let out_dir = env::var_os("OUT_DIR").unwrap();
    let src = Path::new("src/rep.rs.in");
    let dst = Path::new(&out_dir).join("rep.rs");

    let mut registry = syntex::Registry::new();

    serde_codegen::register(&mut registry);
    registry.expand("", &src, &dst).unwrap();
}
<commit_msg>update build<commit_after>extern crate serde_codegen;

use std::env;
use std::path::Path;

fn main() {
    let out_dir = env::var_os("OUT_DIR").unwrap();

    let src = Path::new("src/rep.rs.in");
    let dst = Path::new(&out_dir).join("rep.rs");

    serde_codegen::expand(&src, &dst).unwrap();
}
<|endoftext|>


<commit_before>extern crate gcc;

use std::fs::File;
use std::path::Path;
use std::io::Write;
use std::process::Command;
use std::env;

fn main() {
    if cfg!(target_os = "linux") || cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        env::set_var("CC", "gcc");
        env::set_var("AS", "gcc -c");
        if cfg!(target_os = "linux") {
            env::set_var("AR", "ar");
        }
    } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
        env::set_var("CC", "cc");
        env::set_var("AS", "cc -c");
        env::set_var("AR", "ar");
    }

    let sse3 = if cfg!(target_os = "windows") {
        cfg!(feature = "sse")
    } else {
        let output = if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            // /usr/bin/grep -o SSSE3 /var/run/dmesg.boot | /usr/bin/head -1
            Command::new("/usr/bin/grep")
                .arg("-o")
                .arg("SSE3")
                .arg("/var/run/dmesg.boot")
                .arg("|")
                .arg("/usr/bin/head")
                .arg("-1")
                .output()
                .unwrap()
        } else if cfg!(target_os = "macos") {
            // /usr/sbin/sysctl machdep.cpu.features | grep -m 1 -ow SSSE3
            Command::new("/usr/sbin/sysctl")
                .arg("machdep.cpu.features")
                .arg("|")
                .arg("grep")
                .arg("-m")
                .arg("1")
                .arg("-ow")
                .arg("SSSE3")
                .output()
                .unwrap()
        } else {
            // /bin/grep -m 1 -o ssse3 /proc/cpuinfo
            Command::new("/bin/grep")
                .arg("-m")
                .arg("1")
                .arg("-o")
                .arg("sse3")
                .arg("/proc/cpuinfo")
                .output()
                .unwrap()
        };
        let output = std::str::from_utf8(&output.stdout[..]).unwrap().trim();

        if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") || cfg!(target_os = "macos") {
            output == "SSSE3"
        } else {
            output == "sse3"
        }
    };

    let mut cflags = "-g -Wall -Wextra -Wno-unused-parameter".to_owned();
    if !cfg!(feature = "no-sse") && sse3 {
        cflags = cflags + " -mssse3";
    }
    if cfg!(feature = "no-sse") && cfg!(target_os = "macos") {
        cflags = cflags + " -march=x86-64";
    }
    cflags = cflags + " -O2";

    env::set_var("CFLAGS", cflags);

    let mut config = gcc::Config::new();
    config.file("src/c/src/bitstring.c")
          .file("src/c/src/encparams.c")
          .file("src/c/src/hash.c")
          .file("src/c/src/idxgen.c")
          .file("src/c/src/key.c")
          .file("src/c/src/mgf.c")
          .file("src/c/src/ntru.c")
          .file("src/c/src/poly.c")
          .file("src/c/src/rand.c")
          .file("src/c/src/arith.c")
          .file("src/c/src/sha1.c")
          .file("src/c/src/sha2.c")
          .file("src/c/src/nist_ctr_drbg.c")
          .file("src/c/src/rijndael.c")
          .file("src/c/src/rijndael-alg-fst.c");

    if sse3 &&
       (cfg!(target_pointer_width = "64") || cfg!(target_os = "macos") ||
        cfg!(target_os = "windows")) {
        let out = if cfg!(target_os = "windows") {
            Command::new("c:\\mingw\\msys\\1.0\\bin\\perl")
                .arg("src/c/src/sha1-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        } else {
            Command::new("/usr/bin/perl")
                .arg("src/c/src/sha1-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        };
        let out = std::str::from_utf8(&out.stdout[..]).unwrap().trim();

        let p = Path::new("src/c/src/sha1-mb-x86_64.s");
        let mut f = File::create(&p).unwrap();
        f.write(out.as_bytes()).unwrap();

        if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
            Command::new("gcc")
                .arg("-c")
                .arg("src/c/src/sha1-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha1-mb-x86_64.o")
                .output()
                .unwrap();
        } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            Command::new("cc")
                .arg("-c")
                .arg("src/c/src/sha1-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha1-mb-x86_64.o")
                .output()
                .unwrap();
        }

        let out = if cfg!(target_os = "windows") {
            Command::new("c:\\mingw\\msys\\1.0\\bin\\perl")
                .arg("src/c/src/sha256-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        } else {
            Command::new("/usr/bin/perl")
                .arg("src/c/src/sha256-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        };
        let out = std::str::from_utf8(&out.stdout[..]).unwrap().trim();

        let p = Path::new("src/c/src/sha256-mb-x86_64.s");
        let mut f = File::create(&p).unwrap();
        f.write(out.as_bytes()).unwrap();

        if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
            Command::new("gcc")
                .arg("-c")
                .arg("src/c/src/sha256-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha256-mb-x86_64.o")
                .output()
                .unwrap();
        } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            Command::new("cc")
                .arg("-c")
                .arg("src/c/src/sha256-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha256-mb-x86_64.o")
                .output()
                .unwrap();
        }

        config.object("src/c/src/sha1-mb-x86_64.o").object("src/c/src/sha256-mb-x86_64.o");
    }

    config.include("src/c/src").compile("libntru.a");

    if !cfg!(feature = "no-sse") && sse3 {
        println!("cargo:rustc-cfg=SSE3")
    }
}
<commit_msg>Avoiding pipes in commands<commit_after>extern crate gcc;

use std::fs::File;
use std::path::Path;
use std::io::Write;
use std::process::Command;
use std::env;

fn main() {
    if cfg!(target_os = "linux") || cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        env::set_var("CC", "gcc");
        env::set_var("AS", "gcc -c");
        if cfg!(target_os = "linux") {
            env::set_var("AR", "ar");
        }
    } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
        env::set_var("CC", "cc");
        env::set_var("AS", "cc -c");
        env::set_var("AR", "ar");
    }

    let sse3 = if cfg!(target_os = "windows") {
        cfg!(feature = "sse")
    } else {
        let output = if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            // /usr/bin/grep -o SSSE3 /var/run/dmesg.boot | /usr/bin/head -1
            Command::new("/usr/bin/grep")
                .arg("-o")
                .arg("SSE3")
                .arg("/var/run/dmesg.boot")
                .output()
                .unwrap()
        } else if cfg!(target_os = "macos") {
            // /usr/sbin/sysctl machdep.cpu.features | grep -m 1 -ow SSSE3
            Command::new("/usr/sbin/sysctl")
                .arg("machdep.cpu.features")
                .output()
                .unwrap()
        } else {
            // /bin/grep -m 1 -o ssse3 /proc/cpuinfo
            Command::new("/bin/grep")
                .arg("-m")
                .arg("1")
                .arg("-o")
                .arg("ssse3")
                .arg("/proc/cpuinfo")
                .output()
                .unwrap()
        };
        let output = std::str::from_utf8(&output.stdout[..]).unwrap().trim();

        if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") || cfg!(target_os = "macos") {
            output.contains("SSSE3")
        } else {
            output == "ssse3"
        }
    };

    let mut cflags = "-g -Wall -Wextra -Wno-unused-parameter".to_owned();
    if !cfg!(feature = "no-sse") && sse3 {
        cflags = cflags + " -mssse3";
    }
    if cfg!(feature = "no-sse") && cfg!(target_os = "macos") {
        cflags = cflags + " -march=x86-64";
    }
    cflags = cflags + " -O2";

    env::set_var("CFLAGS", cflags);

    let mut config = gcc::Config::new();
    config.file("src/c/src/bitstring.c")
          .file("src/c/src/encparams.c")
          .file("src/c/src/hash.c")
          .file("src/c/src/idxgen.c")
          .file("src/c/src/key.c")
          .file("src/c/src/mgf.c")
          .file("src/c/src/ntru.c")
          .file("src/c/src/poly.c")
          .file("src/c/src/rand.c")
          .file("src/c/src/arith.c")
          .file("src/c/src/sha1.c")
          .file("src/c/src/sha2.c")
          .file("src/c/src/nist_ctr_drbg.c")
          .file("src/c/src/rijndael.c")
          .file("src/c/src/rijndael-alg-fst.c");

    if sse3 &&
       (cfg!(target_pointer_width = "64") || cfg!(target_os = "macos") ||
        cfg!(target_os = "windows")) {
        let out = if cfg!(target_os = "windows") {
            Command::new("c:\\mingw\\msys\\1.0\\bin\\perl")
                .arg("src/c/src/sha1-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        } else {
            Command::new("/usr/bin/perl")
                .arg("src/c/src/sha1-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        };
        let out = std::str::from_utf8(&out.stdout[..]).unwrap().trim();

        let p = Path::new("src/c/src/sha1-mb-x86_64.s");
        let mut f = File::create(&p).unwrap();
        f.write(out.as_bytes()).unwrap();

        if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
            Command::new("gcc")
                .arg("-c")
                .arg("src/c/src/sha1-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha1-mb-x86_64.o")
                .output()
                .unwrap();
        } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            Command::new("cc")
                .arg("-c")
                .arg("src/c/src/sha1-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha1-mb-x86_64.o")
                .output()
                .unwrap();
        }

        let out = if cfg!(target_os = "windows") {
            Command::new("c:\\mingw\\msys\\1.0\\bin\\perl")
                .arg("src/c/src/sha256-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        } else {
            Command::new("/usr/bin/perl")
                .arg("src/c/src/sha256-mb-x86_64.pl")
                .arg("elf")
                .output()
                .unwrap()
        };
        let out = std::str::from_utf8(&out.stdout[..]).unwrap().trim();

        let p = Path::new("src/c/src/sha256-mb-x86_64.s");
        let mut f = File::create(&p).unwrap();
        f.write(out.as_bytes()).unwrap();

        if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
            Command::new("gcc")
                .arg("-c")
                .arg("src/c/src/sha256-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha256-mb-x86_64.o")
                .output()
                .unwrap();
        } else if cfg!(target_os = "freebsd") || cfg!(target_os = "openbsd") {
            Command::new("cc")
                .arg("-c")
                .arg("src/c/src/sha256-mb-x86_64.s")
                .arg("-o")
                .arg("src/c/src/sha256-mb-x86_64.o")
                .output()
                .unwrap();
        }

        config.object("src/c/src/sha1-mb-x86_64.o").object("src/c/src/sha256-mb-x86_64.o");
    }

    config.include("src/c/src").compile("libntru.a");

    if !cfg!(feature = "no-sse") && sse3 {
        println!("cargo:rustc-cfg=SSE3")
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::path::PathBuf;
use std::process::Command;
extern crate bindgen;
extern crate gcc;

fn main() {

    Command::new("git")
        .args(&["clone", "https://github.com/potassco/clingo.git"])
        .status()
        .unwrap();

    Command::new("git")
        .args(&["checkout", "tags/v5.0.0"])
        .status()
        .unwrap();

    gcc::Config::new()
        .cpp(true)
        .define("NDEBUG", Some("1"))
        .file("clingo/libgringo/src/control.cc")
        .file("clingo/libgringo/src/term.cc")
        .file("clingo/libgringo/src/symbol.cc")
        .file("clingo/libgringo/src/primes.cc")
        .file("clingo/libgringo/src/backend.cc")
        .file("clingo/libgringo/src/lua.cc")
        .file("clingo/libgringo/src/scripts.cc")
        .file("clingo/libgringo/src/python.cc")
        .file("clingo/libgringo/src/terms.cc")
        .file("clingo/libgringo/src/ground/statements.cc")
        .file("clingo/libgringo/src/ground/literals.cc")
        .file("clingo/libgringo/src/ground/instantiation.cc")
        .file("clingo/libgringo/src/input/groundtermparser.cc")
        .file("generated/input/nongroundgrammar/grammar.cc")
        .file("generated/input/groundtermgrammar/grammar.cc")
        .file("clingo/libgringo/src/input/nongroundparser.cc")
        .file("clingo/libgringo/src/input/aggregate.cc")
        .file("clingo/libgringo/src/input/aggregates.cc")
        .file("clingo/libgringo/src/input/program.cc")
        .file("clingo/libgringo/src/ground/program.cc")
        .file("clingo/libgringo/src/input/programbuilder.cc")
        .file("clingo/libgringo/src/input/literals.cc")
        .file("clingo/libgringo/src/input/statement.cc")
        .file("clingo/libgringo/src/input/literal.cc")
        .file("clingo/libgringo/src/input/theory.cc")
        .file("clingo/libgringo/src/output/statements.cc")
        .file("clingo/libgringo/src/output/literals.cc")
        .file("clingo/libgringo/src/output/aggregates.cc")
        .file("clingo/libgringo/src/output/output.cc")
        .file("clingo/libgringo/src/output/statement.cc")
        .file("clingo/libgringo/src/output/literal.cc")
        .file("clingo/libgringo/src/output/theory.cc")
        .include("clingo/libgringo")
        .include("generated")
        .include("clingo/liblp")
        .include("clingo/libreify")
        .compile("libgringo.a");

    gcc::Config::new()
        .cpp(true)
        .define("NDEBUG", Some("1"))
        .file("clingo/libprogram_opts/src/application.cpp")
        .file("clingo/libprogram_opts/src/alarm.cpp")
        .file("clingo/libprogram_opts/src/program_options.cpp")
        .file("clingo/libprogram_opts/src/string_convert.cpp")
        .file("clingo/libprogram_opts/src/value_store.cpp")
        .include("clingo/libprogram_opts")
        .compile("libprogram_opts.a");

    gcc::Config::new()
        .cpp(true)
        .define("NDEBUG", Some("1"))
        .file("clingo/libreify/src/program.cc")
        .include("clingo/libreify")
        .include("clingo/liblp")
        .include("clingo/libgringo")
        .compile("libreify.a");

    gcc::Config::new()
        .cpp(true)
        .define("NDEBUG", Some("1"))
        .file("clingo/liblp/src/aspif.cpp")
        .file("clingo/liblp/src/clingo.cpp")
        .file("clingo/liblp/src/theory_data.cpp")
        .file("clingo/liblp/src/smodels.cpp")
        .file("clingo/liblp/src/convert.cpp")
        .file("clingo/liblp/src/rule_utils.cpp")
        .file("clingo/liblp/src/match_basic_types.cpp")
        .file("clingo/liblp/src/aspif_text.cpp")
        .include("clingo/liblp")
        .compile("liblp.a");

    gcc::Config::new()
        .cpp(true)
        .define("NDEBUG", Some("1"))
        .define("WITH_THREADS", Some("0"))
        .file("clingo/libclingo/src/clingocontrol.cc")
        .include("clingo/libclingo")
        .include("clingo/libgringo")
        .include("clingo/liblp")
        .include("clingo/libclasp")
        .include("clingo/libprogram_opts")
        .compile("libclingo.a");

    gcc::Config::new()
        .cpp(true)
        .define("NDEBUG", Some("1"))
        .define("WITH_THREADS", Some("0"))
        .file("clingo/libclasp/src/parallel_solve.cpp")
        .file("clingo/libclasp/src/solver_types.cpp")
        .file("clingo/libclasp/src/solver_strategies.cpp")
        .file("clingo/libclasp/src/clause.cpp")
        .file("clingo/libclasp/src/logic_program.cpp")
        .file("clingo/libclasp/src/clasp_facade.cpp")
        .file("clingo/libclasp/src/cb_enumerator.cpp")
        .file("clingo/libclasp/src/minimize_constraint.cpp")
        .file("clingo/libclasp/src/clingo.cpp")
        .file("clingo/libclasp/src/shared_context.cpp")
        .file("clingo/libclasp/src/dependency_graph.cpp")
        .file("clingo/libclasp/src/logic_program_types.cpp")
        .file("clingo/libclasp/src/asp_preprocessor.cpp")
        .file("clingo/libclasp/src/clasp_options.cpp")
        .file("clingo/libclasp/src/heuristics.cpp")
        .file("clingo/libclasp/src/timer.cpp")
        .file("clingo/libclasp/src/lookahead.cpp")
        .file("clingo/libclasp/src/constraint.cpp")
        .file("clingo/libclasp/src/unfounded_check.cpp")
        .file("clingo/libclasp/src/solver.cpp")
        .file("clingo/libclasp/src/model_enumerators.cpp")
        .file("clingo/libclasp/src/clasp_output.cpp")
        .file("clingo/libclasp/src/parser.cpp")
        .file("clingo/libclasp/src/solve_algorithms.cpp")
        .file("clingo/libclasp/src/enumerator.cpp")
        .file("clingo/libclasp/src/program_builder.cpp")
        .file("clingo/libclasp/src/satelite.cpp")
        .file("clingo/libclasp/src/statistics.cpp")
        .file("clingo/libclasp/src/weight_constraint.cpp")
        .include("clingo/libclasp")
        .include("clingo/libclingo")
        .include("clingo/liblp")
        .include("clingo/libprogram_opts")
        .compile("libclasp.a");

    println!("cargo:rustc-link-lib=clingo");

    let out_dir = env::var("OUT_DIR").unwrap();

    let bindings = bindgen::builder()
        .no_unstable_rust()
        .header("clingo/libgringo/clingo.h")
        .use_core()
        .generate()
        .expect("Unable to generate bindings");

    let out_path = PathBuf::from(out_dir);

    bindings.write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");

}
<commit_msg>Download clingo from github<commit_after>use std::env;
use std::path::PathBuf;
use std::process::Command;
extern crate bindgen;
extern crate gcc;

fn main() {

    Command::new("git")
        .args(&["clone", "https://github.com/potassco/clingo.git"])
        .status()
        .unwrap();

    Command::new("git")
        .args(&["checkout", "tags/v5.0.0"])
        .current_dir("./clingo")
        .status()
        .unwrap();

    gcc::Config::new()
        .cpp(true)
        .define("NDEBUG", Some("1"))
        .file("clingo/libgringo/src/control.cc")
        .file("clingo/libgringo/src/term.cc")
        .file("clingo/libgringo/src/symbol.cc")
        .file("clingo/libgringo/src/primes.cc")
        .file("clingo/libgringo/src/backend.cc")
        .file("clingo/libgringo/src/lua.cc")
        .file("clingo/libgringo/src/scripts.cc")
        .file("clingo/libgringo/src/python.cc")
        .file("clingo/libgringo/src/terms.cc")
        .file("clingo/libgringo/src/ground/statements.cc")
        .file("clingo/libgringo/src/ground/literals.cc")
        .file("clingo/libgringo/src/ground/instantiation.cc")
        .file("clingo/libgringo/src/input/groundtermparser.cc")
        .file("generated/input/nongroundgrammar/grammar.cc")
        .file("generated/input/groundtermgrammar/grammar.cc")
        .file("clingo/libgringo/src/input/nongroundparser.cc")
        .file("clingo/libgringo/src/input/aggregate.cc")
        .file("clingo/libgringo/src/input/aggregates.cc")
        .file("clingo/libgringo/src/input/program.cc")
        .file("clingo/libgringo/src/ground/program.cc")
        .file("clingo/libgringo/src/input/programbuilder.cc")
        .file("clingo/libgringo/src/input/literals.cc")
        .file("clingo/libgringo/src/input/statement.cc")
        .file("clingo/libgringo/src/input/literal.cc")
        .file("clingo/libgringo/src/input/theory.cc")
        .file("clingo/libgringo/src/output/statements.cc")
        .file("clingo/libgringo/src/output/literals.cc")
        .file("clingo/libgringo/src/output/aggregates.cc")
        .file("clingo/libgringo/src/output/output.cc")
        .file("clingo/libgringo/src/output/statement.cc")
        .file("clingo/libgringo/src/output/literal.cc")
        .file("clingo/libgringo/src/output/theory.cc")
        .include("clingo/libgringo")
        .include("generated")
        .include("clingo/liblp")
        .include("clingo/libreify")
        .compile("libgringo.a");

    gcc::Config::new()
        .cpp(true)
        .define("NDEBUG", Some("1"))
        .file("clingo/libprogram_opts/src/application.cpp")
        .file("clingo/libprogram_opts/src/alarm.cpp")
        .file("clingo/libprogram_opts/src/program_options.cpp")
        .file("clingo/libprogram_opts/src/string_convert.cpp")
        .file("clingo/libprogram_opts/src/value_store.cpp")
        .include("clingo/libprogram_opts")
        .compile("libprogram_opts.a");

    gcc::Config::new()
        .cpp(true)
        .define("NDEBUG", Some("1"))
        .file("clingo/libreify/src/program.cc")
        .include("clingo/libreify")
        .include("clingo/liblp")
        .include("clingo/libgringo")
        .compile("libreify.a");

    gcc::Config::new()
        .cpp(true)
        .define("NDEBUG", Some("1"))
        .file("clingo/liblp/src/aspif.cpp")
        .file("clingo/liblp/src/clingo.cpp")
        .file("clingo/liblp/src/theory_data.cpp")
        .file("clingo/liblp/src/smodels.cpp")
        .file("clingo/liblp/src/convert.cpp")
        .file("clingo/liblp/src/rule_utils.cpp")
        .file("clingo/liblp/src/match_basic_types.cpp")
        .file("clingo/liblp/src/aspif_text.cpp")
        .include("clingo/liblp")
        .compile("liblp.a");

    gcc::Config::new()
        .cpp(true)
        .define("NDEBUG", Some("1"))
        .define("WITH_THREADS", Some("0"))
        .file("clingo/libclingo/src/clingocontrol.cc")
        .include("clingo/libclingo")
        .include("clingo/libgringo")
        .include("clingo/liblp")
        .include("clingo/libclasp")
        .include("clingo/libprogram_opts")
        .compile("libclingo.a");

    gcc::Config::new()
        .cpp(true)
        .define("NDEBUG", Some("1"))
        .define("WITH_THREADS", Some("0"))
        .file("clingo/libclasp/src/parallel_solve.cpp")
        .file("clingo/libclasp/src/solver_types.cpp")
        .file("clingo/libclasp/src/solver_strategies.cpp")
        .file("clingo/libclasp/src/clause.cpp")
        .file("clingo/libclasp/src/logic_program.cpp")
        .file("clingo/libclasp/src/clasp_facade.cpp")
        .file("clingo/libclasp/src/cb_enumerator.cpp")
        .file("clingo/libclasp/src/minimize_constraint.cpp")
        .file("clingo/libclasp/src/clingo.cpp")
        .file("clingo/libclasp/src/shared_context.cpp")
        .file("clingo/libclasp/src/dependency_graph.cpp")
        .file("clingo/libclasp/src/logic_program_types.cpp")
        .file("clingo/libclasp/src/asp_preprocessor.cpp")
        .file("clingo/libclasp/src/clasp_options.cpp")
        .file("clingo/libclasp/src/heuristics.cpp")
        .file("clingo/libclasp/src/timer.cpp")
        .file("clingo/libclasp/src/lookahead.cpp")
        .file("clingo/libclasp/src/constraint.cpp")
        .file("clingo/libclasp/src/unfounded_check.cpp")
        .file("clingo/libclasp/src/solver.cpp")
        .file("clingo/libclasp/src/model_enumerators.cpp")
        .file("clingo/libclasp/src/clasp_output.cpp")
        .file("clingo/libclasp/src/parser.cpp")
        .file("clingo/libclasp/src/solve_algorithms.cpp")
        .file("clingo/libclasp/src/enumerator.cpp")
        .file("clingo/libclasp/src/program_builder.cpp")
        .file("clingo/libclasp/src/satelite.cpp")
        .file("clingo/libclasp/src/statistics.cpp")
        .file("clingo/libclasp/src/weight_constraint.cpp")
        .include("clingo/libclasp")
        .include("clingo/libclingo")
        .include("clingo/liblp")
        .include("clingo/libprogram_opts")
        .compile("libclasp.a");

    println!("cargo:rustc-link-lib=clingo");

    let out_dir = env::var("OUT_DIR").unwrap();

    let bindings = bindgen::builder()
        .no_unstable_rust()
        .header("clingo/libgringo/clingo.h")
        .use_core()
        .generate()
        .expect("Unable to generate bindings");

    let out_path = PathBuf::from(out_dir);

    bindings.write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");

}
<|endoftext|>


<commit_before>use std::process::Command;
use std::env;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();

    // Invoke ISPC to compile our code
    let ispc_status = Command::new("ispc").args(&["src/say_hello.ispc", "--pic", "-o"])
        .arg(&format!("{}/say_hello.o", out_dir))
        .status().unwrap();
    if !ispc_status.success() {
        panic!("ISPC compilation failed");
    }
    // Place our code into a static library we can link against
    let link_status = Command::new("ar").args(&["crus", "libsay_hello.a", "say_hello.o"])
        .current_dir(&Path::new(&out_dir))
        .status().unwrap();
    if !link_status.success() {
        panic!("Linking ISPC code into archive failed");
    }
    println!("cargo:rustc-flags=-L native={}", out_dir);
}

<commit_msg>Update to use path module correctly<commit_after>use std::path::Path;
use std::process::Command;
use std::env;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let debug = env::var("DEBUG").unwrap();

    let mut ispc_args = vec!["src/say_hello.ispc", "--pic"];
    if debug == "true" {
        ispc_args.push("-g");
    }
    // Invoke ISPC to compile our code
    let ispc_status = Command::new("ispc").args(&ispc_args[..])
        .args(&["-o", &format!("{}/say_hello.o", out_dir)])
        .status().unwrap();
    if !ispc_status.success() {
        panic!("ISPC compilation failed");
    }
    // Place our code into a static library we can link against
    let link_status = Command::new("ar").args(&["crus", "libsay_hello.a", "say_hello.o"])
        .current_dir(&Path::new(&out_dir))
        .status().unwrap();
    if !link_status.success() {
        panic!("Linking ISPC code into archive failed");
    }
    println!("cargo:rustc-flags=-L native={}", out_dir);
}

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

#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;
extern crate proc_macro2;

use std::env;
use std::path::Path;

#[cfg(feature = "dummy_match_byte")]
mod codegen {
    use std::path::Path;
    pub fn main() {}
}

#[cfg(not(feature = "dummy_match_byte"))]
#[path = "build/match_byte.rs"]
mod match_byte;

#[cfg(not(feature = "dummy_match_byte"))]
mod codegen {
    use match_byte;
    use std::env;
    use std::path::Path;
    use std::thread::Builder;

    pub fn main() {
        let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

        let input = Path::new(&manifest_dir).join("src/tokenizer.rs");
        let output = Path::new(&env::var("OUT_DIR").unwrap()).join("tokenizer.rs");
        println!("cargo:rerun-if-changed={}", input.display());

        // We have stack overflows on Servo's CI.
        let handle = Builder::new().stack_size(128 * 1024 * 1024).spawn(move || {
            match_byte::expand(&input, &output);
        }).unwrap();

        handle.join().unwrap();
    }
}

fn main() {
    if std::mem::size_of::<Option<bool>>() == 1 {
        // https://github.com/rust-lang/rust/pull/45225
        println!("cargo:rustc-cfg=rustc_has_pr45225")
    }

    codegen::main();
}
<commit_msg>Remove some warnings.<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/. */

#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;
extern crate proc_macro2;

#[cfg(feature = "dummy_match_byte")]
mod codegen {
    use std::path::Path;
    pub fn main() {}
}

#[cfg(not(feature = "dummy_match_byte"))]
#[path = "build/match_byte.rs"]
mod match_byte;

#[cfg(not(feature = "dummy_match_byte"))]
mod codegen {
    use match_byte;
    use std::env;
    use std::path::Path;
    use std::thread::Builder;

    pub fn main() {
        let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

        let input = Path::new(&manifest_dir).join("src/tokenizer.rs");
        let output = Path::new(&env::var("OUT_DIR").unwrap()).join("tokenizer.rs");
        println!("cargo:rerun-if-changed={}", input.display());

        // We have stack overflows on Servo's CI.
        let handle = Builder::new().stack_size(128 * 1024 * 1024).spawn(move || {
            match_byte::expand(&input, &output);
        }).unwrap();

        handle.join().unwrap();
    }
}

fn main() {
    if std::mem::size_of::<Option<bool>>() == 1 {
        // https://github.com/rust-lang/rust/pull/45225
        println!("cargo:rustc-cfg=rustc_has_pr45225")
    }

    codegen::main();
}
<|endoftext|>


<commit_before>use std::env;
use std::ffi::OsString;
use std::process::Command;

fn get_rustc_version() -> (i32, i32) {
    let rustc = env::var_os("RUSTC").unwrap_or_else(|| OsString::from("rustc"));
    let out = String::from_utf8(Command::new(&rustc)
        .arg("--version")
        .output()
        .unwrap().stdout).unwrap();
    let mut pieces = out.split(' ');
    let _ = pieces.next();

    let mut ver_iter = pieces.next().unwrap().split('.').map(|x| x.parse().unwrap());
    (ver_iter.next().unwrap(), ver_iter.next().unwrap())
}

fn rustc_has_unix_socket() -> bool {
    if !cfg!(unix) {
        false
    } else {
        let (major, minor) = get_rustc_version();
        major > 1 || (major == 1 && minor >= 10)
    }
}

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    if rustc_has_unix_socket() {
        println!("cargo:rustc-cfg=feature=\"with-system-unix-sockets\"");
    }
}
<commit_msg>Don't crash if the rustc version can't be determined<commit_after>use std::env;
use std::ffi::OsString;
use std::process::Command;
use std::error::Error;

fn get_rustc_version() -> Result<(i32, i32), Box<Error>> {
    fn err() -> Box<Error> {
        "Can't determine the rustc version.".into()
    }

    let rustc = env::var_os("RUSTC").unwrap_or_else(|| OsString::from("rustc"));
    let out = String::from_utf8(Command::new(&rustc)
        .arg("--version")
        .output()
        .unwrap().stdout).unwrap();
    let mut pieces = out.split(' ');
    let _ = pieces.next().ok_or(err())?;

    let mut ver_iter = pieces
        .next()
        .ok_or(err())?
        .split('.')
        .map(|x| x.parse());
    let major = ver_iter.next().ok_or(err())??;
    let minor = ver_iter.next().ok_or(err())??;
    Ok((major, minor))
}

fn rustc_has_unix_socket() -> bool {
    if !cfg!(unix) {
        false
    } else {
        if let Ok((major, minor)) = get_rustc_version() {
            major > 1 || (major == 1 && minor >= 10)
        } else {
            false
        }
    }
}

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    if rustc_has_unix_socket() {
        println!("cargo:rustc-cfg=feature=\"with-system-unix-sockets\"");
    }
}
<|endoftext|>