<commit_before>use base::*;
use rouille;
use rouille::Response;
use ui::*;
use std::fs::File;
use std::io::Read;
use std::thread;

fn load_file(filename: &str) -> Result<String> {
    let mut file = try!(File::open(filename));
    let mut content = String::new();
    try!(file.read_to_string(&mut content));
    Ok(content)
}

#[derive(RustcEncodable)]
struct EmptyResponse {}

fn serve_web(address: &str, shared_state: SharedState) {
    rouille::start_server(address, move |request| {
        router!(request,
            (GET) (/) => {
                match load_file("web/index.html") {
                    Ok(html) => Response::html(html),
                    Err(error) => {
                        println!("Can't load index.html: {}", error);
                        Response::text("Internal Server Error").with_status_code(500)
                    }
                }
            },
            (GET) (/api/state) => {
                let state_controller = shared_state.lock();
                Response::json(state_controller.state())
            },
            (POST) (/api/state) => {
                 #[derive(RustcDecodable)]
                 struct LoudnessParams {
                     enabled: Option<bool>,
                     auto: Option<bool>,
                     level: Option<f32>,
                 }

                 #[derive(RustcDecodable)]
                 struct CrossfeedParams {
                     enabled: Option<bool>,
                     level: Option<f32>,
                     delay_ms: Option<f32>,
                 }

                 #[derive(RustcDecodable)]
                 struct FeatureParams {
                     enabled: Option<bool>,
                     level: Option<f32>,
                 }

                 #[derive(RustcDecodable)]
                 struct RequestParams {
                     volume: Option<f32>,
                     output: Option<usize>,
                     mux_mode: Option<MuxMode>,
                     enable_drc: Option<bool>,
                     loudness: Option<LoudnessParams>,
                     voice_boost: Option<FeatureParams>,
                     crossfeed: Option<CrossfeedParams>,
                 }

                let json: RequestParams = try_or_400!(rouille::input::json_input(request));

                let mut state_controller = shared_state.lock();

                json.volume.map( |volume| {
                  state_controller.set_volume(Gain{db: volume});
                });

                match json.output {
                    Some(output) => {
                          if output > state_controller.state().outputs.len() {
                            return Response::text("Invalid output id").with_status_code(404)
                          }
                          state_controller.select_output(output);
                        }
                    None => ()
                };

                json.mux_mode.map( |mux_mode| {
                    state_controller.set_mux_mode(mux_mode);
                });

                json.enable_drc.map( |enable_drc| {
                    state_controller.set_enable_drc(enable_drc);
                });

                json.loudness.map( |loudness| {
                    let mut loudness_config = state_controller.state().loudness.clone();
                    loudness.enabled.map( |enabled| {
                        loudness_config.enabled = enabled;
                    });
                    loudness.auto.map( |auto| {
                        loudness_config.auto = auto;
                    });
                    loudness.level.map( |level| {
                        loudness_config.level = level;
                    });
                    state_controller.set_loudness(loudness_config);
                });

                json.voice_boost.map( |voice_boost| {
                    let mut voice_boost_config = state_controller.state().voice_boost.clone();
                    voice_boost.enabled.map( |enabled| {
                        voice_boost_config.enabled = enabled;
                    });
                    voice_boost.level.map( |level| {
                        voice_boost_config.level = level;
                    });
                    state_controller.set_voice_boost(voice_boost_config);
                });

                json.crossfeed.map( |crossfeed| {
                    let mut crossfeed_config = state_controller.state().crossfeed.clone();
                    crossfeed.enabled.map( |enabled| {
                        crossfeed_config.enabled = enabled;
                    });
                    crossfeed.level.map( |level| {
                        crossfeed_config.level = level;
                    });
                    crossfeed.delay_ms.map( |delay_ms| {
                        crossfeed_config.delay_ms = delay_ms;
                    });
                    state_controller.set_crossfeed(crossfeed_config);
                });

                Response::json(&EmptyResponse{})
            },
            (POST) (/api/inputs/{id: usize}) => {
                 #[derive(RustcDecodable)]
                 struct RequestParams {
                     gain: f32,
                 }

                let json: RequestParams = try_or_400!(rouille::input::json_input(request));
                let gain = Gain { db: json.gain };

                let mut state_controller = shared_state.lock();
                if id >= state_controller.state().inputs.len() {
                    return Response::text("Invalid input id").with_status_code(404)
                }

                state_controller.set_input_gain(id, gain);

                Response::json(&EmptyResponse{})
            },
            (GET) (/status) => {
                let temp_str = match load_file("/sys/class/thermal/thermal_zone0/temp") {
                    Ok(s) => s,
                    Err(error) => {
                        println!("Failed to get temp: {}", error);
                        return Response::text("Internal Server Error").with_status_code(500)
                    }
                };
                let temp = match temp_str.trim().parse::<usize>() {
                    Ok(temp) => temp,
                    Err(error) => {
                        println!("Failed to parse temp: {}", error);
                        return Response::text("Internal Server Error").with_status_code(500)
                    }
                };
                Response::html(format!("CPU temperature: {:.1}°C", temp as f32 / 1000.0))
            },
            _ => Response::empty_404()
        )
    });
}

pub fn start_web(address: &str, shared_state: SharedState) {
    let address_copy = String::from(address);
    thread::spawn(move || { serve_web(&address_copy, shared_state); });
}
<commit_msg>fix stats page scaling<commit_after>use base::*;
use rouille;
use rouille::Response;
use ui::*;
use std::fs::File;
use std::io::Read;
use std::thread;

fn load_file(filename: &str) -> Result<String> {
    let mut file = try!(File::open(filename));
    let mut content = String::new();
    try!(file.read_to_string(&mut content));
    Ok(content)
}

#[derive(RustcEncodable)]
struct EmptyResponse {}

fn serve_web(address: &str, shared_state: SharedState) {
    rouille::start_server(address, move |request| {
        router!(request,
            (GET) (/) => {
                match load_file("web/index.html") {
                    Ok(html) => Response::html(html),
                    Err(error) => {
                        println!("Can't load index.html: {}", error);
                        Response::text("Internal Server Error").with_status_code(500)
                    }
                }
            },
            (GET) (/api/state) => {
                let state_controller = shared_state.lock();
                Response::json(state_controller.state())
            },
            (POST) (/api/state) => {
                 #[derive(RustcDecodable)]
                 struct LoudnessParams {
                     enabled: Option<bool>,
                     auto: Option<bool>,
                     level: Option<f32>,
                 }

                 #[derive(RustcDecodable)]
                 struct CrossfeedParams {
                     enabled: Option<bool>,
                     level: Option<f32>,
                     delay_ms: Option<f32>,
                 }

                 #[derive(RustcDecodable)]
                 struct FeatureParams {
                     enabled: Option<bool>,
                     level: Option<f32>,
                 }

                 #[derive(RustcDecodable)]
                 struct RequestParams {
                     volume: Option<f32>,
                     output: Option<usize>,
                     mux_mode: Option<MuxMode>,
                     enable_drc: Option<bool>,
                     loudness: Option<LoudnessParams>,
                     voice_boost: Option<FeatureParams>,
                     crossfeed: Option<CrossfeedParams>,
                 }

                let json: RequestParams = try_or_400!(rouille::input::json_input(request));

                let mut state_controller = shared_state.lock();

                json.volume.map( |volume| {
                  state_controller.set_volume(Gain{db: volume});
                });

                match json.output {
                    Some(output) => {
                          if output > state_controller.state().outputs.len() {
                            return Response::text("Invalid output id").with_status_code(404)
                          }
                          state_controller.select_output(output);
                        }
                    None => ()
                };

                json.mux_mode.map( |mux_mode| {
                    state_controller.set_mux_mode(mux_mode);
                });

                json.enable_drc.map( |enable_drc| {
                    state_controller.set_enable_drc(enable_drc);
                });

                json.loudness.map( |loudness| {
                    let mut loudness_config = state_controller.state().loudness.clone();
                    loudness.enabled.map( |enabled| {
                        loudness_config.enabled = enabled;
                    });
                    loudness.auto.map( |auto| {
                        loudness_config.auto = auto;
                    });
                    loudness.level.map( |level| {
                        loudness_config.level = level;
                    });
                    state_controller.set_loudness(loudness_config);
                });

                json.voice_boost.map( |voice_boost| {
                    let mut voice_boost_config = state_controller.state().voice_boost.clone();
                    voice_boost.enabled.map( |enabled| {
                        voice_boost_config.enabled = enabled;
                    });
                    voice_boost.level.map( |level| {
                        voice_boost_config.level = level;
                    });
                    state_controller.set_voice_boost(voice_boost_config);
                });

                json.crossfeed.map( |crossfeed| {
                    let mut crossfeed_config = state_controller.state().crossfeed.clone();
                    crossfeed.enabled.map( |enabled| {
                        crossfeed_config.enabled = enabled;
                    });
                    crossfeed.level.map( |level| {
                        crossfeed_config.level = level;
                    });
                    crossfeed.delay_ms.map( |delay_ms| {
                        crossfeed_config.delay_ms = delay_ms;
                    });
                    state_controller.set_crossfeed(crossfeed_config);
                });

                Response::json(&EmptyResponse{})
            },
            (POST) (/api/inputs/{id: usize}) => {
                 #[derive(RustcDecodable)]
                 struct RequestParams {
                     gain: f32,
                 }

                let json: RequestParams = try_or_400!(rouille::input::json_input(request));
                let gain = Gain { db: json.gain };

                let mut state_controller = shared_state.lock();
                if id >= state_controller.state().inputs.len() {
                    return Response::text("Invalid input id").with_status_code(404)
                }

                state_controller.set_input_gain(id, gain);

                Response::json(&EmptyResponse{})
            },
            (GET) (/status) => {
                let temp_str = match load_file("/sys/class/thermal/thermal_zone0/temp") {
                    Ok(s) => s,
                    Err(error) => {
                        println!("Failed to get temp: {}", error);
                        return Response::text("Internal Server Error").with_status_code(500)
                    }
                };
                let temp = match temp_str.trim().parse::<usize>() {
                    Ok(temp) => temp,
                    Err(error) => {
                        println!("Failed to parse temp: {}", error);
                        return Response::text("Internal Server Error").with_status_code(500)
                    }
                };
                Response::html(format!(r#"

  <meta name="viewport" content="width=device-width, initial-scale=1">
</meta>

CPU temperature: {:.1}°C

"#, temp as f32 / 1000.0))
            },
            _ => Response::empty_404()
        )
    });
}

pub fn start_web(address: &str, shared_state: SharedState) {
    let address_copy = String::from(address);
    thread::spawn(move || { serve_web(&address_copy, shared_state); });
}
<|endoftext|>


<commit_before>use std::mem;

use misc::*;

#[ repr (C) ]
struct BinaryHeader {

	name: [u8; 100],
	mode: [u8; 8],
	uid: [u8; 8],
	gid: [u8; 8],
	size: [u8; 12],
	mtime: [u8; 12],
	cksum: [u8; 8],
	typeflag: [u8; 1],
	linkname: [u8; 100],
	magic: [u8; 6],
	version: [u8; 2],
	uname: [u8; 32],
	gname: [u8; 32],
	dev_major: [u8; 8],
	dev_minor: [u8; 8],
	atime: [u8; 12],
	ctime: [u8; 12],
	offset: [u8; 12],
	longnames: [u8; 4],
	unused: [u8; 1],
	sparse: [BinarySparseHeader; 4],
	isextended: [u8; 1],
	realsize: [u8; 12],
	pad: [u8; 17],

}

#[ repr (C) ]
struct BinarySparseHeader {

	offset: [u8; 12],
	numbytes: [u8; 12],

}

pub struct Header {

	pub name: Vec <u8>,
	pub mode: u32,
	pub uid: u32,
	pub gid: u32,
	pub size: u64,
	pub mtime: u64,
	pub cksum: u32,
	pub typeflag: Type,
	pub linkname: Vec <u8>,
	pub uname: Vec <u8>,
	pub gname: Vec <u8>,
	pub dev_major: u32,
	pub dev_minor: u32,
	pub atime: u64,
	pub ctime: u64,
	pub offset: u64,

}

#[ derive (Debug) ]
pub enum Type {

	Regular,
	Link,
	SymbolicLink,
	CharacterSpecial,
	BlockSpecial,
	Directory,
	Fifo,

	LongName,
	LongLink,

}

impl Header {

	pub fn read (
		header_bytes: & [u8],
	) -> Result <Header, TfError> {

		if header_bytes.len () != 512 {
			panic! ();
		}

		let binary_header =
			unsafe {
				mem::transmute::<& u8, & BinaryHeader> (
					& header_bytes [0])
			};

		if binary_header.magic != * b"ustar " {

			Err (TfError {
				error_message: format! (
					"Unrecognised tar format: {:?} {:?}",
					binary_header.magic,
					binary_header.version),
			})

		} else if binary_header.version != * b" \0" {

			Err (TfError {
				error_message: format! (
					"Unrecognised gnu tar version: {:?}",
					binary_header.version),
			})

	 	} else {

			Ok (Header {

				name: tar_string (
					& binary_header.name),

				mode: try! (
					tar_number_u32 (
						& binary_header.mode)),

				uid: try! (
					tar_number_u32 (
						& binary_header.uid)),

				gid: try! (
					tar_number_u32 (
						& binary_header.gid)),

				size: try! (
					tar_number_u64 (
						& binary_header.size)),

				mtime: try! (
					tar_number_u64 (
						& binary_header.mtime)),

				cksum: try! (
					tar_number_u32 (
						& binary_header.cksum)),

				typeflag: tar_type (
					& binary_header.typeflag),

				linkname: tar_string (
					& binary_header.linkname),

				uname: tar_string (
					& binary_header.uname),

				gname: tar_string (
					& binary_header.gname),

				dev_major: try! (
					tar_number_u32 (
						& binary_header.dev_major)),

				dev_minor: try! (
					tar_number_u32 (
						& binary_header.dev_minor)),

				atime: try! (
					tar_number_u64 (
						& binary_header.atime)),

				ctime: try! (
					tar_number_u64 (
						& binary_header.ctime)),

				offset: try! (
					tar_number_u64 (
						& binary_header.offset)),

/*
				longnames: [u8; 4],
				unused: [u8; 1],
				sparse: [BinarySparseHeader; 4],
				isextended: [u8; 1],
				realsize: [u8; 12],
				pad: [u8; 17],
*/

			})

		}

	}

}

fn tar_string (
	slice: & [u8],
) -> Vec <u8> {

	match slice.iter ().position (
		|index| * index == 0,
	) {

		Some (index) =>
			slice [ .. index ].to_vec (),

		None =>
			slice.to_vec (),

	}

}

fn tar_number_u64 (
	slice: & [u8],
) -> Result <u64, TfError> {

	if slice [0] == 0 {

		Ok (0)

	} else if slice [0] == 0x80 {

		Ok (unsafe {
			* mem::transmute::<& u8, & u64> (
				& slice [4])
		})

	} else if slice [0] == 0xff {

		panic! ()

	} else {

		let string =
			try! (
				String::from_utf8 (
					tar_string (slice)));

		let number =
			try! (
				u64::from_str_radix (
					& string,
					8));

		Ok (number)

	}

}

fn tar_number_u32 (
	slice: & [u8],
) -> Result <u32, TfError> {

	if slice [0] == 0 {

		Ok (0)

	} else {

		let string =
			try! (
				String::from_utf8 (
					tar_string (slice)));

		let number =
			try! (
				u32::from_str_radix (
					& string,
					8));

		Ok (number)

	}

}

fn tar_type (
	typeflag: & [u8; 1],
) -> Type {

	match typeflag [0] {

		b'0' => Type::Regular,
		b'1' => Type::Link,
		b'2' => Type::SymbolicLink,
		b'3' => Type::CharacterSpecial,
		b'4' => Type::BlockSpecial,
		b'5' => Type::Directory,
		b'6' => Type::Fifo,

		b'K' => Type::LongLink,
		b'L' => Type::LongName,

		_ => {

			panic! (
				"Unrecognised typeflag: {:?}",
				typeflag [0])

		}

	}

}
<commit_msg>handle binary file sizes for large tar entries<commit_after>use std::mem;

use misc::*;

#[ repr (C) ]
struct BinaryHeader {

	name: [u8; 100],
	mode: [u8; 8],
	uid: [u8; 8],
	gid: [u8; 8],
	size: [u8; 12],
	mtime: [u8; 12],
	cksum: [u8; 8],
	typeflag: [u8; 1],
	linkname: [u8; 100],
	magic: [u8; 6],
	version: [u8; 2],
	uname: [u8; 32],
	gname: [u8; 32],
	dev_major: [u8; 8],
	dev_minor: [u8; 8],
	atime: [u8; 12],
	ctime: [u8; 12],
	offset: [u8; 12],
	longnames: [u8; 4],
	unused: [u8; 1],
	sparse: [BinarySparseHeader; 4],
	isextended: [u8; 1],
	realsize: [u8; 12],
	pad: [u8; 17],

}

#[ repr (C) ]
struct BinarySparseHeader {

	offset: [u8; 12],
	numbytes: [u8; 12],

}

pub struct Header {

	pub name: Vec <u8>,
	pub mode: u32,
	pub uid: u32,
	pub gid: u32,
	pub size: u64,
	pub mtime: u64,
	pub cksum: u32,
	pub typeflag: Type,
	pub linkname: Vec <u8>,
	pub uname: Vec <u8>,
	pub gname: Vec <u8>,
	pub dev_major: u32,
	pub dev_minor: u32,
	pub atime: u64,
	pub ctime: u64,
	pub offset: u64,

}

#[ derive (Debug) ]
pub enum Type {

	Regular,
	Link,
	SymbolicLink,
	CharacterSpecial,
	BlockSpecial,
	Directory,
	Fifo,

	LongName,
	LongLink,

}

impl Header {

	pub fn read (
		header_bytes: & [u8],
	) -> Result <Header, TfError> {

		if header_bytes.len () != 512 {
			panic! ();
		}

		let binary_header =
			unsafe {
				mem::transmute::<& u8, & BinaryHeader> (
					& header_bytes [0])
			};

		if binary_header.magic != * b"ustar " {

			Err (TfError {
				error_message: format! (
					"Unrecognised tar format: {:?} {:?}",
					binary_header.magic,
					binary_header.version),
			})

		} else if binary_header.version != * b" \0" {

			Err (TfError {
				error_message: format! (
					"Unrecognised gnu tar version: {:?}",
					binary_header.version),
			})

	 	} else {

			Ok (Header {

				name: tar_string (
					& binary_header.name),

				mode: try! (
					tar_number_u32 (
						& binary_header.mode)),

				uid: try! (
					tar_number_u32 (
						& binary_header.uid)),

				gid: try! (
					tar_number_u32 (
						& binary_header.gid)),

				size: try! (
					tar_number_u64 (
						& binary_header.size)),

				mtime: try! (
					tar_number_u64 (
						& binary_header.mtime)),

				cksum: try! (
					tar_number_u32 (
						& binary_header.cksum)),

				typeflag: tar_type (
					& binary_header.typeflag),

				linkname: tar_string (
					& binary_header.linkname),

				uname: tar_string (
					& binary_header.uname),

				gname: tar_string (
					& binary_header.gname),

				dev_major: try! (
					tar_number_u32 (
						& binary_header.dev_major)),

				dev_minor: try! (
					tar_number_u32 (
						& binary_header.dev_minor)),

				atime: try! (
					tar_number_u64 (
						& binary_header.atime)),

				ctime: try! (
					tar_number_u64 (
						& binary_header.ctime)),

				offset: try! (
					tar_number_u64 (
						& binary_header.offset)),

/*
				longnames: [u8; 4],
				unused: [u8; 1],
				sparse: [BinarySparseHeader; 4],
				isextended: [u8; 1],
				realsize: [u8; 12],
				pad: [u8; 17],
*/

			})

		}

	}

}

fn tar_string (
	slice: & [u8],
) -> Vec <u8> {

	match slice.iter ().position (
		|index| * index == 0,
	) {

		Some (index) =>
			slice [ .. index ].to_vec (),

		None =>
			slice.to_vec (),

	}

}

fn tar_number_u64 (
	slice: & [u8],
) -> Result <u64, TfError> {

	if slice [0] == 0 {

		Ok (0)

	} else if slice [0] == 0x80 {

		Ok (u64::from_be (
			unsafe {
				* mem::transmute::<& u8, & u64> (
					& slice [4])
			}
		))

	} else if slice [0] == 0xff {

		panic! ()

	} else {

		let string =
			try! (
				String::from_utf8 (
					tar_string (slice)));

		let number =
			try! (
				u64::from_str_radix (
					& string,
					8));

		Ok (number)

	}

}

fn tar_number_u32 (
	slice: & [u8],
) -> Result <u32, TfError> {

	if slice [0] == 0 {

		Ok (0)

	} else {

		let string =
			try! (
				String::from_utf8 (
					tar_string (slice)));

		let number =
			try! (
				u32::from_str_radix (
					& string,
					8));

		Ok (number)

	}

}

fn tar_type (
	typeflag: & [u8; 1],
) -> Type {

	match typeflag [0] {

		b'0' => Type::Regular,
		b'1' => Type::Link,
		b'2' => Type::SymbolicLink,
		b'3' => Type::CharacterSpecial,
		b'4' => Type::BlockSpecial,
		b'5' => Type::Directory,
		b'6' => Type::Fifo,

		b'K' => Type::LongLink,
		b'L' => Type::LongName,

		_ => {

			panic! (
				"Unrecognised typeflag: {:?}",
				typeflag [0])

		}

	}

}
<|endoftext|>


<commit_before>extern crate crypto;

use crypto::md5::Md5;
use crypto::digest::Digest;

const INPUT: &'static str = "uqwqemis";

fn main() {
    let mut hasher = Md5::new();
    let input = INPUT.as_bytes();
    for i in (0..std::u64::MAX) {
        hasher.input(input);
        hasher.input(i.to_string().as_bytes());
        let result = hasher.result_str();
        if result.chars().take(5).all(|c| c == '0') {
            println!("{}", result);
        }
        hasher.reset();
    }
    hasher.reset()
}
<commit_msg>rust day05 proper solution<commit_after>extern crate crypto;

use crypto::md5::Md5;
use crypto::digest::Digest;
use std::collections::BTreeMap;

const INPUT: &'static str = "uqwqemis";

fn main() {
    let mut hasher = Md5::new();
    let hashes_with_five_zeroes = || {
        (0..)
            .map(move |i| {
                hasher.reset();
                hasher.input_str(&format!("{}{}", INPUT, i));
                hasher.result_str().to_owned()
            })
            .filter(|hash| hash.chars().take(5).all(|c| c == '0'))
    };
    let part1: String = hashes_with_five_zeroes()
        .take(8)
        .map(|hash| hash.chars().nth(5).unwrap())
        .collect();

    let mut part2 = BTreeMap::<char, char>::new();
    for hash in hashes_with_five_zeroes() {
        let index = hash.chars().nth(5).unwrap();
        if index.is_digit(10) && !part2.contains_key(&index) && index != '8' && index != '9' {
            part2.insert(index, hash.chars().nth(6).unwrap());
        }
        if part2.len() == 8 {
            break;
        }
    }
    println!("part 1: {}", part1);
    println!("part 2: {}", part2.values().cloned().collect::<String>());
}
<|endoftext|>


<commit_before>extern crate num;

use self::num::traits::Num;

use std::cmp;
use std::mem;
use std::fmt::Debug;
use std::ops::Range;

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct IntervalTree<N, D> {
    root: Option<Node<N, D>>,
}

impl<N: Debug + Num + Clone + Ord, D: Debug> IntervalTree<N, D> {
    pub fn new() -> Self {
        IntervalTree { root: None }
    }

    pub fn insert(&mut self, interval: Range<N>, data: D) {
        validate(&interval);
        match self.root {
            Some(ref mut n) => n.insert(interval, data),
            None => self.root = Some(Node::new(interval, data)),
        }
    }

    pub fn find_any(&self, interval: &Range<N>) -> Option<(&Range<N>, &D)> {
        validate(&interval);
        match self.root {
            Some(ref n) => {
                let mut result = vec![];
                n.find(interval, true, &mut result);
                result.pop()
            }
            None => None,
        }
    }

    pub fn find_all(&self, interval: &Range<N>) -> Vec<(&Range<N>, &D)> {
        validate(&interval);
        match self.root {
            Some(ref n) => {
                let mut result = vec![];
                n.find(interval, true, &mut result);
                result
            }
            None => vec![],
        }
    }
}

fn validate<N: Ord + Debug>(interval: &Range<N>) {
    if interval.start >= interval.end {
        panic!("Expected interval.end > interval.start, got: ({:?})",
               interval);
    }
}

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Node<N, D> {
    // actual interval data
    interval: Range<N>,
    value: D,
    // tree metadata
    max: N,
    height: i64,
    left: Option<Box<Node<N, D>>>,
    right: Option<Box<Node<N, D>>>,
}

impl<N: Debug + Num + Clone + Ord, D: Debug> Node<N, D> {
    pub fn new(interval: Range<N>, data: D) -> Self {
        let max = interval.end.clone();
        Node {
            interval: interval,
            max: max,
            height: 1,
            value: data,
            left: None,
            right: None,
        }
    }

    pub fn insert(&mut self, interval: Range<N>, data: D) {
        if interval.start <= self.interval.start {
            if let Some(ref mut son) = self.left {
                son.insert(interval, data);
            } else {
                self.left = Some(Box::new(Node::new(interval, data)));
            }
        } else {
            if let Some(ref mut son) = self.right {
                son.insert(interval, data);
            } else {
                self.right = Some(Box::new(Node::new(interval, data)));
            }
        }
        self.repair();
    }

    pub fn find<'a>(&'a self,
                    interval: &Range<N>,
                    only_one: bool,
                    result: &mut Vec<(&'a Range<N>, &'a D)>) {
        if interval.end <= self.interval.start || self.interval.end <= interval.start {
            // no overlap with current node, recur into children
            if let Some(ref left) = self.left {
                if left.max > interval.start {
                    left.find(interval, only_one, result);
                    return;
                }
            }
            if let Some(ref right) = self.right {
                right.find(interval, only_one, result);
                return;
            }
        } else {
            result.push((&self.interval, &self.value));
            if only_one {
                return;
            } else {
                if let Some(ref left) = self.left {
                    left.find(interval, only_one, result);
                }
                if let Some(ref right) = self.right {
                    right.find(interval, only_one, result);
                }
            }
        }
    }

    fn update_height(&mut self) {
        let ref left_h = self.left.as_ref().map_or(0, |n| n.height);
        let ref right_h = self.right.as_ref().map_or(0, |n| n.height);
        self.height = 1 + cmp::max(*left_h, *right_h);
    }

    fn update_max(&mut self) {
        self.max = self.interval.end.clone();
        if let Some(ref n) = self.left {
            if self.max < n.max {
                self.max = n.max.clone();
            }
        }
        if let Some(ref n) = self.right {
            if self.max < n.max {
                self.max = n.max.clone();
            }
        }
    }

    fn repair(&mut self) {
        let ref left_h = self.left.as_ref().map_or(0, |n| n.height);
        let ref right_h = self.right.as_ref().map_or(0, |n| n.height);
        // each case - update both height and max
        if (left_h - right_h).abs() <= 1 {
            self.update_height();
            self.update_max();
        } else if right_h > left_h {
            {
                let mut right =
                    self.right.as_mut().expect("Invalid tree: leaf is taller than its sibling.");
                let ref right_left_h = right.left.as_ref().map_or(0, |n| n.height);
                let ref right_right_h = right.right.as_ref().map_or(0, |n| n.height);
                if right_left_h > right_right_h {
                    right.rotate_right();
                }
            }
            self.rotate_left();
        } else {
            {
                let mut left =
                    self.left.as_mut().expect("Invalid tree: leaf is taller than its sibling.");
                let ref left_right_h = left.right.as_ref().map_or(0, |n| n.height);
                let ref left_left_h = left.left.as_ref().map_or(0, |n| n.height);
                if left_right_h > left_left_h {
                    println!("double rot");
                    left.rotate_left();
                }
            }
            self.rotate_right();
        }
    }

    fn rotate_left(&mut self) {
        let mut new_root = self.right.take().unwrap();
        let t1 = self.left.take();
        let t2 = new_root.left.take();
        let t3 = new_root.right.take();
        swap_interval_data(self, &mut *new_root);

        new_root.left = t1;
        new_root.right = t2;
        new_root.update_height();
        new_root.update_max();

        self.right = t3;
        self.left = Some(new_root);
        self.update_height();
        self.update_max();
    }

    fn rotate_right(&mut self) {
        let mut new_root = self.left.take().unwrap();
        let t1 = new_root.left.take();
        let t2 = new_root.right.take();
        let t3 = self.right.take();
        swap_interval_data(self, &mut *new_root);

        new_root.left = t2;
        new_root.right = t3;
        new_root.update_height();
        new_root.update_max();

        self.left = t1;
        self.right = Some(new_root);
        self.update_height();
        self.update_max();
    }
}

fn swap_interval_data<N, D>(node_1: &mut Node<N, D>, node_2: &mut Node<N, D>) {
    mem::swap(&mut node_1.value, &mut node_2.value);
    mem::swap(&mut node_1.interval, &mut node_2.interval);
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::cmp;
    use std::ops::Range;

    fn validate(node: &Node<i64, String>) {
        validate_height(node);
        validate_intervals(node);
        validate_string_metadata(node);
        node.left.as_ref().map(|n| validate(n));
        node.right.as_ref().map(|n| validate(n));
    }

    fn validate_height(node: &Node<i64, String>) {
        let ref left_height = node.left.as_ref().map_or(0, |n| n.height);
        let ref right_height = node.right.as_ref().map_or(0, |n| n.height);
        assert!((left_height - right_height).abs() <= 1);
        assert_eq!(node.height, cmp::max(left_height, right_height) + 1)
    }

    fn validate_intervals(node: &Node<i64, String>) {
        let mut reached_maximum: bool = false;
        if node.interval.end == node.max {
            reached_maximum = true;
        }
        if let Some(ref son) = node.left {
            if !(son.max <= node.max) {
                panic!("left max invariant violated:\n{:?} -> {:?}", node, son);
            }
            if !(son.interval.start <= node.interval.start) {
                panic!("left ord invariant violated\n{:?} -> {:?}", node, son);
            }
            if node.max == son.max {
                reached_maximum = true;
            }
        }
        if let Some(ref son) = node.right {
            if !(son.max <= node.max) {
                panic!("right max invariant violated\n{:?} -> {:?}", node, son);
            }

            if !(son.interval.start >= node.interval.start) {
                panic!("right ord invariant violated\n{:?} -> {:?}", node, son);
            }
            if node.max == son.max {
                reached_maximum = true;
            }
        }
        if !reached_maximum {
            panic!("maximum invariant violated: {:?}", node);
        }
    }

    fn validate_string_metadata(node: &Node<i64, String>) {
        let mut name: String = "".to_string();
        name.push_str(&node.interval.start.to_string());
        name.push_str(":");
        name.push_str(&node.interval.end.to_string());
        if name != node.value {
            panic!("Invalid metadata for node {:?}", node);
        }
    }

    fn insert_and_validate(tree: &mut IntervalTree<i64, String>, start: i64, end: i64) {
        let mut name: String = "".to_string();
        name.push_str(&start.to_string());
        name.push_str(":");
        name.push_str(&end.to_string());
        tree.insert((start..end), name);
        if let Some(ref n) = tree.root {
            validate(n);
        }
    }

    fn assert_intersection(tree: &IntervalTree<i64, String>,
                           target: Range<i64>,
                           expected_bounds: Range<i64>) {
        let mut expected_data: String = "".to_string();
        expected_data.push_str(&expected_bounds.start.to_string());
        expected_data.push_str(":");
        expected_data.push_str(&expected_bounds.end.to_string());
        if let Some((actual_bounds, actual_data)) = tree.find_any(&target) {
            assert_eq!(&expected_data.to_string(), actual_data);
            assert_eq!(&expected_bounds, actual_bounds);
        } else {
            panic!("Expected to find {:?} in the tree", expected_bounds);
        }
    }

    #[test]
    fn test_insertion_and_intersection() {
        let mut tree: IntervalTree<i64, String> = IntervalTree::new();
        tree.insert((50..51), "50:51".to_string());
        assert_eq!(tree.find_any(&(49..50)), None);
        assert_intersection(&tree, (49..55), (50..51));
        assert_eq!(tree.find_any(&(51..55)), None);
        assert_eq!(tree.find_any(&(52..55)), None);
        assert_eq!(tree.find_any(&(40..45)), None);
        insert_and_validate(&mut tree, 80, 81);
        assert_intersection(&tree, (80..83), (80..81));
        assert_eq!(tree.find_any(&(82..83)), None);
        insert_and_validate(&mut tree, 30, 35);
        assert_intersection(&tree, (25..33), (30..35));
        assert_eq!(tree.find_any(&(42..43)), None);
        assert_eq!(tree.find_any(&(35..36)), None);
        assert_eq!(tree.find_any(&(22..29)), None);
        insert_and_validate(&mut tree, 70, 77);
        assert_intersection(&tree, (75..79), (70..77));
        assert_eq!(tree.find_any(&(62..68)), None);
        assert_intersection(&tree, (75..77), (70..77));
        assert_eq!(tree.find_any(&(78..79)), None);
        assert_intersection(&tree, (49..51), (50..51));
        assert_intersection(&tree, (49..55), (50..51));
        assert_eq!(tree.find_any(&(51..55)), None);
        assert_eq!(tree.find_any(&(52..55)), None);
        assert_eq!(tree.find_any(&(40..45)), None);
        insert_and_validate(&mut tree, 101, 102);
        insert_and_validate(&mut tree, 103, 104);
        insert_and_validate(&mut tree, 105, 106);
        insert_and_validate(&mut tree, 107, 108);
        insert_and_validate(&mut tree, 111, 112);
        insert_and_validate(&mut tree, 113, 114);
        insert_and_validate(&mut tree, 115, 116);
        insert_and_validate(&mut tree, 117, 118);
        insert_and_validate(&mut tree, 119, 129);
        assert_eq!(tree.find_any(&(112..113)), None);
        assert_eq!(tree.find_any(&(108..109)), None);
        assert_intersection(&tree, (106..108), (107..108));
    }
}
<commit_msg>Add iterator interface and entry struct<commit_after>extern crate num;

use self::num::traits::Num;

use std::cmp;
use std::mem;
use std::fmt::Debug;
use std::ops::Range;

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct IntervalTree<N, D> {
    root: Option<Node<N, D>>,
}

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Entry<'a, N: 'a, D: 'a> {
    data: &'a D,
    interval: &'a Range<N>,
}

pub struct IntervalTreeIterator<'a, N: 'a, D: 'a> {
    nodes: Vec<&'a Node<N, D>>,
    interval: Range<N>,
}

impl<'a, N: Debug + Num + Clone + Ord + 'a, D: Debug + 'a> Iterator for IntervalTreeIterator<'a, N, D> {
    type Item = Entry<'a, N, D>;

    fn next(&mut self) -> Option<Entry<'a, N, D>> {
        loop {
            let candidate = match self.nodes.pop() {
                None => return None,
                Some(node) => node,
            };
            if self.interval.end <= candidate.interval.start ||
               candidate.interval.end <= self.interval.start {
                // no overlap with current candidate, check his children
                if let Some(ref left) = candidate.left {
                    if left.max > self.interval.start {
                        self.nodes.push(left);
                    }
                }
                // TODO: make sure there isn't any unnecessary recursion here
                if let Some(ref right) = candidate.right {
                    self.nodes.push(right);
                }
            } else {
                if let Some(ref left) = candidate.left {
                    self.nodes.push(left);
                }
                if let Some(ref right) = candidate.right {
                    self.nodes.push(right);
                }
                let e = Entry {
                    data: &candidate.value,
                    interval: &candidate.interval,
                };
                return Some(e);
            }
        }
    }
}

impl<N: Debug + Num + Clone + Ord, D: Debug> IntervalTree<N, D> {
    pub fn new() -> Self {
        IntervalTree { root: None }
    }

    pub fn insert(&mut self, interval: Range<N>, data: D) {
        validate(&interval);
        match self.root {
            Some(ref mut n) => n.insert(interval, data),
            None => self.root = Some(Node::new(interval, data)),
        }
    }

    pub fn find(&self, interval: Range<N>) -> IntervalTreeIterator<N, D> {
        validate(&interval);
        match self.root {
            Some(ref n) => {
                n.find_iter(interval)
            }
            None => {
                let empty_nodes = vec![];
                IntervalTreeIterator {
                    nodes: empty_nodes,
                    interval: interval,
                }
            }
        }

    }

    pub fn find_any(&self, interval: &Range<N>) -> Option<(&Range<N>, &D)> {
        validate(&interval);
        match self.root {
            Some(ref n) => {
                let mut result = vec![];
                n.find(interval, true, &mut result);
                result.pop()
            }
            None => None,
        }
    }

    pub fn find_all(&self, interval: &Range<N>) -> Vec<(&Range<N>, &D)> {
        validate(&interval);
        match self.root {
            Some(ref n) => {
                let mut result = vec![];
                n.find(interval, true, &mut result);
                result
            }
            None => vec![],
        }
    }
}

fn validate<N: Ord + Debug>(interval: &Range<N>) {
    if interval.start >= interval.end {
        panic!("Expected interval.end > interval.start, got: ({:?})",
               interval);
    }
}

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Node<N, D> {
    // actual interval data
    interval: Range<N>,
    value: D,
    // tree metadata
    max: N,
    height: i64,
    left: Option<Box<Node<N, D>>>,
    right: Option<Box<Node<N, D>>>,
}

impl<N: Debug + Num + Clone + Ord, D: Debug> Node<N, D> {
    pub fn new(interval: Range<N>, data: D) -> Self {
        let max = interval.end.clone();
        Node {
            interval: interval,
            max: max,
            height: 1,
            value: data,
            left: None,
            right: None,
        }
    }

    pub fn insert(&mut self, interval: Range<N>, data: D) {
        if interval.start <= self.interval.start {
            if let Some(ref mut son) = self.left {
                son.insert(interval, data);
            } else {
                self.left = Some(Box::new(Node::new(interval, data)));
            }
        } else {
            if let Some(ref mut son) = self.right {
                son.insert(interval, data);
            } else {
                self.right = Some(Box::new(Node::new(interval, data)));
            }
        }
        self.repair();
    }

    pub fn find_iter<'a>(&'a self, interval: Range<N>) -> IntervalTreeIterator<'a, N, D> {
        let nodes = vec![self];
        IntervalTreeIterator {
            nodes: nodes,
            interval: interval,
        }
    }

    pub fn find<'a>(&'a self,
                    interval: &Range<N>,
                    only_one: bool,
                    result: &mut Vec<(&'a Range<N>, &'a D)>) {
        if interval.end <= self.interval.start || self.interval.end <= interval.start {
            // no overlap with current node, recur into children
            if let Some(ref left) = self.left {
                if left.max > interval.start {
                    left.find(interval, only_one, result);
                    return;
                }
            }
            if let Some(ref right) = self.right {
                right.find(interval, only_one, result);
                return;
            }
        } else {
            result.push((&self.interval, &self.value));
            if only_one {
                return;
            } else {
                if let Some(ref left) = self.left {
                    left.find(interval, only_one, result);
                }
                if let Some(ref right) = self.right {
                    right.find(interval, only_one, result);
                }
            }
        }
    }

    fn update_height(&mut self) {
        let ref left_h = self.left.as_ref().map_or(0, |n| n.height);
        let ref right_h = self.right.as_ref().map_or(0, |n| n.height);
        self.height = 1 + cmp::max(*left_h, *right_h);
    }

    fn update_max(&mut self) {
        self.max = self.interval.end.clone();
        if let Some(ref n) = self.left {
            if self.max < n.max {
                self.max = n.max.clone();
            }
        }
        if let Some(ref n) = self.right {
            if self.max < n.max {
                self.max = n.max.clone();
            }
        }
    }

    fn repair(&mut self) {
        let ref left_h = self.left.as_ref().map_or(0, |n| n.height);
        let ref right_h = self.right.as_ref().map_or(0, |n| n.height);
        // each case - update both height and max
        if (left_h - right_h).abs() <= 1 {
            self.update_height();
            self.update_max();
        } else if right_h > left_h {
            {
                let mut right =
                    self.right.as_mut().expect("Invalid tree: leaf is taller than its sibling.");
                let ref right_left_h = right.left.as_ref().map_or(0, |n| n.height);
                let ref right_right_h = right.right.as_ref().map_or(0, |n| n.height);
                if right_left_h > right_right_h {
                    right.rotate_right();
                }
            }
            self.rotate_left();
        } else {
            {
                let mut left =
                    self.left.as_mut().expect("Invalid tree: leaf is taller than its sibling.");
                let ref left_right_h = left.right.as_ref().map_or(0, |n| n.height);
                let ref left_left_h = left.left.as_ref().map_or(0, |n| n.height);
                if left_right_h > left_left_h {
                    println!("double rot");
                    left.rotate_left();
                }
            }
            self.rotate_right();
        }
    }

    fn rotate_left(&mut self) {
        let mut new_root = self.right.take().unwrap();
        let t1 = self.left.take();
        let t2 = new_root.left.take();
        let t3 = new_root.right.take();
        swap_interval_data(self, &mut *new_root);

        new_root.left = t1;
        new_root.right = t2;
        new_root.update_height();
        new_root.update_max();

        self.right = t3;
        self.left = Some(new_root);
        self.update_height();
        self.update_max();
    }

    fn rotate_right(&mut self) {
        let mut new_root = self.left.take().unwrap();
        let t1 = new_root.left.take();
        let t2 = new_root.right.take();
        let t3 = self.right.take();
        swap_interval_data(self, &mut *new_root);

        new_root.left = t2;
        new_root.right = t3;
        new_root.update_height();
        new_root.update_max();

        self.left = t1;
        self.right = Some(new_root);
        self.update_height();
        self.update_max();
    }
}

fn swap_interval_data<N, D>(node_1: &mut Node<N, D>, node_2: &mut Node<N, D>) {
    mem::swap(&mut node_1.value, &mut node_2.value);
    mem::swap(&mut node_1.interval, &mut node_2.interval);
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::cmp;
    use std::ops::Range;

    fn validate(node: &Node<i64, String>) {
        validate_height(node);
        validate_intervals(node);
        validate_string_metadata(node);
        node.left.as_ref().map(|n| validate(n));
        node.right.as_ref().map(|n| validate(n));
    }

    fn validate_height(node: &Node<i64, String>) {
        let ref left_height = node.left.as_ref().map_or(0, |n| n.height);
        let ref right_height = node.right.as_ref().map_or(0, |n| n.height);
        assert!((left_height - right_height).abs() <= 1);
        assert_eq!(node.height, cmp::max(left_height, right_height) + 1)
    }

    fn validate_intervals(node: &Node<i64, String>) {
        let mut reached_maximum: bool = false;
        if node.interval.end == node.max {
            reached_maximum = true;
        }
        if let Some(ref son) = node.left {
            if !(son.max <= node.max) {
                panic!("left max invariant violated:\n{:?} -> {:?}", node, son);
            }
            if !(son.interval.start <= node.interval.start) {
                panic!("left ord invariant violated\n{:?} -> {:?}", node, son);
            }
            if node.max == son.max {
                reached_maximum = true;
            }
        }
        if let Some(ref son) = node.right {
            if !(son.max <= node.max) {
                panic!("right max invariant violated\n{:?} -> {:?}", node, son);
            }

            if !(son.interval.start >= node.interval.start) {
                panic!("right ord invariant violated\n{:?} -> {:?}", node, son);
            }
            if node.max == son.max {
                reached_maximum = true;
            }
        }
        if !reached_maximum {
            panic!("maximum invariant violated: {:?}", node);
        }
    }

    fn validate_string_metadata(node: &Node<i64, String>) {
        let mut name: String = "".to_string();
        name.push_str(&node.interval.start.to_string());
        name.push_str(":");
        name.push_str(&node.interval.end.to_string());
        if name != node.value {
            panic!("Invalid metadata for node {:?}", node);
        }
    }

    fn insert_and_validate(tree: &mut IntervalTree<i64, String>, start: i64, end: i64) {
        let mut name: String = "".to_string();
        name.push_str(&start.to_string());
        name.push_str(":");
        name.push_str(&end.to_string());
        tree.insert((start..end), name);
        if let Some(ref n) = tree.root {
            validate(n);
        }
    }

    fn assert_intersection(tree: &IntervalTree<i64, String>,
                           target: Range<i64>,
                           expected_bounds: Range<i64>) {
        let mut expected_data: String = "".to_string();
        expected_data.push_str(&expected_bounds.start.to_string());
        expected_data.push_str(":");
        expected_data.push_str(&expected_bounds.end.to_string());
        if let Some((actual_bounds, actual_data)) = tree.find_any(&target) {
            assert_eq!(&expected_data.to_string(), actual_data);
            assert_eq!(&expected_bounds, actual_bounds);
        } else {
            panic!("Expected to find {:?} in the tree", expected_bounds);
        }
    }

    #[test]
    fn test_insertion_and_intersection() {
        let mut tree: IntervalTree<i64, String> = IntervalTree::new();
        tree.insert((50..51), "50:51".to_string());
        assert_eq!(tree.find_any(&(49..50)), None);
        assert_intersection(&tree, (49..55), (50..51));
        assert_eq!(tree.find_any(&(51..55)), None);
        assert_eq!(tree.find_any(&(52..55)), None);
        assert_eq!(tree.find_any(&(40..45)), None);
        insert_and_validate(&mut tree, 80, 81);
        assert_intersection(&tree, (80..83), (80..81));
        assert_eq!(tree.find_any(&(82..83)), None);
        insert_and_validate(&mut tree, 30, 35);
        assert_intersection(&tree, (25..33), (30..35));
        assert_eq!(tree.find_any(&(42..43)), None);
        assert_eq!(tree.find_any(&(35..36)), None);
        assert_eq!(tree.find_any(&(22..29)), None);
        insert_and_validate(&mut tree, 70, 77);
        assert_intersection(&tree, (75..79), (70..77));
        assert_eq!(tree.find_any(&(62..68)), None);
        assert_intersection(&tree, (75..77), (70..77));
        assert_eq!(tree.find_any(&(78..79)), None);
        assert_intersection(&tree, (49..51), (50..51));
        assert_intersection(&tree, (49..55), (50..51));
        assert_eq!(tree.find_any(&(51..55)), None);
        assert_eq!(tree.find_any(&(52..55)), None);
        assert_eq!(tree.find_any(&(40..45)), None);
        insert_and_validate(&mut tree, 101, 102);
        insert_and_validate(&mut tree, 103, 104);
        insert_and_validate(&mut tree, 105, 106);
        insert_and_validate(&mut tree, 107, 108);
        insert_and_validate(&mut tree, 111, 112);
        insert_and_validate(&mut tree, 113, 114);
        insert_and_validate(&mut tree, 115, 116);
        insert_and_validate(&mut tree, 117, 118);
        insert_and_validate(&mut tree, 119, 129);
        assert_eq!(tree.find_any(&(112..113)), None);
        assert_eq!(tree.find_any(&(108..109)), None);
        assert_intersection(&tree, (106..108), (107..108));
    }
}
<|endoftext|>


<commit_before>//! Integration tests for rustfmt.

use std::env;
use std::fs::remove_file;
use std::path::Path;
use std::process::Command;

/// Run the rustfmt executable and return its output.
fn rustfmt(args: &[&str]) -> (String, String) {
    let mut bin_dir = env::current_exe().unwrap();
    bin_dir.pop(); // chop off test exe name
    if bin_dir.ends_with("deps") {
        bin_dir.pop();
    }
    let cmd = bin_dir.join(format!("rustfmt{}", env::consts::EXE_SUFFIX));

    // Ensure the rustfmt binary runs from the local target dir.
    let path = env::var_os("PATH").unwrap_or_default();
    let mut paths = env::split_paths(&path).collect::<Vec<_>>();
    paths.insert(0, bin_dir);
    let new_path = env::join_paths(paths).unwrap();

    match Command::new(&cmd).args(args).env("PATH", new_path).output() {
        Ok(output) => (
            String::from_utf8(output.stdout).expect("utf-8"),
            String::from_utf8(output.stderr).expect("utf-8"),
        ),
        Err(e) => panic!("failed to run `{:?} {:?}`: {}", cmd, args, e),
    }
}

macro_rules! assert_that {
    ($args:expr, $($check:ident $check_args:tt)&&+) => {
        let (stdout, stderr) = rustfmt($args);
        if $(!stdout.$check$check_args && !stderr.$check$check_args)||* {
            panic!(
                "Output not expected for rustfmt {:?}\n\
                 expected: {}\n\
                 actual stdout:\n{}\n\
                 actual stderr:\n{}",
                $args,
                stringify!($( $check$check_args )&&*),
                stdout,
                stderr
            );
        }
    };
}

#[ignore]
#[test]
fn print_config() {
    assert_that!(
        &["--print-config", "unknown"],
        starts_with("Unknown print-config option")
    );
    assert_that!(&["--print-config", "default"], contains("max_width = 100"));
    assert_that!(&["--print-config", "minimal"], contains("PATH required"));
    assert_that!(
        &["--print-config", "minimal", "minimal-config"],
        contains("doesn't work with standard input.")
    );

    let (stdout, stderr) = rustfmt(&[
        "--print-config",
        "minimal",
        "minimal-config",
        "src/shape.rs",
    ]);
    assert!(
        Path::new("minimal-config").exists(),
        "stdout:\n{}\nstderr:\n{}",
        stdout,
        stderr
    );
    remove_file("minimal-config").unwrap();
}

#[ignore]
#[test]
fn inline_config() {
    // single invocation
    assert_that!(
        &[
            "--print-config",
            "current",
            ".",
            "--config=color=Never,edition=2018"
        ],
        contains("color = \"Never\"") && contains("edition = \"2018\"")
    );

    // multiple overriding invocations
    assert_that!(
        &["--print-config", "current", ".",
        "--config", "color=never,edition=2018",
        "--config", "color=always,format_strings=true"],
        contains("color = \"Always\"") &&
        contains("edition = \"2018\"") &&
        contains("format_strings = true")
    );
}
<commit_msg>Cargo fmt<commit_after>//! Integration tests for rustfmt.

use std::env;
use std::fs::remove_file;
use std::path::Path;
use std::process::Command;

/// Run the rustfmt executable and return its output.
fn rustfmt(args: &[&str]) -> (String, String) {
    let mut bin_dir = env::current_exe().unwrap();
    bin_dir.pop(); // chop off test exe name
    if bin_dir.ends_with("deps") {
        bin_dir.pop();
    }
    let cmd = bin_dir.join(format!("rustfmt{}", env::consts::EXE_SUFFIX));

    // Ensure the rustfmt binary runs from the local target dir.
    let path = env::var_os("PATH").unwrap_or_default();
    let mut paths = env::split_paths(&path).collect::<Vec<_>>();
    paths.insert(0, bin_dir);
    let new_path = env::join_paths(paths).unwrap();

    match Command::new(&cmd).args(args).env("PATH", new_path).output() {
        Ok(output) => (
            String::from_utf8(output.stdout).expect("utf-8"),
            String::from_utf8(output.stderr).expect("utf-8"),
        ),
        Err(e) => panic!("failed to run `{:?} {:?}`: {}", cmd, args, e),
    }
}

macro_rules! assert_that {
    ($args:expr, $($check:ident $check_args:tt)&&+) => {
        let (stdout, stderr) = rustfmt($args);
        if $(!stdout.$check$check_args && !stderr.$check$check_args)||* {
            panic!(
                "Output not expected for rustfmt {:?}\n\
                 expected: {}\n\
                 actual stdout:\n{}\n\
                 actual stderr:\n{}",
                $args,
                stringify!($( $check$check_args )&&*),
                stdout,
                stderr
            );
        }
    };
}

#[ignore]
#[test]
fn print_config() {
    assert_that!(
        &["--print-config", "unknown"],
        starts_with("Unknown print-config option")
    );
    assert_that!(&["--print-config", "default"], contains("max_width = 100"));
    assert_that!(&["--print-config", "minimal"], contains("PATH required"));
    assert_that!(
        &["--print-config", "minimal", "minimal-config"],
        contains("doesn't work with standard input.")
    );

    let (stdout, stderr) = rustfmt(&[
        "--print-config",
        "minimal",
        "minimal-config",
        "src/shape.rs",
    ]);
    assert!(
        Path::new("minimal-config").exists(),
        "stdout:\n{}\nstderr:\n{}",
        stdout,
        stderr
    );
    remove_file("minimal-config").unwrap();
}

#[ignore]
#[test]
fn inline_config() {
    // single invocation
    assert_that!(
        &[
            "--print-config",
            "current",
            ".",
            "--config=color=Never,edition=2018"
        ],
        contains("color = \"Never\"") && contains("edition = \"2018\"")
    );

    // multiple overriding invocations
    assert_that!(
        &[
            "--print-config",
            "current",
            ".",
            "--config",
            "color=never,edition=2018",
            "--config",
            "color=always,format_strings=true"
        ],
        contains("color = \"Always\"")
            && contains("edition = \"2018\"")
            && contains("format_strings = true")
    );
}
<|endoftext|>


<commit_before>extern crate eventual;
extern crate sbahn;

use eventual::*;
use sbahn::client;
use sbahn::handler;
use sbahn::message::*;
use sbahn::storage::HashMapBackend;
use sbahn::storage_node::StorageNode;
use std::net::{Ipv4Addr, SocketAddrV4};
use std::thread;

static mut port: u16 = 1200;
fn get_port() -> u16 {
    let mut p = 0;
    unsafe {
        port += 1;
        p = port;
    }
    p
}

fn get_storage_node<'a>(pos: usize, shard_count: usize) -> SocketAddrV4 {
    let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), get_port());
    let mut sn: StorageNode<HashMapBackend> = StorageNode::new(&addr, pos, shard_count);
    thread::spawn(move || {
        &sn.listen();
    });
    thread::sleep_ms(100);  // Wait for storage node to start listening
    addr
}

#[test]
fn single_node() {
    let addr = get_storage_node(0, 1);

    let insert_key = Key {
        dataset: vec![1, 2, 3],
        pkey: vec![4, 5, 6],
        lkey: vec![7, 8, 9],
    };
    {
        let content = InternodeRequest::Write {
            key: insert_key.to_owned(),
            value: Value::Value {
                content: vec![1],
                timestamp: 10000000,
            },
        };
        let addr = &addr.to_owned();
        let r: Future<Result<InternodeResponse>, ()> = client::Client::send_to_node(addr, &content);
        let r = r.await().unwrap();
        match r {
            Ok(r) => match r {
                InternodeResponse::WriteAck {key, timestamp} => {
                    assert_eq!(key, insert_key);
                    assert_eq!(timestamp, 10000000);
                },
                e => {println!("{:?}", e); assert!(false)},
            },
            Err(_) => assert!(false),
        }
    }
    {
        let content = InternodeRequest::Read {
            key: insert_key.to_owned(),
        };
        let addr = &addr.to_owned();
        let r: Future<Result<InternodeResponse>, ()> = client::Client::send_to_node(addr, &content);
        let r = r.await().unwrap();
        match r {
            Ok(r) => match r {
                InternodeResponse::Value {key, value} => {
                    assert_eq!(key, insert_key);
                    match value {
                        Value::Value {content, timestamp} => {
                            assert_eq!(&content[..], &[1][..]);
                            assert_eq!(timestamp, 10000000);
                        },
                        _ => assert!(false),
                    }
                },
                _ => assert!(false),
            },
            Err(_) => assert!(false),
        }
    }
}

#[test]
fn read_my_writes() {
    let mut shards: Vec<Vec<SocketAddrV4>> = vec![];
    for i in 0..3 {
        let mut shard: Vec<SocketAddrV4> = vec![];
        for _ in 0..3 {
            shard.push(get_storage_node(i, 3));
        }
        shards.push(shard);
    }

    let e = &shards;
    let z = e.clone();
    let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), get_port());
    thread::spawn(move || {
        let _shards = &z.to_owned();
        let _ = handler::listen(&addr, &_shards);
    });
    thread::sleep_ms(100);  // Wait for handler node to start listening

    {
        let insert_key = Key {
            dataset: vec![1, 2, 3],
            pkey: vec![4, 5, 6],
            lkey: vec![7, 8, 9],
        };
        let client = client::Client { handlers: vec![addr] };
        {
            let content = Request {
                action: Action::Write {
                    key: insert_key.to_owned(),
                    content: vec![1],
                },
                consistency: Consistency::Latest,
            };
            let r = client.send(&content);
            let r = r.await().unwrap();
            match r {
                Ok(r) => match r.message {
                    Response::WriteAck {key, ..} => assert_eq!(key, insert_key),
                    _ => assert!(false),
                },
                Err(_) => assert!(false),
            }
        }
        {
            let content = Request {
                action: Action::Read {
                    key: insert_key.to_owned(),
                },
                consistency: Consistency::Latest,
            };
            let r = client.send(&content);
            let r = r.await().unwrap();
            match r {
                Ok(r) => match r.message {
                    Response::Value {key, value} => {
                        assert_eq!(key, insert_key);
                        match value {
                            Value::Value {content, ..} => assert_eq!(&content[..], &vec![1][..]),
                            _ => assert!(false),
                        }
                    },
                    _ => assert!(false),
                },
                Err(_) => assert!(false),
            }
        }
        {
            let content = Request {
                action: Action::Delete {
                    key: insert_key.to_owned(),
                },
                consistency: Consistency::Latest,
            };
            let r = client.send(&content);
            let r = r.await().unwrap();
            match r {
                Ok(r) => match r.message {
                    Response::WriteAck {key, ..} => assert_eq!(key, insert_key),
                    _ => assert!(false),
                },
                Err(_) => assert!(false),
            }
        }
        {
            let content = Request {
                action: Action::Read {
                    key: insert_key.to_owned(),
                },
                consistency: Consistency::Latest,
            };
            let r = client.send(&content);
            let r = r.await().unwrap();
            match r {
                Ok(r) => match r.message {
                    Response::Value {key, value} => {
                        assert_eq!(key, insert_key);
                        match value {
                            Value::Tombstone {..} => assert!(true),
                            _ => assert!(false),
                        }
                    },
                    _ => assert!(false),
                },
                Err(_) => assert!(false),
            }
        }
    }
}
<commit_msg>Fix more warnings<commit_after>extern crate eventual;
extern crate sbahn;

use eventual::*;
use sbahn::client;
use sbahn::handler;
use sbahn::message::*;
use sbahn::storage::HashMapBackend;
use sbahn::storage_node::StorageNode;
use std::net::{Ipv4Addr, SocketAddrV4};
use std::thread;
use std::time::Duration;

static mut port: u16 = 1200;
fn get_port() -> u16 {
    let p;
    unsafe {
        port += 1;
        p = port;
    }
    p
}

fn get_storage_node<'a>(pos: usize, shard_count: usize) -> SocketAddrV4 {
    let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), get_port());
    let mut sn: StorageNode<HashMapBackend> = StorageNode::new(&addr, pos, shard_count);
    thread::spawn(move || {
        &sn.listen();
    });
    thread::sleep(Duration::from_millis(100));  // Wait for storage node to start listening
    addr
}

#[test]
fn single_node() {
    let addr = get_storage_node(0, 1);

    let insert_key = Key {
        dataset: vec![1, 2, 3],
        pkey: vec![4, 5, 6],
        lkey: vec![7, 8, 9],
    };
    {
        let content = InternodeRequest::Write {
            key: insert_key.to_owned(),
            value: Value::Value {
                content: vec![1],
                timestamp: 10000000,
            },
        };
        let addr = &addr.to_owned();
        let r: Future<Result<InternodeResponse>, ()> = client::Client::send_to_node(addr, &content);
        let r = r.await().unwrap();
        match r {
            Ok(r) => match r {
                InternodeResponse::WriteAck {key, timestamp} => {
                    assert_eq!(key, insert_key);
                    assert_eq!(timestamp, 10000000);
                },
                e => {println!("{:?}", e); assert!(false)},
            },
            Err(_) => assert!(false),
        }
    }
    {
        let content = InternodeRequest::Read {
            key: insert_key.to_owned(),
        };
        let addr = &addr.to_owned();
        let r: Future<Result<InternodeResponse>, ()> = client::Client::send_to_node(addr, &content);
        let r = r.await().unwrap();
        match r {
            Ok(r) => match r {
                InternodeResponse::Value {key, value} => {
                    assert_eq!(key, insert_key);
                    match value {
                        Value::Value {content, timestamp} => {
                            assert_eq!(&content[..], &[1][..]);
                            assert_eq!(timestamp, 10000000);
                        },
                        _ => assert!(false),
                    }
                },
                _ => assert!(false),
            },
            Err(_) => assert!(false),
        }
    }
}

#[test]
fn read_my_writes() {
    let mut shards: Vec<Vec<SocketAddrV4>> = vec![];
    for i in 0..3 {
        let mut shard: Vec<SocketAddrV4> = vec![];
        for _ in 0..3 {
            shard.push(get_storage_node(i, 3));
        }
        shards.push(shard);
    }

    let e = &shards;
    let z = e.clone();
    let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), get_port());
    thread::spawn(move || {
        let _shards = &z.to_owned();
        let _ = handler::listen(&addr, &_shards);
    });
    thread::sleep(Duration::from_millis(100));  // Wait for handler node to start listening

    {
        let insert_key = Key {
            dataset: vec![1, 2, 3],
            pkey: vec![4, 5, 6],
            lkey: vec![7, 8, 9],
        };
        let client = client::Client { handlers: vec![addr] };
        {
            let content = Request {
                action: Action::Write {
                    key: insert_key.to_owned(),
                    content: vec![1],
                },
                consistency: Consistency::Latest,
            };
            let r = client.send(&content);
            let r = r.await().unwrap();
            match r {
                Ok(r) => match r.message {
                    Response::WriteAck {key, ..} => assert_eq!(key, insert_key),
                    _ => assert!(false),
                },
                Err(_) => assert!(false),
            }
        }
        {
            let content = Request {
                action: Action::Read {
                    key: insert_key.to_owned(),
                },
                consistency: Consistency::Latest,
            };
            let r = client.send(&content);
            let r = r.await().unwrap();
            match r {
                Ok(r) => match r.message {
                    Response::Value {key, value} => {
                        assert_eq!(key, insert_key);
                        match value {
                            Value::Value {content, ..} => assert_eq!(&content[..], &vec![1][..]),
                            _ => assert!(false),
                        }
                    },
                    _ => assert!(false),
                },
                Err(_) => assert!(false),
            }
        }
        {
            let content = Request {
                action: Action::Delete {
                    key: insert_key.to_owned(),
                },
                consistency: Consistency::Latest,
            };
            let r = client.send(&content);
            let r = r.await().unwrap();
            match r {
                Ok(r) => match r.message {
                    Response::WriteAck {key, ..} => assert_eq!(key, insert_key),
                    _ => assert!(false),
                },
                Err(_) => assert!(false),
            }
        }
        {
            let content = Request {
                action: Action::Read {
                    key: insert_key.to_owned(),
                },
                consistency: Consistency::Latest,
            };
            let r = client.send(&content);
            let r = r.await().unwrap();
            match r {
                Ok(r) => match r.message {
                    Response::Value {key, value} => {
                        assert_eq!(key, insert_key);
                        match value {
                            Value::Tombstone {..} => assert!(true),
                            _ => assert!(false),
                        }
                    },
                    _ => assert!(false),
                },
                Err(_) => assert!(false),
            }
        }
    }
}
<|endoftext|>


<commit_before>use svm::cell::SVMCell;
use svm::slist::List;

/// Trait for AST nodes.
pub trait ASTNode {
    /// Compile this node to a list of SVM expressions
    fn compile(self)                    -> Result<SVMCell, &'static str>;

    /// Pretty-print this node
    fn prettyprint(&self)               -> String { self.print_level(0usize) }

    /// Pretty-print this node at the desired indent level
    fn print_level(&self, level: usize) -> String;
}

/// Expression
///
/// All Seax Scheme expressions are one of the following
///  + Nested S-Expressions
///  + Identifiers
///  + Lists
///  + Numbers
///     - signed int
///     - unsigned int
///     - floating-point
///  + Characters
///  + Strings
///  TODO: implement the entire Scheme 'numeric tower'
///  TODO: macros should happen
#[derive(Clone, PartialEq)]
pub enum ExprNode {
    Root(RootNode),
    SExpr(SExprNode),
    Name(NameNode),
    List(ListNode),
    IntConst(IntNode),
    UIntConst(UIntNode),
    FloatConst(FloatNode),
    BoolConst(BoolNode),
    StringConst(StringNode),
    CharConst(CharNode),
}

/// AST node for the root of a program's AST
#[derive(Clone, PartialEq)]
pub struct RootNode { pub exprs: Vec<ExprNode> }

/// AST node for an S-expression.
///
/// This includes function application, assignment,
/// function definition, et cetera...Scheme is not a complexl anguage.
#[derive(Clone, PartialEq)]
pub struct SExprNode {
    pub operator: NameNode,
    pub operands: Vec<ExprNode>,
}

/// AST node for a list literal
#[derive(Clone, PartialEq)]
pub struct ListNode { pub elements: Vec<ExprNode> }

/// AST node for an identifier
#[derive(Clone, PartialEq)]
pub struct NameNode { pub name: String }

/// AST node for an integer constant
#[derive(Clone, PartialEq)]
pub struct IntNode { pub value: isize }

/// AST node for an unsigned integer constant
#[derive(Clone, PartialEq)]
pub struct UIntNode { pub value: usize }

/// AST node for a floating-point constant
#[derive(Clone, PartialEq)]
pub struct FloatNode { pub value: f64 }

/// AST node for a boolean constant
#[derive(Clone, PartialEq)]
pub struct BoolNode { pub value: bool }

/// AST node for a character constant
#[derive(Clone, PartialEq)]
pub struct CharNode { pub value: char }

<commit_msg>Add string AST node<commit_after>use svm::cell::SVMCell;
use svm::slist::List;

/// Trait for AST nodes.
pub trait ASTNode {
    /// Compile this node to a list of SVM expressions
    fn compile(self)                    -> Result<SVMCell, &'static str>;

    /// Pretty-print this node
    fn prettyprint(&self)               -> String { self.print_level(0usize) }

    /// Pretty-print this node at the desired indent level
    fn print_level(&self, level: usize) -> String;
}

/// Expression
///
/// All Seax Scheme expressions are one of the following
///  + Nested S-Expressions
///  + Identifiers
///  + Lists
///  + Numbers
///     - signed int
///     - unsigned int
///     - floating-point
///  + Characters
///  + Strings
///  TODO: implement the entire Scheme 'numeric tower'
///  TODO: macros should happen
#[derive(Clone, PartialEq)]
pub enum ExprNode {
    Root(RootNode),
    SExpr(SExprNode),
    Name(NameNode),
    List(ListNode),
    IntConst(IntNode),
    UIntConst(UIntNode),
    FloatConst(FloatNode),
    BoolConst(BoolNode),
    StringConst(StringNode),
    CharConst(CharNode),
}

/// AST node for the root of a program's AST
#[derive(Clone, PartialEq)]
pub struct RootNode { pub exprs: Vec<ExprNode> }

/// AST node for an S-expression.
///
/// This includes function application, assignment,
/// function definition, et cetera...Scheme is not a complexl anguage.
#[derive(Clone, PartialEq)]
pub struct SExprNode {
    pub operator: NameNode,
    pub operands: Vec<ExprNode>,
}

/// AST node for a list literal
#[derive(Clone, PartialEq)]
pub struct ListNode { pub elements: Vec<ExprNode> }

/// AST node for an identifier
#[derive(Clone, PartialEq)]
pub struct NameNode { pub name: String }

/// AST node for an integer constant
#[derive(Clone, PartialEq)]
pub struct IntNode { pub value: isize }

/// AST node for an unsigned integer constant
#[derive(Clone, PartialEq)]
pub struct UIntNode { pub value: usize }

/// AST node for a floating-point constant
#[derive(Clone, PartialEq)]
pub struct FloatNode { pub value: f64 }

/// AST node for a boolean constant
#[derive(Clone, PartialEq)]
pub struct BoolNode { pub value: bool }

/// AST node for a character constant
#[derive(Clone, PartialEq)]
pub struct CharNode { pub value: char }

/// AST node for a  string constant
#[derive(Clone, PartialEq)]
pub struct StringNode { pub value: String }

<|endoftext|>


<commit_before>use std::fmt::Display;
use thiserror::Error;

fn assert<T: Display>(expected: &str, value: T) {
    assert_eq!(expected, value.to_string());
}

#[test]
fn test_braced() {
    #[derive(Error, Debug)]
    #[error("braced error: {msg}")]
    struct Error {
        msg: String,
    }

    let msg = "T".to_owned();
    assert("braced error: T", Error { msg });
}

#[test]
fn test_braced_unused() {
    #[derive(Error, Debug)]
    #[error("braced error")]
    struct Error {
        extra: usize,
    }

    assert("braced error", Error { extra: 0 });
}

#[test]
fn test_tuple() {
    #[derive(Error, Debug)]
    #[error("tuple error: {0}")]
    struct Error(usize);

    assert("tuple error: 0", Error(0));
}

#[test]
fn test_unit() {
    #[derive(Error, Debug)]
    #[error("unit error")]
    struct Error;

    assert("unit error", Error);
}

#[test]
fn test_enum() {
    #[derive(Error, Debug)]
    enum Error {
        #[error("braced error: {id}")]
        Braced { id: usize },
        #[error("tuple error: {0}")]
        Tuple(usize),
        #[error("unit error")]
        Unit,
    }

    assert("braced error: 0", Error::Braced { id: 0 });
    assert("tuple error: 0", Error::Tuple(0));
    assert("unit error", Error::Unit);
}

#[test]
fn test_constants() {
    #[derive(Error, Debug)]
    #[error("{MSG}: {id:?} (code {CODE:?})")]
    struct Error {
        id: &'static str,
    }

    const MSG: &str = "failed to do";
    const CODE: usize = 9;

    assert("failed to do: \"\" (code 9)", Error { id: "" });
}

#[test]
fn test_inherit() {
    #[derive(Error, Debug)]
    #[error("{0}")]
    enum Error {
        Some(&'static str),
        #[error("other error")]
        Other(&'static str),
    }

    assert("some error", Error::Some("some error"));
    assert("other error", Error::Other("..."));
}

#[test]
fn test_brace_escape() {
    #[derive(Error, Debug)]
    #[error("fn main() {{}}")]
    struct Error;

    assert("fn main() {}", Error);
}

#[test]
fn test_expr() {
    #[derive(Error, Debug)]
    #[error("1 + 1 = {}", 1 + 1)]
    struct Error;
    assert("1 + 1 = 2", Error);
}

#[test]
fn test_nested() {
    #[derive(Error, Debug)]
    #[error("!bool = {}", not(.0))]
    struct Error(bool);

    fn not(bool: &bool) -> bool {
        !*bool
    }

    assert("!bool = false", Error(true));
}

#[test]
fn test_match() {
    #[derive(Error, Debug)]
    #[error("{}: {0}", match .1 {
        Some(n) => format!("error occurred with {}", n),
        None => format!("there was an empty error"),
    })]
    struct Error(String, Option<usize>);

    assert("error occurred with 1: ...", Error("...".to_owned(), Some(1)));
    assert("there was an empty error: ...", Error("...".to_owned(), None));
}

#[test]
fn test_void() {
    #[derive(Error, Debug)]
    #[error("...")]
    pub enum Error {}
}

#[test]
fn test_mixed() {
    #[derive(Error, Debug)]
    #[error("a={a} :: b={} :: c={c} :: d={d}", 1, c = 2, d = 3)]
    struct Error {
        a: usize,
        d: usize,
    }

    assert("a=0 :: b=1 :: c=2 :: d=3", Error { a: 0, d: 0 });
}

#[test]
fn test_ints() {
    #[derive(Error, Debug)]
    enum Error {
        #[error("error {0}")]
        Tuple(usize, usize),
        #[error("error {0}", '?')]
        Struct { v: usize },
    }

    assert("error 9", Error::Tuple(9, 0));
    assert("error ?", Error::Struct { v: 0 });
}

#[test]
fn test_trailing_comma() {
    #[derive(Error, Debug)]
    #[error(
        "error {0}",
    )]
    #[rustfmt::skip]
    struct Error(char);

    assert("error ?", Error('?'));
}

#[test]
fn test_field() {
    #[derive(Debug)]
    struct Inner {
        data: usize,
    }

    #[derive(Error, Debug)]
    #[error("{}", .0.data)]
    struct Error(Inner);

    assert("0", Error(Inner { data: 0 }));
}
<commit_msg>Format with rustfmt 2019-10-07<commit_after>use std::fmt::Display;
use thiserror::Error;

fn assert<T: Display>(expected: &str, value: T) {
    assert_eq!(expected, value.to_string());
}

#[test]
fn test_braced() {
    #[derive(Error, Debug)]
    #[error("braced error: {msg}")]
    struct Error {
        msg: String,
    }

    let msg = "T".to_owned();
    assert("braced error: T", Error { msg });
}

#[test]
fn test_braced_unused() {
    #[derive(Error, Debug)]
    #[error("braced error")]
    struct Error {
        extra: usize,
    }

    assert("braced error", Error { extra: 0 });
}

#[test]
fn test_tuple() {
    #[derive(Error, Debug)]
    #[error("tuple error: {0}")]
    struct Error(usize);

    assert("tuple error: 0", Error(0));
}

#[test]
fn test_unit() {
    #[derive(Error, Debug)]
    #[error("unit error")]
    struct Error;

    assert("unit error", Error);
}

#[test]
fn test_enum() {
    #[derive(Error, Debug)]
    enum Error {
        #[error("braced error: {id}")]
        Braced { id: usize },
        #[error("tuple error: {0}")]
        Tuple(usize),
        #[error("unit error")]
        Unit,
    }

    assert("braced error: 0", Error::Braced { id: 0 });
    assert("tuple error: 0", Error::Tuple(0));
    assert("unit error", Error::Unit);
}

#[test]
fn test_constants() {
    #[derive(Error, Debug)]
    #[error("{MSG}: {id:?} (code {CODE:?})")]
    struct Error {
        id: &'static str,
    }

    const MSG: &str = "failed to do";
    const CODE: usize = 9;

    assert("failed to do: \"\" (code 9)", Error { id: "" });
}

#[test]
fn test_inherit() {
    #[derive(Error, Debug)]
    #[error("{0}")]
    enum Error {
        Some(&'static str),
        #[error("other error")]
        Other(&'static str),
    }

    assert("some error", Error::Some("some error"));
    assert("other error", Error::Other("..."));
}

#[test]
fn test_brace_escape() {
    #[derive(Error, Debug)]
    #[error("fn main() {{}}")]
    struct Error;

    assert("fn main() {}", Error);
}

#[test]
fn test_expr() {
    #[derive(Error, Debug)]
    #[error("1 + 1 = {}", 1 + 1)]
    struct Error;
    assert("1 + 1 = 2", Error);
}

#[test]
fn test_nested() {
    #[derive(Error, Debug)]
    #[error("!bool = {}", not(.0))]
    struct Error(bool);

    fn not(bool: &bool) -> bool {
        !*bool
    }

    assert("!bool = false", Error(true));
}

#[test]
fn test_match() {
    #[derive(Error, Debug)]
    #[error("{}: {0}", match .1 {
        Some(n) => format!("error occurred with {}", n),
        None => format!("there was an empty error"),
    })]
    struct Error(String, Option<usize>);

    assert(
        "error occurred with 1: ...",
        Error("...".to_owned(), Some(1)),
    );
    assert(
        "there was an empty error: ...",
        Error("...".to_owned(), None),
    );
}

#[test]
fn test_void() {
    #[derive(Error, Debug)]
    #[error("...")]
    pub enum Error {}
}

#[test]
fn test_mixed() {
    #[derive(Error, Debug)]
    #[error("a={a} :: b={} :: c={c} :: d={d}", 1, c = 2, d = 3)]
    struct Error {
        a: usize,
        d: usize,
    }

    assert("a=0 :: b=1 :: c=2 :: d=3", Error { a: 0, d: 0 });
}

#[test]
fn test_ints() {
    #[derive(Error, Debug)]
    enum Error {
        #[error("error {0}")]
        Tuple(usize, usize),
        #[error("error {0}", '?')]
        Struct { v: usize },
    }

    assert("error 9", Error::Tuple(9, 0));
    assert("error ?", Error::Struct { v: 0 });
}

#[test]
fn test_trailing_comma() {
    #[derive(Error, Debug)]
    #[error(
        "error {0}",
    )]
    #[rustfmt::skip]
    struct Error(char);

    assert("error ?", Error('?'));
}

#[test]
fn test_field() {
    #[derive(Debug)]
    struct Inner {
        data: usize,
    }

    #[derive(Error, Debug)]
    #[error("{}", .0.data)]
    struct Error(Inner);

    assert("0", Error(Inner { data: 0 }));
}
<|endoftext|>


<commit_before>// Copyright 2014 The html5ever Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use util::foreach_html5lib_test;

use std::io;
use std::mem::replace;
use std::default::Default;
use std::path::Path;
use std::collections::hashmap::HashMap;
use std::vec::MoveItems;
use test::{TestDesc, TestDescAndFn, DynTestName, DynTestFn};

use html5ever::sink::common::{Document, Doctype, Text, Comment, Element};
use html5ever::sink::rcdom::{RcDom, Handle};
use html5ever::{parse, one_input};

fn parse_tests<It: Iterator<String>>(mut lines: It) -> Vec<HashMap<String, String>> {
    let mut tests = vec!();
    let mut test = HashMap::new();
    let mut key = None;
    let mut val = String::new();

    macro_rules! finish_val ( () => (
        match key.take() {
            None => (),
            Some(key) => assert!(test.insert(key, replace(&mut val, String::new()))),
        }
    ))

    macro_rules! finish_test ( () => (
        if !test.is_empty() {
            tests.push(replace(&mut test, HashMap::new()));
        }
    ))

    loop {
        match lines.next() {
            None => break,
            Some(line) => {
                if line.as_slice().starts_with("#") {
                    finish_val!();
                    if line.as_slice() == "#data\n" {
                        finish_test!();
                    }
                    key = Some(line.as_slice().slice_from(1)
                        .trim_right_chars('\n').to_string());
                } else {
                    val.push_str(line.as_slice());
                }
            }
        }
    }

    finish_val!();
    finish_test!();
    tests
}

fn serialize(buf: &mut String, indent: uint, handle: Handle) {
    buf.push_str("|");
    buf.grow(indent, ' ');

    let node = handle.borrow();
    match node.node {
        Document => fail!("should not reach Document"),

        Doctype(ref name, ref public, ref system) => {
            buf.push_str("<!DOCTYPE ");
            buf.push_str(name.as_slice());
            if !public.is_empty() || !system.is_empty() {
                buf.push_str(format!(" \"{}\" \"{}\"", public, system).as_slice());
            }
            buf.push_str(">\n");
        }

        Text(ref text) => {
            buf.push_str("\"");
            buf.push_str(text.as_slice());
            buf.push_str("\"\n");
        }

        Comment(ref text) => {
            buf.push_str("<!-- ");
            buf.push_str(text.as_slice());
            buf.push_str(" -->\n");
        }

        Element(ref name, ref attrs) => {
            assert!(name.ns == ns!(""));
            buf.push_str("<");
            buf.push_str(name.local.as_slice());
            buf.push_str(">\n");

            let mut attrs = attrs.clone();
            attrs.sort_by(|x, y| x.name.local.cmp(&y.name.local));
            // FIXME: sort by UTF-16 code unit

            for attr in attrs.into_iter() {
                assert!(attr.name.ns == ns!(""));
                buf.push_str("|");
                buf.grow(indent+2, ' ');
                buf.push_str(format!("{}=\"{}\"\n",
                    attr.name.local.as_slice(), attr.value).as_slice());
            }
        }
    }

    for child in node.children.iter() {
        serialize(buf, indent+2, child.clone());
    }
}

// Ignore tests containing these strings; we don't support these features yet.
static IGNORE_SUBSTRS: &'static [&'static str]
    = &["<math", "<svg", "<template"];

fn make_test(
        tests: &mut Vec<TestDescAndFn>,
        path_str: &str,
        idx: uint,
        fields: HashMap<String, String>) {

    let get_field = |key| {
        let field = fields.find_equiv(&key).expect("missing field");
        field.as_slice().trim_right_chars('\n').to_string()
    };

    if fields.find_equiv(&"document-fragment").is_some() {
        // FIXME
        return;
    }

    let data = get_field("data");
    let expected = get_field("document");
    tests.push(TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(format!("tb: {}-{}", path_str, idx)),
            ignore: IGNORE_SUBSTRS.iter().any(|&ig| data.as_slice().contains(ig)),
            should_fail: false,
        },
        testfn: DynTestFn(proc() {
            let dom: RcDom = parse(one_input(data.clone()), Default::default());

            let mut result = String::new();
            for child in dom.document.borrow().children.iter() {
                serialize(&mut result, 1, child.clone());
            }
            let len = result.len();
            result.truncate(len - 1);  // drop the trailing newline

            if result != expected {
                fail!("\ninput: {}\ngot:\n{}\nexpected:\n{}\n",
                    data, result, expected);
            }
        }),
    });
}

pub fn tests(src_dir: Path) -> MoveItems<TestDescAndFn> {
    let mut tests = vec!();

    foreach_html5lib_test(src_dir, "tree-construction", ".dat", |path_str, file| {
        let mut buf = io::BufferedReader::new(file);
        let lines = buf.lines()
            .map(|res| res.ok().expect("couldn't read"));
        let data = parse_tests(lines);

        for (i, test) in data.into_iter().enumerate() {
            make_test(&mut tests, path_str, i, test);
        }
    });

    tests.into_iter()
}
<commit_msg>Fix tree builder test runner<commit_after>// Copyright 2014 The html5ever Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use util::foreach_html5lib_test;

use std::io;
use std::mem::replace;
use std::default::Default;
use std::path::Path;
use std::collections::hashmap::HashMap;
use std::vec::MoveItems;
use test::{TestDesc, TestDescAndFn, DynTestName, DynTestFn};

use html5ever::sink::common::{Document, Doctype, Text, Comment, Element};
use html5ever::sink::rcdom::{RcDom, Handle};
use html5ever::{parse, one_input};

fn parse_tests<It: Iterator<String>>(mut lines: It) -> Vec<HashMap<String, String>> {
    let mut tests = vec!();
    let mut test = HashMap::new();
    let mut key = None;
    let mut val = String::new();

    macro_rules! finish_val ( () => (
        match key.take() {
            None => (),
            Some(key) => assert!(test.insert(key, replace(&mut val, String::new()))),
        }
    ))

    macro_rules! finish_test ( () => (
        if !test.is_empty() {
            tests.push(replace(&mut test, HashMap::new()));
        }
    ))

    loop {
        match lines.next() {
            None => break,
            Some(line) => {
                if line.as_slice().starts_with("#") {
                    finish_val!();
                    if line.as_slice() == "#data\n" {
                        finish_test!();
                    }
                    key = Some(line.as_slice().slice_from(1)
                        .trim_right_chars('\n').to_string());
                } else {
                    val.push_str(line.as_slice());
                }
            }
        }
    }

    finish_val!();
    finish_test!();
    tests
}

fn serialize(buf: &mut String, indent: uint, handle: Handle) {
    buf.push_str("|");
    buf.grow(indent, ' ');

    let node = handle.borrow();
    match node.node {
        Document => fail!("should not reach Document"),

        Doctype(ref name, ref public, ref system) => {
            buf.push_str("<!DOCTYPE ");
            buf.push_str(name.as_slice());
            if !public.is_empty() || !system.is_empty() {
                buf.push_str(format!(" \"{}\" \"{}\"", public, system).as_slice());
            }
            buf.push_str(">\n");
        }

        Text(ref text) => {
            buf.push_str("\"");
            buf.push_str(text.as_slice());
            buf.push_str("\"\n");
        }

        Comment(ref text) => {
            buf.push_str("<!-- ");
            buf.push_str(text.as_slice());
            buf.push_str(" -->\n");
        }

        Element(ref name, ref attrs) => {
            assert!(name.ns == ns!(HTML));
            buf.push_str("<");
            buf.push_str(name.local.as_slice());
            buf.push_str(">\n");

            let mut attrs = attrs.clone();
            attrs.sort_by(|x, y| x.name.local.cmp(&y.name.local));
            // FIXME: sort by UTF-16 code unit

            for attr in attrs.into_iter() {
                assert!(attr.name.ns == ns!(""));
                buf.push_str("|");
                buf.grow(indent+2, ' ');
                buf.push_str(format!("{}=\"{}\"\n",
                    attr.name.local.as_slice(), attr.value).as_slice());
            }
        }
    }

    for child in node.children.iter() {
        serialize(buf, indent+2, child.clone());
    }
}

// Ignore tests containing these strings; we don't support these features yet.
static IGNORE_SUBSTRS: &'static [&'static str]
    = &["<math", "<svg", "<template"];

fn make_test(
        tests: &mut Vec<TestDescAndFn>,
        path_str: &str,
        idx: uint,
        fields: HashMap<String, String>) {

    let get_field = |key| {
        let field = fields.find_equiv(&key).expect("missing field");
        field.as_slice().trim_right_chars('\n').to_string()
    };

    if fields.find_equiv(&"document-fragment").is_some() {
        // FIXME
        return;
    }

    let data = get_field("data");
    let expected = get_field("document");
    tests.push(TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(format!("tb: {}-{}", path_str, idx)),
            ignore: IGNORE_SUBSTRS.iter().any(|&ig| data.as_slice().contains(ig)),
            should_fail: false,
        },
        testfn: DynTestFn(proc() {
            let dom: RcDom = parse(one_input(data.clone()), Default::default());

            let mut result = String::new();
            for child in dom.document.borrow().children.iter() {
                serialize(&mut result, 1, child.clone());
            }
            let len = result.len();
            result.truncate(len - 1);  // drop the trailing newline

            if result != expected {
                fail!("\ninput: {}\ngot:\n{}\nexpected:\n{}\n",
                    data, result, expected);
            }
        }),
    });
}

pub fn tests(src_dir: Path) -> MoveItems<TestDescAndFn> {
    let mut tests = vec!();

    foreach_html5lib_test(src_dir, "tree-construction", ".dat", |path_str, file| {
        let mut buf = io::BufferedReader::new(file);
        let lines = buf.lines()
            .map(|res| res.ok().expect("couldn't read"));
        let data = parse_tests(lines);

        for (i, test) in data.into_iter().enumerate() {
            make_test(&mut tests, path_str, i, test);
        }
    });

    tests.into_iter()
}
<|endoftext|>