<commit_before>const MAGIC_NUMBERS : [u8; 4] = [0x4Eu8, 0x45u8, 0x53u8, 0x1Au8];
pub const PRG_ROM_PAGE_SIZE : usize = 16384;
pub const CHR_ROM_PAGE_SIZE : usize = 8192;
pub const PRG_RAM_PAGE_SIZE : usize = 8192;

#[derive(PartialEq, Debug)]
pub enum ScreenMode {
	Horizontal,
	Vertical,
	FourScreen
}

pub struct Rom {
	prg_rom: Vec<u8>,
	chr_rom_pages: u8,
	flags6: u8,
	flags7: u8,
	prg_ram_pages: u8,
	trainer: Vec<u8>,
}

fn get_bit(byte: u8, bit_num: u8) -> bool {
	!((byte & 1u8 << bit_num) == 0)
}

fn read_byte( iter : &mut Iterator<Item=u8> ) -> u8 {
	iter.next().unwrap()
}

fn read_bytes( iter: &mut Iterator<Item=u8>, bytes: usize ) -> Vec<u8> {
	iter.take( bytes ).collect()
}

impl Rom {
	///Parse the given bytes as an iNES 1.0 header.
	///NES 2.0 is not supported until I can find a rom that actually uses it.
	pub fn parse(data: Vec<u8>) -> Rom {
		let mut iter = data.iter().cloned();
		assert_eq!( read_bytes( &mut iter, 4 ), MAGIC_NUMBERS );
		let prg_rom_pages = read_byte( &mut iter );
		let chr_rom_pages = read_byte( &mut iter );
		let flags6 = read_byte( &mut iter );
		let flags7 = read_byte( &mut iter );
		let prg_ram_pages = read_byte( &mut iter );

		read_bytes( &mut iter, 7 );

		let has_trainer = get_bit(flags6, 2);
		let trainer = match has_trainer {
			false => vec!(),
			true => read_bytes( &mut iter, 512 ),
		};

		Rom {
			prg_rom: read_bytes( &mut iter, PRG_ROM_PAGE_SIZE * prg_rom_pages as usize ),
			chr_rom_pages: chr_rom_pages,
			flags6: flags6,
			flags7: flags7,
			prg_ram_pages: prg_ram_pages,
			trainer: trainer
		}
	}

	pub fn screen_mode(&self) -> ScreenMode {
		match self.flags6 & 0b0000_1001u8 {
			0b0000_0000 => ScreenMode::Horizontal,
			0b0000_0001 => ScreenMode::Vertical,
			0b0000_1000 | 0b0000_1001 => ScreenMode::FourScreen,
			_ => panic!("Math is broken!"),
		}
	}

	pub fn sram(&self) -> bool {
		get_bit(self.flags6, 1)
	}

	pub fn trainer(&self) -> &Vec<u8> {
		&self.trainer
	}

	pub fn pc10(&self) -> bool {
		get_bit(self.flags7, 0)
	}

	pub fn vs(&self) -> bool {
		get_bit(self.flags7, 1)
	}

	pub fn mapper(&self) -> u8 {
		( ( self.flags6 & 0xF0 ) >> 4 ) | ( self.flags7 & 0xF0 )
	}
}

#[cfg(test)]
mod tests {
	use super::*;
	use rand::{Rng, thread_rng};

	struct RomBuilder {
		header : Vec<u8>,
		trainer : Vec<u8>,
		prg_rom : Vec<u8>,
	}

	fn set_bit(byte: &mut u8, bit_num: u8) {
		*byte = *byte | 1u8 << bit_num;
	}

	fn generate_bytes( size: usize ) -> Vec<u8> {
		let mut rng = thread_rng();
		let mut bytes : Vec<u8> = vec!(0u8; size);
		rng.fill_bytes(&mut bytes);
		bytes
	}

	impl RomBuilder {
		fn new() -> RomBuilder {
			let mut header = vec![0x4Eu8, 0x45u8, 0x53u8, 0x1Au8];
			header.extend([0; 12].iter().cloned());
			return RomBuilder{
				header: header,
				trainer: vec!(),
				prg_rom: vec!(),
			}
		}

		fn set_prg_page_count( &mut self, count: u8 ) {
			self.header[4] = count;
			self.prg_rom = generate_bytes( count as usize * PRG_ROM_PAGE_SIZE );
		}

		fn set_chr_page_count( &mut self, count: u8 ) {
			self.header[5] = count;
		}

		fn set_mirroring( &mut self ) {
			set_bit(&mut self.header[6], 0)
		}

		fn set_sram( &mut self ) {
			set_bit(&mut self.header[6], 1)
		}

		fn set_trainer( &mut self ) {
			set_bit(&mut self.header[6], 2);
			self.trainer = generate_bytes( 512 );
		}

		fn set_fourscreen( &mut self ) {
			set_bit(&mut self.header[6], 3)
		}

		fn set_pc10( &mut self ) {
			set_bit(&mut self.header[7], 0)
		}

		fn set_vs( &mut self ) {
			set_bit(&mut self.header[7], 1)
		}

		fn set_mapper( &mut self, mapper: u8 ) {
			self.header[6] = ( self.header[6] & 0x0F ) | ( ( mapper & 0x0Fu8 ) << 4 );
			self.header[7] = ( self.header[7] & 0x0F ) | ( ( mapper & 0xF0u8 ) << 0 );
		}

		fn set_prg_ram_pages( &mut self, pages: u8 ) {
			self.header[8] = pages;
		}

		fn build(&self) -> Vec<u8> {
			let mut buf = self.header.clone();
			buf.extend(self.trainer.iter().clone());
			buf.extend(self.prg_rom.iter().clone());
			buf
		}
	}

	#[test]
	#[should_panic]
	fn parse_panics_on_empty_input() {
		Rom::parse( vec!() );
	}

	#[test]
	fn test_prg_rom_pages() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).prg_rom, vec!() );

		builder.set_prg_page_count( 3 );
		assert_eq!( Rom::parse( builder.build() ).prg_rom, builder.prg_rom );
	}

	#[test]
	fn test_chr_rom_pages() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).chr_rom_pages, 0 );

		builder.set_chr_page_count( 150 );
		assert_eq!( Rom::parse( builder.build() ).chr_rom_pages, 150 );
	}

	#[test]
	fn test_screen_mode_without_fourscreen() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).screen_mode(), ScreenMode::Horizontal );

		builder.set_mirroring();
		assert_eq!( Rom::parse( builder.build() ).screen_mode(), ScreenMode::Vertical );
	}

	#[test]
	fn test_screen_mode_with_fourscreen() {
		let mut builder = RomBuilder::new();
		builder.set_fourscreen();
		assert_eq!( Rom::parse( builder.build() ).screen_mode(), ScreenMode::FourScreen );

		builder.set_mirroring();
		assert_eq!( Rom::parse( builder.build() ).screen_mode(), ScreenMode::FourScreen );
	}

	#[test]
	fn test_sram() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).sram(), false );

		builder.set_sram();
		assert_eq!( Rom::parse( builder.build() ).sram(), true );
	}

	#[test]
	fn test_trainer() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).trainer(), &vec!() );

		builder.set_trainer();
		assert_eq!( Rom::parse( builder.build() ).trainer().len(), builder.trainer.len() );
		assert_eq!( Rom::parse( builder.build() ).trainer(), &builder.trainer );
	}

	#[test]
	fn test_pc10() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).pc10(), false );

		builder.set_pc10();
		assert_eq!( Rom::parse( builder.build() ).pc10(), true );
	}

	#[test]
	fn test_vs() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).vs(), false );

		builder.set_vs();
		assert_eq!( Rom::parse( builder.build() ).vs(), true );
	}

	#[test]
	fn test_mapper() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).mapper(), 0x00u8 );

		builder.set_mapper(0x0Au8);
		assert_eq!( Rom::parse( builder.build() ).mapper(), 0x0Au8 );

		builder.set_mapper(0xF0u8);
		println!( "0x{:02X}, 0x{:02X}", builder.header[6], builder.header[7] );
		assert_eq!( Rom::parse( builder.build() ).mapper(), 0xF0u8 );
	}

		#[test]
	fn test_prg_ram_pages() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).prg_ram_pages, 0 );

		builder.set_prg_ram_pages(15);
		assert_eq!( Rom::parse( builder.build() ).prg_ram_pages, 15 );
	}
}<commit_msg>Finished iNES 1.0 parsing (I think).<commit_after>const MAGIC_NUMBERS : [u8; 4] = [0x4Eu8, 0x45u8, 0x53u8, 0x1Au8];
pub const PRG_ROM_PAGE_SIZE : usize = 16384;
pub const CHR_ROM_PAGE_SIZE : usize = 8192;
pub const PRG_RAM_PAGE_SIZE : usize = 8192;

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum ScreenMode {
	Horizontal,
	Vertical,
	FourScreen
}

pub struct Rom {
	flags6: u8,
	flags7: u8,
	prg_rom: Vec<u8>,
	chr_rom: Vec<u8>,
	prg_ram: Vec<u8>,
	trainer: Vec<u8>,
}

fn get_bit(byte: u8, bit_num: u8) -> bool {
	!((byte & 1u8 << bit_num) == 0)
}

fn read_byte( iter : &mut Iterator<Item=u8> ) -> u8 {
	iter.next().unwrap()
}

fn read_bytes( iter: &mut Iterator<Item=u8>, bytes: usize ) -> Vec<u8> {
	iter.take( bytes ).collect()
}

impl Rom {
	///Parse the given bytes as an iNES 1.0 header.
	///NES 2.0 is not supported until I can find a rom that actually uses it.
	pub fn parse(data: &Vec<u8>) -> Rom {
		let mut iter = data.iter().cloned();
		assert_eq!( read_bytes( &mut iter, 4 ), MAGIC_NUMBERS );
		let prg_rom_pages = read_byte( &mut iter );
		let chr_rom_pages = read_byte( &mut iter );
		let flags6 = read_byte( &mut iter );
		let flags7 = read_byte( &mut iter );
		let prg_ram_pages = match read_byte( &mut iter ) {
			0 => 1,
			x => x,
		};

		read_bytes( &mut iter, 7 );

		let has_trainer = get_bit(flags6, 2);
		let trainer = match has_trainer {
			false => vec!(),
			true => read_bytes( &mut iter, 512 ),
		};

		Rom {
			prg_rom: read_bytes( &mut iter, PRG_ROM_PAGE_SIZE * prg_rom_pages as usize ),
			chr_rom: read_bytes( &mut iter, CHR_ROM_PAGE_SIZE * chr_rom_pages as usize ),
			flags6: flags6,
			flags7: flags7,
			prg_ram: vec!( 0u8; PRG_RAM_PAGE_SIZE * prg_ram_pages as usize ),
			trainer: trainer
		}
	}

	pub fn screen_mode(&self) -> ScreenMode {
		match self.flags6 & 0b0000_1001u8 {
			0b0000_0000 => ScreenMode::Horizontal,
			0b0000_0001 => ScreenMode::Vertical,
			0b0000_1000 | 0b0000_1001 => ScreenMode::FourScreen,
			_ => panic!("Math is broken!"),
		}
	}

	pub fn sram(&self) -> bool {
		get_bit(self.flags6, 1)
	}

	pub fn trainer(&self) -> &Vec<u8> {
		&self.trainer
	}

	pub fn pc10(&self) -> bool {
		get_bit(self.flags7, 0)
	}

	pub fn vs(&self) -> bool {
		get_bit(self.flags7, 1)
	}

	pub fn mapper(&self) -> u8 {
		( ( self.flags6 & 0xF0 ) >> 4 ) | ( self.flags7 & 0xF0 )
	}
}

#[cfg(test)]
mod tests {
	use super::*;
	use rand::{Rng, thread_rng};

	struct RomBuilder {
		header : Vec<u8>,
		trainer : Vec<u8>,
		prg_rom : Vec<u8>,
		chr_rom : Vec<u8>,
	}

	fn set_bit(byte: &mut u8, bit_num: u8) {
		*byte = *byte | 1u8 << bit_num;
	}

	fn generate_bytes( size: usize ) -> Vec<u8> {
		let mut rng = thread_rng();
		let mut bytes : Vec<u8> = vec!(0u8; size);
		rng.fill_bytes(&mut bytes);
		bytes
	}

	impl RomBuilder {
		fn new() -> RomBuilder {
			let mut header = vec![0x4Eu8, 0x45u8, 0x53u8, 0x1Au8];
			header.extend([0; 12].iter().cloned());
			return RomBuilder{
				header: header,
				trainer: vec!(),
				prg_rom: vec!(),
				chr_rom: vec!(),
			}
		}

		fn set_prg_page_count( &mut self, count: u8 ) {
			self.header[4] = count;
			self.prg_rom = generate_bytes( count as usize * PRG_ROM_PAGE_SIZE );
		}

		fn set_chr_page_count( &mut self, count: u8 ) {
			self.header[5] = count;
			self.chr_rom = generate_bytes( count as usize * CHR_ROM_PAGE_SIZE );
		}

		fn set_mirroring( &mut self ) {
			set_bit(&mut self.header[6], 0)
		}

		fn set_sram( &mut self ) {
			set_bit(&mut self.header[6], 1)
		}

		fn set_trainer( &mut self ) {
			set_bit(&mut self.header[6], 2);
			self.trainer = generate_bytes( 512 );
		}

		fn set_fourscreen( &mut self ) {
			set_bit(&mut self.header[6], 3)
		}

		fn set_pc10( &mut self ) {
			set_bit(&mut self.header[7], 0)
		}

		fn set_vs( &mut self ) {
			set_bit(&mut self.header[7], 1)
		}

		fn set_mapper( &mut self, mapper: u8 ) {
			self.header[6] = ( self.header[6] & 0x0F ) | ( ( mapper & 0x0Fu8 ) << 4 );
			self.header[7] = ( self.header[7] & 0x0F ) | ( ( mapper & 0xF0u8 ) << 0 );
		}

		fn set_prg_ram_pages( &mut self, pages: u8 ) {
			self.header[8] = pages;
		}

		fn build(&self) -> Vec<u8> {
			let mut buf = self.header.clone();
			buf.extend(self.trainer.iter().clone());
			buf.extend(self.prg_rom.iter().clone());
			buf.extend(self.chr_rom.iter().clone());
			buf
		}
	}

	#[test]
	#[should_panic]
	fn parse_panics_on_empty_input() {
		Rom::parse( &vec!() );
	}

	#[test]
	fn test_prg_rom() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( &builder.build() ).prg_rom, vec!() );

		builder.set_prg_page_count( 3 );
		assert_eq!( Rom::parse( &builder.build() ).prg_rom, builder.prg_rom );
	}

	#[test]
	fn test_chr_rom() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( &builder.build() ).chr_rom, vec!() );

		builder.set_chr_page_count( 150 );
		assert_eq!( Rom::parse( &builder.build() ).chr_rom, builder.chr_rom );
	}

	#[test]
	fn test_screen_mode_without_fourscreen() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( &builder.build() ).screen_mode(), ScreenMode::Horizontal );

		builder.set_mirroring();
		assert_eq!( Rom::parse( &builder.build() ).screen_mode(), ScreenMode::Vertical );
	}

	#[test]
	fn test_screen_mode_with_fourscreen() {
		let mut builder = RomBuilder::new();
		builder.set_fourscreen();
		assert_eq!( Rom::parse( &builder.build() ).screen_mode(), ScreenMode::FourScreen );

		builder.set_mirroring();
		assert_eq!( Rom::parse( &builder.build() ).screen_mode(), ScreenMode::FourScreen );
	}

	#[test]
	fn test_sram() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( &builder.build() ).sram(), false );

		builder.set_sram();
		assert_eq!( Rom::parse( &builder.build() ).sram(), true );
	}

	#[test]
	fn test_trainer() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( &builder.build() ).trainer(), &vec!() );

		builder.set_trainer();
		assert_eq!( Rom::parse( &builder.build() ).trainer().len(), builder.trainer.len() );
		assert_eq!( Rom::parse( &builder.build() ).trainer(), &builder.trainer );
	}

	#[test]
	fn test_pc10() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( &builder.build() ).pc10(), false );

		builder.set_pc10();
		assert_eq!( Rom::parse( &builder.build() ).pc10(), true );
	}

	#[test]
	fn test_vs() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( &builder.build() ).vs(), false );

		builder.set_vs();
		assert_eq!( Rom::parse( &builder.build() ).vs(), true );
	}

	#[test]
	fn test_mapper() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( &builder.build() ).mapper(), 0x00u8 );

		builder.set_mapper(0x0Au8);
		assert_eq!( Rom::parse( &builder.build() ).mapper(), 0x0Au8 );

		builder.set_mapper(0xF0u8);
		println!( "0x{:02X}, 0x{:02X}", builder.header[6], builder.header[7] );
		assert_eq!( Rom::parse( &builder.build() ).mapper(), 0xF0u8 );
	}

		#[test]
	fn test_prg_ram_pages() {
		let mut builder = RomBuilder::new();
		builder.set_prg_ram_pages(1);
		assert_eq!( Rom::parse( &builder.build() ).prg_ram.len(), PRG_RAM_PAGE_SIZE );

		builder.set_prg_ram_pages(0);
		assert_eq!( Rom::parse( &builder.build() ).prg_ram.len(), PRG_RAM_PAGE_SIZE );

		builder.set_prg_ram_pages(15);
		assert_eq!( Rom::parse( &builder.build() ).prg_ram.len(), 15 * PRG_RAM_PAGE_SIZE );
	}
}<|endoftext|>


<commit_before>//! LLVM's simd platform intrinsics
//!
//! TODO: should use `link_llvm_intrinsic` instead: issue #112

extern "platform-intrinsic" {
    //pub fn simd_select_bitmask
    pub fn simd_eq<T, U>(x: T, y: T) -> U;
    pub fn simd_ne<T, U>(x: T, y: T) -> U;
    pub fn simd_lt<T, U>(x: T, y: T) -> U;
    pub fn simd_le<T, U>(x: T, y: T) -> U;
    pub fn simd_gt<T, U>(x: T, y: T) -> U;
    pub fn simd_ge<T, U>(x: T, y: T) -> U;

    #[rustc_args_required_const(2)]
    pub fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
    #[rustc_args_required_const(2)]
    pub fn simd_shuffle4<T, U>(x: T, y: T, idx: [u32; 4]) -> U;
    #[rustc_args_required_const(2)]
    pub fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
    #[rustc_args_required_const(2)]
    pub fn simd_shuffle16<T, U>(x: T, y: T, idx: [u32; 16]) -> U;
    #[rustc_args_required_const(2)]
    pub fn simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U;
    #[rustc_args_required_const(2)]
    pub fn simd_shuffle64<T, U>(x: T, y: T, idx: [u32; 64]) -> U;
    #[rustc_args_required_const(2)]
    pub fn simd_shuffle128<T, U>(x: T, y: T, idx: [u32; 128]) -> U;

    #[rustc_const_unstable(feature = "const_simd_insert", issue = "none")]
    pub fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
    #[rustc_const_unstable(feature = "const_simd_extract", issue = "none")]
    pub fn simd_extract<T, U>(x: T, idx: u32) -> U;
    //pub fn simd_select
    pub fn simd_bitmask<T, U>(x: T) -> U;

    pub fn simd_cast<T, U>(x: T) -> U;

    pub fn simd_add<T>(x: T, y: T) -> T;
    pub fn simd_sub<T>(x: T, y: T) -> T;
    pub fn simd_mul<T>(x: T, y: T) -> T;
    pub fn simd_div<T>(x: T, y: T) -> T;
    pub fn simd_shl<T>(x: T, y: T) -> T;
    pub fn simd_shr<T>(x: T, y: T) -> T;
    pub fn simd_and<T>(x: T, y: T) -> T;
    pub fn simd_or<T>(x: T, y: T) -> T;
    pub fn simd_xor<T>(x: T, y: T) -> T;

    pub fn simd_saturating_add<T>(x: T, y: T) -> T;
    pub fn simd_saturating_sub<T>(x: T, y: T) -> T;

    pub fn simd_gather<T, U, V>(values: T, pointers: U, mask: V) -> T;
    pub fn simd_scatter<T, U, V>(values: T, pointers: U, mask: V);

    pub fn simd_reduce_add_unordered<T, U>(x: T) -> U;
    pub fn simd_reduce_mul_unordered<T, U>(x: T) -> U;
    pub fn simd_reduce_add_ordered<T, U>(x: T, acc: U) -> U;
    pub fn simd_reduce_mul_ordered<T, U>(x: T, acc: U) -> U;
    pub fn simd_reduce_min<T, U>(x: T) -> U;
    pub fn simd_reduce_max<T, U>(x: T) -> U;
    pub fn simd_reduce_min_nanless<T, U>(x: T) -> U;
    pub fn simd_reduce_max_nanless<T, U>(x: T) -> U;
    pub fn simd_reduce_and<T, U>(x: T) -> U;
    pub fn simd_reduce_or<T, U>(x: T) -> U;
    pub fn simd_reduce_xor<T, U>(x: T) -> U;
    pub fn simd_reduce_all<T>(x: T) -> bool;
    pub fn simd_reduce_any<T>(x: T) -> bool;

    pub fn simd_select<M, T>(m: M, a: T, b: T) -> T;
    pub fn simd_select_bitmask<M, T>(m: M, a: T, b: T) -> T;

    pub fn simd_fmin<T>(a: T, b: T) -> T;
    pub fn simd_fmax<T>(a: T, b: T) -> T;

    pub fn simd_fsqrt<T>(a: T) -> T;
    pub fn simd_fsin<T>(a: T) -> T;
    pub fn simd_fcos<T>(a: T) -> T;
    pub fn simd_fabs<T>(a: T) -> T;
    pub fn simd_floor<T>(a: T) -> T;
    pub fn simd_ceil<T>(a: T) -> T;
    pub fn simd_fexp<T>(a: T) -> T;
    pub fn simd_fexp2<T>(a: T) -> T;
    pub fn simd_flog10<T>(a: T) -> T;
    pub fn simd_flog2<T>(a: T) -> T;
    pub fn simd_flog<T>(a: T) -> T;
    //pub fn simd_fpowi
    //pub fn simd_fpow
    pub fn simd_fma<T>(a: T, b: T, c: T) -> T;
}
<commit_msg>Remove old TODO (#911)<commit_after>//! LLVM's SIMD platform intrinsics

extern "platform-intrinsic" {
    //pub fn simd_select_bitmask
    pub fn simd_eq<T, U>(x: T, y: T) -> U;
    pub fn simd_ne<T, U>(x: T, y: T) -> U;
    pub fn simd_lt<T, U>(x: T, y: T) -> U;
    pub fn simd_le<T, U>(x: T, y: T) -> U;
    pub fn simd_gt<T, U>(x: T, y: T) -> U;
    pub fn simd_ge<T, U>(x: T, y: T) -> U;

    #[rustc_args_required_const(2)]
    pub fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
    #[rustc_args_required_const(2)]
    pub fn simd_shuffle4<T, U>(x: T, y: T, idx: [u32; 4]) -> U;
    #[rustc_args_required_const(2)]
    pub fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
    #[rustc_args_required_const(2)]
    pub fn simd_shuffle16<T, U>(x: T, y: T, idx: [u32; 16]) -> U;
    #[rustc_args_required_const(2)]
    pub fn simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U;
    #[rustc_args_required_const(2)]
    pub fn simd_shuffle64<T, U>(x: T, y: T, idx: [u32; 64]) -> U;
    #[rustc_args_required_const(2)]
    pub fn simd_shuffle128<T, U>(x: T, y: T, idx: [u32; 128]) -> U;

    #[rustc_const_unstable(feature = "const_simd_insert", issue = "none")]
    pub fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
    #[rustc_const_unstable(feature = "const_simd_extract", issue = "none")]
    pub fn simd_extract<T, U>(x: T, idx: u32) -> U;
    //pub fn simd_select
    pub fn simd_bitmask<T, U>(x: T) -> U;

    pub fn simd_cast<T, U>(x: T) -> U;

    pub fn simd_add<T>(x: T, y: T) -> T;
    pub fn simd_sub<T>(x: T, y: T) -> T;
    pub fn simd_mul<T>(x: T, y: T) -> T;
    pub fn simd_div<T>(x: T, y: T) -> T;
    pub fn simd_shl<T>(x: T, y: T) -> T;
    pub fn simd_shr<T>(x: T, y: T) -> T;
    pub fn simd_and<T>(x: T, y: T) -> T;
    pub fn simd_or<T>(x: T, y: T) -> T;
    pub fn simd_xor<T>(x: T, y: T) -> T;

    pub fn simd_saturating_add<T>(x: T, y: T) -> T;
    pub fn simd_saturating_sub<T>(x: T, y: T) -> T;

    pub fn simd_gather<T, U, V>(values: T, pointers: U, mask: V) -> T;
    pub fn simd_scatter<T, U, V>(values: T, pointers: U, mask: V);

    pub fn simd_reduce_add_unordered<T, U>(x: T) -> U;
    pub fn simd_reduce_mul_unordered<T, U>(x: T) -> U;
    pub fn simd_reduce_add_ordered<T, U>(x: T, acc: U) -> U;
    pub fn simd_reduce_mul_ordered<T, U>(x: T, acc: U) -> U;
    pub fn simd_reduce_min<T, U>(x: T) -> U;
    pub fn simd_reduce_max<T, U>(x: T) -> U;
    pub fn simd_reduce_min_nanless<T, U>(x: T) -> U;
    pub fn simd_reduce_max_nanless<T, U>(x: T) -> U;
    pub fn simd_reduce_and<T, U>(x: T) -> U;
    pub fn simd_reduce_or<T, U>(x: T) -> U;
    pub fn simd_reduce_xor<T, U>(x: T) -> U;
    pub fn simd_reduce_all<T>(x: T) -> bool;
    pub fn simd_reduce_any<T>(x: T) -> bool;

    pub fn simd_select<M, T>(m: M, a: T, b: T) -> T;
    pub fn simd_select_bitmask<M, T>(m: M, a: T, b: T) -> T;

    pub fn simd_fmin<T>(a: T, b: T) -> T;
    pub fn simd_fmax<T>(a: T, b: T) -> T;

    pub fn simd_fsqrt<T>(a: T) -> T;
    pub fn simd_fsin<T>(a: T) -> T;
    pub fn simd_fcos<T>(a: T) -> T;
    pub fn simd_fabs<T>(a: T) -> T;
    pub fn simd_floor<T>(a: T) -> T;
    pub fn simd_ceil<T>(a: T) -> T;
    pub fn simd_fexp<T>(a: T) -> T;
    pub fn simd_fexp2<T>(a: T) -> T;
    pub fn simd_flog10<T>(a: T) -> T;
    pub fn simd_flog2<T>(a: T) -> T;
    pub fn simd_flog<T>(a: T) -> T;
    //pub fn simd_fpowi
    //pub fn simd_fpow
    pub fn simd_fma<T>(a: T, b: T, c: T) -> T;
}
<|endoftext|>


<commit_before>use super::{Value, ValueRef};
use std::error::Error;
use std::fmt;

/// Enum listing possible errors from `FromSql` trait.
#[derive(Debug)]
pub enum FromSqlError {
    /// Error when an SQLite value is requested, but the type of the result
    /// cannot be converted to the requested Rust type.
    InvalidType,

    /// Error when the i64 value returned by SQLite cannot be stored into the
    /// requested type.
    OutOfRange(i64),

    /// Error returned when reading an `i128` from a blob with a size
    /// other than 16. Only available when the `i128_blob` feature is enabled.
    #[cfg(feature = "i128_blob")]
    InvalidI128Size(usize),

    /// An error case available for implementors of the `FromSql` trait.
    Other(Box<dyn Error + Send + Sync>),
}

impl PartialEq for FromSqlError {
    fn eq(&self, other: &FromSqlError) -> bool {
        match (self, other) {
            (FromSqlError::InvalidType, FromSqlError::InvalidType) => true,
            (FromSqlError::OutOfRange(n1), FromSqlError::OutOfRange(n2)) => n1 == n2,
            #[cfg(feature = "i128_blob")]
            (FromSqlError::InvalidI128Size(s1), FromSqlError::InvalidI128Size(s2)) => s1 == s2,
            (_, _) => false,
        }
    }
}

impl fmt::Display for FromSqlError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            FromSqlError::InvalidType => write!(f, "Invalid type"),
            FromSqlError::OutOfRange(i) => write!(f, "Value {} out of range", i),
            #[cfg(feature = "i128_blob")]
            FromSqlError::InvalidI128Size(s) => {
                write!(f, "Cannot read 128bit value out of {} byte blob", s)
            }
            FromSqlError::Other(ref err) => err.fmt(f),
        }
    }
}

impl Error for FromSqlError {
    fn description(&self) -> &str {
        match *self {
            FromSqlError::InvalidType => "invalid type",
            FromSqlError::OutOfRange(_) => "value out of range",
            #[cfg(feature = "i128_blob")]
            FromSqlError::InvalidI128Size(_) => "unexpected blob size for 128bit value",
            FromSqlError::Other(ref err) => err.description(),
        }
    }

    #[allow(clippy::match_same_arms)]
    fn cause(&self) -> Option<&dyn Error> {
        match *self {
            FromSqlError::Other(ref err) => err.cause(),
            FromSqlError::InvalidType | FromSqlError::OutOfRange(_) => None,
            #[cfg(feature = "i128_blob")]
            FromSqlError::InvalidI128Size(_) => None,
        }
    }
}

/// Result type for implementors of the `FromSql` trait.
pub type FromSqlResult<T> = Result<T, FromSqlError>;

/// A trait for types that can be created from a SQLite value.
///
/// Note that `FromSql` and `ToSql` are defined for most integral types, but
/// not `u64` or `usize`. This is intentional; SQLite returns integers as
/// signed 64-bit values, which cannot fully represent the range of these
/// types. Rusqlite would have to
/// decide how to handle negative values: return an error or reinterpret as a
/// very large postive numbers, neither of which
/// is guaranteed to be correct for everyone. Callers can work around this by
/// fetching values as i64 and then doing the interpretation themselves or by
/// defining a newtype and implementing `FromSql`/`ToSql` for it.
pub trait FromSql: Sized {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self>;
}

impl FromSql for isize {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        i64::column_result(value).and_then(|i| {
            if i < isize::min_value() as i64 || i > isize::max_value() as i64 {
                Err(FromSqlError::OutOfRange(i))
            } else {
                Ok(i as isize)
            }
        })
    }
}

macro_rules! from_sql_integral(
    ($t:ident) => (
        impl FromSql for $t {
            fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
                i64::column_result(value).and_then(|i| {
                    if i < i64::from($t::min_value()) || i > i64::from($t::max_value()) {
                        Err(FromSqlError::OutOfRange(i))
                    } else {
                        Ok(i as $t)
                    }
                })
            }
        }
    )
);

from_sql_integral!(i8);
from_sql_integral!(i16);
from_sql_integral!(i32);
from_sql_integral!(u8);
from_sql_integral!(u16);
from_sql_integral!(u32);

impl FromSql for i64 {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        value.as_i64()
    }
}

impl FromSql for f64 {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        match value {
            ValueRef::Integer(i) => Ok(i as f64),
            ValueRef::Real(f) => Ok(f),
            _ => Err(FromSqlError::InvalidType),
        }
    }
}

impl FromSql for bool {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        i64::column_result(value).map(|i| match i {
            0 => false,
            _ => true,
        })
    }
}

impl FromSql for String {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        value.as_str().map(|s| s.to_string())
    }
}

impl FromSql for Vec<u8> {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        value.as_blob().map(|b| b.to_vec())
    }
}

#[cfg(feature = "i128_blob")]
impl FromSql for i128 {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        use byteorder::{BigEndian, ByteOrder};

        value.as_blob().and_then(|bytes| {
            if bytes.len() == 16 {
                Ok(BigEndian::read_i128(bytes) ^ (1i128 << 127))
            } else {
                Err(FromSqlError::InvalidI128Size(bytes.len()))
            }
        })
    }
}

impl<T: FromSql> FromSql for Option<T> {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        match value {
            ValueRef::Null => Ok(None),
            _ => FromSql::column_result(value).map(Some),
        }
    }
}

impl FromSql for Value {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        Ok(value.into())
    }
}

#[cfg(test)]
mod test {
    use super::FromSql;
    use crate::{Connection, Error};

    fn checked_memory_handle() -> Connection {
        Connection::open_in_memory().unwrap()
    }

    #[test]
    fn test_integral_ranges() {
        let db = checked_memory_handle();

        fn check_ranges<T>(db: &Connection, out_of_range: &[i64], in_range: &[i64])
        where
            T: Into<i64> + FromSql + ::std::fmt::Debug,
        {
            for n in out_of_range {
                let err = db
                    .query_row("SELECT ?", &[n], |r| r.get_checked::<_, T>(0))
                    .unwrap()
                    .unwrap_err();
                match err {
                    Error::IntegralValueOutOfRange(_, value) => assert_eq!(*n, value),
                    _ => panic!("unexpected error: {}", err),
                }
            }
            for n in in_range {
                assert_eq!(
                    *n,
                    db.query_row("SELECT ?", &[n], |r| r.get::<_, T>(0))
                        .unwrap()
                        .into()
                );
            }
        }

        check_ranges::<i8>(&db, &[-129, 128], &[-128, 0, 1, 127]);
        check_ranges::<i16>(&db, &[-32769, 32768], &[-32768, -1, 0, 1, 32767]);
        check_ranges::<i32>(
            &db,
            &[-2147483649, 2147483648],
            &[-2147483648, -1, 0, 1, 2147483647],
        );
        check_ranges::<u8>(&db, &[-2, -1, 256], &[0, 1, 255]);
        check_ranges::<u16>(&db, &[-2, -1, 65536], &[0, 1, 65535]);
        check_ranges::<u32>(&db, &[-2, -1, 4294967296], &[0, 1, 4294967295]);
    }
}
<commit_msg>Fix/suppress warning 'deprecated'<commit_after>use super::{Value, ValueRef};
use std::error::Error;
use std::fmt;

/// Enum listing possible errors from `FromSql` trait.
#[derive(Debug)]
pub enum FromSqlError {
    /// Error when an SQLite value is requested, but the type of the result
    /// cannot be converted to the requested Rust type.
    InvalidType,

    /// Error when the i64 value returned by SQLite cannot be stored into the
    /// requested type.
    OutOfRange(i64),

    /// Error returned when reading an `i128` from a blob with a size
    /// other than 16. Only available when the `i128_blob` feature is enabled.
    #[cfg(feature = "i128_blob")]
    InvalidI128Size(usize),

    /// An error case available for implementors of the `FromSql` trait.
    Other(Box<dyn Error + Send + Sync>),
}

impl PartialEq for FromSqlError {
    fn eq(&self, other: &FromSqlError) -> bool {
        match (self, other) {
            (FromSqlError::InvalidType, FromSqlError::InvalidType) => true,
            (FromSqlError::OutOfRange(n1), FromSqlError::OutOfRange(n2)) => n1 == n2,
            #[cfg(feature = "i128_blob")]
            (FromSqlError::InvalidI128Size(s1), FromSqlError::InvalidI128Size(s2)) => s1 == s2,
            (_, _) => false,
        }
    }
}

impl fmt::Display for FromSqlError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            FromSqlError::InvalidType => write!(f, "Invalid type"),
            FromSqlError::OutOfRange(i) => write!(f, "Value {} out of range", i),
            #[cfg(feature = "i128_blob")]
            FromSqlError::InvalidI128Size(s) => {
                write!(f, "Cannot read 128bit value out of {} byte blob", s)
            }
            FromSqlError::Other(ref err) => err.fmt(f),
        }
    }
}

impl Error for FromSqlError {
    fn description(&self) -> &str {
        match *self {
            FromSqlError::InvalidType => "invalid type",
            FromSqlError::OutOfRange(_) => "value out of range",
            #[cfg(feature = "i128_blob")]
            FromSqlError::InvalidI128Size(_) => "unexpected blob size for 128bit value",
            FromSqlError::Other(ref err) => err.description(),
        }
    }

    #[allow(clippy::match_same_arms)]
    #[allow(deprecated)]
    fn cause(&self) -> Option<&dyn Error> {
        match *self {
            FromSqlError::Other(ref err) => err.cause(),
            FromSqlError::InvalidType | FromSqlError::OutOfRange(_) => None,
            #[cfg(feature = "i128_blob")]
            FromSqlError::InvalidI128Size(_) => None,
        }
    }
}

/// Result type for implementors of the `FromSql` trait.
pub type FromSqlResult<T> = Result<T, FromSqlError>;

/// A trait for types that can be created from a SQLite value.
///
/// Note that `FromSql` and `ToSql` are defined for most integral types, but
/// not `u64` or `usize`. This is intentional; SQLite returns integers as
/// signed 64-bit values, which cannot fully represent the range of these
/// types. Rusqlite would have to
/// decide how to handle negative values: return an error or reinterpret as a
/// very large postive numbers, neither of which
/// is guaranteed to be correct for everyone. Callers can work around this by
/// fetching values as i64 and then doing the interpretation themselves or by
/// defining a newtype and implementing `FromSql`/`ToSql` for it.
pub trait FromSql: Sized {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self>;
}

impl FromSql for isize {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        i64::column_result(value).and_then(|i| {
            if i < isize::min_value() as i64 || i > isize::max_value() as i64 {
                Err(FromSqlError::OutOfRange(i))
            } else {
                Ok(i as isize)
            }
        })
    }
}

macro_rules! from_sql_integral(
    ($t:ident) => (
        impl FromSql for $t {
            fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
                i64::column_result(value).and_then(|i| {
                    if i < i64::from($t::min_value()) || i > i64::from($t::max_value()) {
                        Err(FromSqlError::OutOfRange(i))
                    } else {
                        Ok(i as $t)
                    }
                })
            }
        }
    )
);

from_sql_integral!(i8);
from_sql_integral!(i16);
from_sql_integral!(i32);
from_sql_integral!(u8);
from_sql_integral!(u16);
from_sql_integral!(u32);

impl FromSql for i64 {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        value.as_i64()
    }
}

impl FromSql for f64 {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        match value {
            ValueRef::Integer(i) => Ok(i as f64),
            ValueRef::Real(f) => Ok(f),
            _ => Err(FromSqlError::InvalidType),
        }
    }
}

impl FromSql for bool {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        i64::column_result(value).map(|i| match i {
            0 => false,
            _ => true,
        })
    }
}

impl FromSql for String {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        value.as_str().map(|s| s.to_string())
    }
}

impl FromSql for Vec<u8> {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        value.as_blob().map(|b| b.to_vec())
    }
}

#[cfg(feature = "i128_blob")]
impl FromSql for i128 {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        use byteorder::{BigEndian, ByteOrder};

        value.as_blob().and_then(|bytes| {
            if bytes.len() == 16 {
                Ok(BigEndian::read_i128(bytes) ^ (1i128 << 127))
            } else {
                Err(FromSqlError::InvalidI128Size(bytes.len()))
            }
        })
    }
}

impl<T: FromSql> FromSql for Option<T> {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        match value {
            ValueRef::Null => Ok(None),
            _ => FromSql::column_result(value).map(Some),
        }
    }
}

impl FromSql for Value {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        Ok(value.into())
    }
}

#[cfg(test)]
mod test {
    use super::FromSql;
    use crate::{Connection, Error};

    fn checked_memory_handle() -> Connection {
        Connection::open_in_memory().unwrap()
    }

    #[test]
    fn test_integral_ranges() {
        let db = checked_memory_handle();

        fn check_ranges<T>(db: &Connection, out_of_range: &[i64], in_range: &[i64])
        where
            T: Into<i64> + FromSql + ::std::fmt::Debug,
        {
            for n in out_of_range {
                let err = db
                    .query_row("SELECT ?", &[n], |r| r.get_checked::<_, T>(0))
                    .unwrap()
                    .unwrap_err();
                match err {
                    Error::IntegralValueOutOfRange(_, value) => assert_eq!(*n, value),
                    _ => panic!("unexpected error: {}", err),
                }
            }
            for n in in_range {
                assert_eq!(
                    *n,
                    db.query_row("SELECT ?", &[n], |r| r.get::<_, T>(0))
                        .unwrap()
                        .into()
                );
            }
        }

        check_ranges::<i8>(&db, &[-129, 128], &[-128, 0, 1, 127]);
        check_ranges::<i16>(&db, &[-32769, 32768], &[-32768, -1, 0, 1, 32767]);
        check_ranges::<i32>(
            &db,
            &[-2147483649, 2147483648],
            &[-2147483648, -1, 0, 1, 2147483647],
        );
        check_ranges::<u8>(&db, &[-2, -1, 256], &[0, 1, 255]);
        check_ranges::<u16>(&db, &[-2, -1, 65536], &[0, 1, 65535]);
        check_ranges::<u32>(&db, &[-2, -1, 4294967296], &[0, 1, 4294967295]);
    }
}
<|endoftext|>


<commit_before>struct CalcObjects<'a> {
  first: &'a str,
  second: &'a str,
}

impl<'a> CalcObjects<'a> {
  fn max_length(&self) -> uint {
    return if self.first.len() > self.second.len() {
      self.first.len()
    }
    else {
      self.second.len()
    };
  }
}

struct JaroWinkler<'a> {
  co: CalcObjects<'a>,
  matches1: Vec<char>,
  matches2: Vec<char>
}

impl<'b> JaroWinkler<'b> {
  fn new<'b> (this_obj: CalcObjects<'b>) -> JaroWinkler<'b> {
    let mut jw = JaroWinkler {
      co: this_obj,
      matches1: Vec::new(),
      matches2: Vec::new()
    };
    jw.matches1 = jw.get_common_chars(false);
    jw.matches2 = jw.get_common_chars(true);
    jw
  }

  fn get_common_chars(&self, ordering: bool) -> Vec<char> {
    let mut common_chars = Vec::new();
    let max_length = self.co.max_length();
    let match_buffer = ( max_length / 2 ) - 1;
    let mut f = self.co.first;
    let mut s = self.co.second;
    if ordering {
      f = self.co.second;
      s = self.co.first;
    }

    if f.len() == 0 || s.len() == 0 {
      return common_chars;
    }

    for (i,c) in f.chars().enumerate() {
      let s_index: uint = if i < match_buffer {
        0
      }
      else {
        i - match_buffer
      };
      let e_index: uint = if s.len() <= i + match_buffer {
        s.len()
      }
      else {
        i + match_buffer + 1
      };
      let word_slice = s.slice(s_index, e_index);
      if word_slice.contains_char(c) {
        common_chars.push(c);
      }
    }
    common_chars
  }

  fn calculate(&self) -> f32 {
    if self.matches1.len() == 0 || self.matches2.len() == 0 {
      return 0.0;
    }
    if self.matches1.len() != self.matches2.len() {
      return 0.0;
    }

    let mut t = 0.0;
    let n = self.matches1.len();
    for i in range(0u,n) {
      if self.matches2[i] != self.matches1[i] {
        t += 0.5;
      }
    }
    let f1: f32 = self.matches1.len() as f32 / self.co.first.len() as f32;
    let f2: f32 = self.matches2.len() as f32 / self.co.second.len() as f32;
    let f3: f32 = (self.matches1.len() as f32 - t) / self.matches1.len() as f32;
    ( ( f1 + f2 + f3 ) / 3.0 )
  }
}

pub fn jaro_winkler_distance<T:Str, U:Str>(str1: T, str2: U) -> f32 {
  let jw = JaroWinkler::new(CalcObjects{ first: str1.as_slice(), second: str2.as_slice() });
  jw.calculate()
}

pub fn levenshtein_distance<T:Str, U:Str>(str1: T, str2: U) -> uint {
  let a = str1.as_slice();
  let b = str2.as_slice();
  a.lev_distance(b)
}<commit_msg>Fixed range issue<commit_after>struct CalcObjects<'a> {
  first: &'a str,
  second: &'a str,
}

impl<'a> CalcObjects<'a> {
  fn max_length(&self) -> uint {
    return if self.first.len() > self.second.len() {
      self.first.len()
    }
    else {
      self.second.len()
    };
  }
}

struct JaroWinkler<'a> {
  co: CalcObjects<'a>,
  matches1: Vec<char>,
  matches2: Vec<char>
}

impl<'b> JaroWinkler<'b> {
  fn new<'b> (this_obj: CalcObjects<'b>) -> JaroWinkler<'b> {
    let mut jw = JaroWinkler {
      co: this_obj,
      matches1: Vec::new(),
      matches2: Vec::new()
    };
    jw.matches1 = jw.get_common_chars(false);
    jw.matches2 = jw.get_common_chars(true);
    jw
  }

  fn get_common_chars(&self, ordering: bool) -> Vec<char> {
    let mut common_chars = Vec::new();
    let max_length = self.co.max_length();
    let match_buffer = ( max_length / 2 ) - 1;
    let mut f = self.co.first;
    let mut s = self.co.second;
    if ordering {
      f = self.co.second;
      s = self.co.first;
    }

    if f.len() == 0 || s.len() == 0 {
      return common_chars;
    }

    for (i,c) in f.chars().enumerate() {
      let s_index: uint = if i < match_buffer {
        0
      }
      else {
        i - match_buffer
      };
      let e_index: uint = if s.len() <= i + match_buffer {
        s.len()
      }
      else {
        i + match_buffer + 1
      };
      let word_slice = s.slice(s_index, e_index);
      if word_slice.contains_char(c) {
        common_chars.push(c);
      }
    }
    common_chars
  }

  fn calculate(&self) -> f32 {
    if self.matches1.len() == 0 || self.matches2.len() == 0 {
      return 0.0;
    }
    if self.matches1.len() != self.matches2.len() {
      return 0.0;
    }

    let mut t = 0.0;
    let n = self.matches1.len();
    for i in 0..n {
      if self.matches2[i] != self.matches1[i] {
        t += 0.5;
      }
    }
    let f1: f32 = self.matches1.len() as f32 / self.co.first.len() as f32;
    let f2: f32 = self.matches2.len() as f32 / self.co.second.len() as f32;
    let f3: f32 = (self.matches1.len() as f32 - t) / self.matches1.len() as f32;
    ( ( f1 + f2 + f3 ) / 3.0 )
  }
}

pub fn jaro_winkler_distance<T:Str, U:Str>(str1: T, str2: U) -> f32 {
  let jw = JaroWinkler::new(CalcObjects{ first: str1.as_slice(), second: str2.as_slice() });
  jw.calculate()
}

pub fn levenshtein_distance<T:Str, U:Str>(str1: T, str2: U) -> uint {
  let a = str1.as_slice();
  let b = str2.as_slice();
  a.lev_distance(b)
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/ABC_Problem

use std::collections::HashSet;

const WORDS: &'static [&'static str] = &["A", "BARK", "BOOK", "TREAT", "COMMON", "SQUAD",
                                         "CONFUSE"];

const BLOCKS: &'static [&'static str] = &["BO", "XK", "DQ", "CP", "NA", "GT", "RE", "TG", "QD",
                                          "FS", "JW", "HU", "VI", "AN", "OB", "ER", "FS", "LY",
                                          "PC", "ZM"];

fn main() {
    println!("******\nmethod 1\n******");
    for word in WORDS {
        println!("can {} be built? {}", word, can_be_built_input_first(*word))
    }

    println!("\n******\nmethod 2\n******");
    for word in WORDS {
        println!("can {} be built? {}",
                 word,
                 can_be_built_blocks_first(*word))
    }
}

/// First method (common solution among other languages)
///
/// Iterates through the letters of the input and checks if there is a suitable
/// *unused* block for each letter
fn can_be_built_input_first(input: &str) -> bool {
    let mut used = HashSet::new();

    for chr in input.chars() {
        for (ind, block) in BLOCKS.iter().enumerate() {
            if !used.contains(&ind) && block.contains(chr) {
                used.insert(ind);
                break;
            }
        }
    }

    // If the number of used indices is equal to the input length, then we
    // have can successfully make the word with the blocks.
    used.len() == input.len()
}

/// Second method
///
/// Iterates over the blocks. For each block it checks if it can be used for one
/// of the characters in the input that hasn't already been fulfilled.
/// It should be more efficient than the first method whenever there are more
/// blocks than characters in the input.
fn can_be_built_blocks_first(input: &str) -> bool {
    let mut matched = HashSet::new();

    BLOCKS.iter().any(|block| {
        for letter in block.chars() {
            let needle = input.char_indices().find(|&(i, c)| {
                // See if any of the letters in the block can be used for this word
                c == letter && !matched.contains(&i)
            });

            if let Some((idx, _)) = needle {
                // letter with offset idx in the original word has been matched
                matched.insert(idx);
                // don't check the other letter in this block
                // (we can use one character per block)
                break;
            }
        }

        // The iterator will halt if/when this becomes true, so it will early
        // return whenever there is a solution found.
        matched.len() == input.len()
    })
}

#[test]
fn test_solutions() {
    let expected = [true, true, false, true, false, true, true];

    for (&word, &exp) in WORDS.iter().zip(expected.iter()) {
        assert_eq!(can_be_built_input_first(word), exp);
        assert_eq!(can_be_built_blocks_first(word), exp);
    }
}
<commit_msg>remove Rosetta Code comment at top of file<commit_after>use std::collections::HashSet;

const WORDS: &'static [&'static str] = &["A", "BARK", "BOOK", "TREAT", "COMMON", "SQUAD",
                                         "CONFUSE"];

const BLOCKS: &'static [&'static str] = &["BO", "XK", "DQ", "CP", "NA", "GT", "RE", "TG", "QD",
                                          "FS", "JW", "HU", "VI", "AN", "OB", "ER", "FS", "LY",
                                          "PC", "ZM"];

fn main() {
    println!("******\nmethod 1\n******");
    for word in WORDS {
        println!("can {} be built? {}", word, can_be_built_input_first(*word))
    }

    println!("\n******\nmethod 2\n******");
    for word in WORDS {
        println!("can {} be built? {}",
                 word,
                 can_be_built_blocks_first(*word))
    }
}

/// First method (common solution among other languages)
///
/// Iterates through the letters of the input and checks if there is a suitable
/// *unused* block for each letter
fn can_be_built_input_first(input: &str) -> bool {
    let mut used = HashSet::new();

    for chr in input.chars() {
        for (ind, block) in BLOCKS.iter().enumerate() {
            if !used.contains(&ind) && block.contains(chr) {
                used.insert(ind);
                break;
            }
        }
    }

    // If the number of used indices is equal to the input length, then we
    // have can successfully make the word with the blocks.
    used.len() == input.len()
}

/// Second method
///
/// Iterates over the blocks. For each block it checks if it can be used for one
/// of the characters in the input that hasn't already been fulfilled.
/// It should be more efficient than the first method whenever there are more
/// blocks than characters in the input.
fn can_be_built_blocks_first(input: &str) -> bool {
    let mut matched = HashSet::new();

    BLOCKS.iter().any(|block| {
        for letter in block.chars() {
            let needle = input.char_indices().find(|&(i, c)| {
                // See if any of the letters in the block can be used for this word
                c == letter && !matched.contains(&i)
            });

            if let Some((idx, _)) = needle {
                // letter with offset idx in the original word has been matched
                matched.insert(idx);
                // don't check the other letter in this block
                // (we can use one character per block)
                break;
            }
        }

        // The iterator will halt if/when this becomes true, so it will early
        // return whenever there is a solution found.
        matched.len() == input.len()
    })
}

#[test]
fn test_solutions() {
    let expected = [true, true, false, true, false, true, true];

    for (&word, &exp) in WORDS.iter().zip(expected.iter()) {
        assert_eq!(can_be_built_input_first(word), exp);
        assert_eq!(can_be_built_blocks_first(word), exp);
    }
}
<|endoftext|>


<commit_before>//! Check if a reduction makes file smaller, and keep best reductions.
//! Works asynchronously when possible

use crate::atomicmin::AtomicMin;
use crate::deflate;
use crate::png::PngData;
use crate::png::PngImage;
use crate::png::STD_COMPRESSION;
use crate::png::STD_FILTERS;
use crate::png::STD_STRATEGY;
use crate::png::STD_WINDOW;
#[cfg(not(feature = "parallel"))]
use crate::rayon;
use crate::Deadline;
#[cfg(feature = "parallel")]
use rayon;
use rayon::prelude::*;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
#[cfg(feature = "parallel")]
use std::sync::mpsc::*;
use std::sync::Arc;
use std::thread;

struct Candidate {
    image: PngData,
    filter: u8,
    // first wins tie-breaker
    nth: usize,
}

impl Candidate {
    fn cmp_key(&self) -> impl Ord {
        (
            self.image.idat_data.len(),
            self.image.raw.data.len(),
            self.image.raw.ihdr.bit_depth,
            self.filter,
            self.nth,
        )
    }
}

/// Collect image versions and pick one that compresses best
pub(crate) struct Evaluator {
    deadline: Arc<Deadline>,
    nth: AtomicUsize,
    best_candidate_size: Arc<AtomicMin>,
    /// images are sent to the thread for evaluation
    #[cfg(feature = "parallel")]
    eval_send: SyncSender<Candidate>,
    // the thread helps evaluate images asynchronously
    #[cfg(feature = "parallel")]
    eval_thread: thread::JoinHandle<Option<Candidate>>,
    // in non-parallel mode, images are evaluated synchronously
    #[cfg(not(feature = "parallel"))]
    eval_best_candidate: Option<Candidate>,
}

impl Evaluator {
    pub fn new(deadline: Arc<Deadline>) -> Self {
        #[cfg(feature = "parallel")]
        let (tx, rx) = sync_channel(4);
        Self {
            deadline,
            best_candidate_size: Arc::new(AtomicMin::new(None)),
            nth: AtomicUsize::new(0),
            #[cfg(feature = "parallel")]
            eval_send: tx,
            #[cfg(feature = "parallel")]
            eval_thread: thread::spawn(move || rx.into_iter().min_by_key(Candidate::cmp_key)),
            #[cfg(not(feature = "parallel"))]
            eval_best_candidate: None,
        }
    }

    /// Wait for all evaluations to finish and return smallest reduction
    /// Or `None` if all reductions were worse than baseline.
    #[cfg(feature = "parallel")]
    fn get_best_candidate(self) -> Option<Candidate> {
        drop(self.eval_send); // disconnect the sender, breaking the loop in the thread
        self.eval_thread.join().expect("eval thread")
    }

    #[cfg(not(feature = "parallel"))]
    fn get_best_candidate(self) -> Option<Candidate> {
        self.eval_best_candidate
    }

    pub fn get_result(self) -> Option<PngData> {
        self.get_best_candidate().map(|candidate| candidate.image)
    }

    /// Set baseline image. It will be used only to measure minimum compression level required
    pub fn set_baseline(&self, image: Arc<PngImage>) {
        self.try_image_inner(image, false)
    }

    /// Check if the image is smaller than others
    pub fn try_image(&self, image: Arc<PngImage>) {
        self.try_image_inner(image, true)
    }

    fn try_image_inner(&self, image: Arc<PngImage>, is_reduction: bool) {
        let nth = self.nth.fetch_add(1, SeqCst);
        // These clones are only cheap refcounts
        let deadline = self.deadline.clone();
        let best_candidate_size = self.best_candidate_size.clone();
        // sends it off asynchronously for compression,
        // but results will be collected via the message queue
        #[cfg(feature = "parallel")]
        let eval_send = self.eval_send.clone();
        rayon::spawn(move || {
            let filters_iter = STD_FILTERS.par_iter().with_max_len(1);

            // Updating of best result inside the parallel loop would require locks,
            // which are dangerous to do in side Rayon's loop.
            // Instead, only update (atomic) best size in real time,
            // and the best result later without need for locks.
            filters_iter.for_each(|&filter| {
                if deadline.passed() {
                    return;
                }
                if let Ok(idat_data) = deflate::deflate(
                    &image.filter_image(filter),
                    STD_COMPRESSION,
                    STD_STRATEGY,
                    STD_WINDOW,
                    &best_candidate_size,
                    &deadline,
                ) {
                    best_candidate_size.set_min(idat_data.len());
                    // ignore baseline images after this point
                    if !is_reduction {
                        return;
                    }
                    // the rest is shipped to the evavluation/collection thread
                    let new = Candidate {
                        image: PngData {
                            idat_data,
                            raw: Arc::clone(&image),
                        },
                        filter,
                        nth,
                    };

                    #[cfg(feature = "parallel")]
                    {
                        eval_send.send(new).expect("send");
                    }

                    #[cfg(not(feature = "parallel"))]
                    {
                        match self.eval_best_candidate {
                            Some(prev) if prev.cmp_key() < new.cmp_key() => {}
                            _ => self.eval_best_candidate = Some(new),
                        }
                    }
                }
            });
        });
    }
}
<commit_msg>Bring back RefCell<commit_after>//! Check if a reduction makes file smaller, and keep best reductions.
//! Works asynchronously when possible

use crate::atomicmin::AtomicMin;
use crate::deflate;
use crate::png::PngData;
use crate::png::PngImage;
use crate::png::STD_COMPRESSION;
use crate::png::STD_FILTERS;
use crate::png::STD_STRATEGY;
use crate::png::STD_WINDOW;
#[cfg(not(feature = "parallel"))]
use crate::rayon;
use crate::Deadline;
use rayon::prelude::*;
#[cfg(not(feature = "parallel"))]
use std::cell::RefCell;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
#[cfg(feature = "parallel")]
use std::sync::mpsc::*;
use std::sync::Arc;
#[cfg(feature = "parallel")]
use std::thread;

struct Candidate {
    image: PngData,
    filter: u8,
    // first wins tie-breaker
    nth: usize,
}

impl Candidate {
    fn cmp_key(&self) -> impl Ord {
        (
            self.image.idat_data.len(),
            self.image.raw.data.len(),
            self.image.raw.ihdr.bit_depth,
            self.filter,
            self.nth,
        )
    }
}

/// Collect image versions and pick one that compresses best
pub(crate) struct Evaluator {
    deadline: Arc<Deadline>,
    nth: AtomicUsize,
    best_candidate_size: Arc<AtomicMin>,
    /// images are sent to the thread for evaluation
    #[cfg(feature = "parallel")]
    eval_send: SyncSender<Candidate>,
    // the thread helps evaluate images asynchronously
    #[cfg(feature = "parallel")]
    eval_thread: thread::JoinHandle<Option<Candidate>>,
    // in non-parallel mode, images are evaluated synchronously
    #[cfg(not(feature = "parallel"))]
    eval_best_candidate: RefCell<Option<Candidate>>,
}

impl Evaluator {
    pub fn new(deadline: Arc<Deadline>) -> Self {
        #[cfg(feature = "parallel")]
        let (tx, rx) = sync_channel(4);
        Self {
            deadline,
            best_candidate_size: Arc::new(AtomicMin::new(None)),
            nth: AtomicUsize::new(0),
            #[cfg(feature = "parallel")]
            eval_send: tx,
            #[cfg(feature = "parallel")]
            eval_thread: thread::spawn(move || rx.into_iter().min_by_key(Candidate::cmp_key)),
            #[cfg(not(feature = "parallel"))]
            eval_best_candidate: RefCell::new(None),
        }
    }

    /// Wait for all evaluations to finish and return smallest reduction
    /// Or `None` if all reductions were worse than baseline.
    #[cfg(feature = "parallel")]
    fn get_best_candidate(self) -> Option<Candidate> {
        drop(self.eval_send); // disconnect the sender, breaking the loop in the thread
        self.eval_thread.join().expect("eval thread")
    }

    #[cfg(not(feature = "parallel"))]
    fn get_best_candidate(self) -> Option<Candidate> {
        self.eval_best_candidate.into_inner()
    }

    pub fn get_result(self) -> Option<PngData> {
        self.get_best_candidate().map(|candidate| candidate.image)
    }

    /// Set baseline image. It will be used only to measure minimum compression level required
    pub fn set_baseline(&self, image: Arc<PngImage>) {
        self.try_image_inner(image, false)
    }

    /// Check if the image is smaller than others
    pub fn try_image(&self, image: Arc<PngImage>) {
        self.try_image_inner(image, true)
    }

    fn try_image_inner(&self, image: Arc<PngImage>, is_reduction: bool) {
        let nth = self.nth.fetch_add(1, SeqCst);
        // These clones are only cheap refcounts
        let deadline = self.deadline.clone();
        let best_candidate_size = self.best_candidate_size.clone();
        // sends it off asynchronously for compression,
        // but results will be collected via the message queue
        #[cfg(feature = "parallel")]
        let eval_send = self.eval_send.clone();
        rayon::spawn(move || {
            let filters_iter = STD_FILTERS.par_iter().with_max_len(1);

            // Updating of best result inside the parallel loop would require locks,
            // which are dangerous to do in side Rayon's loop.
            // Instead, only update (atomic) best size in real time,
            // and the best result later without need for locks.
            filters_iter.for_each(|&filter| {
                if deadline.passed() {
                    return;
                }
                if let Ok(idat_data) = deflate::deflate(
                    &image.filter_image(filter),
                    STD_COMPRESSION,
                    STD_STRATEGY,
                    STD_WINDOW,
                    &best_candidate_size,
                    &deadline,
                ) {
                    best_candidate_size.set_min(idat_data.len());
                    // ignore baseline images after this point
                    if !is_reduction {
                        return;
                    }
                    // the rest is shipped to the evavluation/collection thread
                    let new = Candidate {
                        image: PngData {
                            idat_data,
                            raw: Arc::clone(&image),
                        },
                        filter,
                        nth,
                    };

                    #[cfg(feature = "parallel")]
                    {
                        eval_send.send(new).expect("send");
                    }

                    #[cfg(not(feature = "parallel"))]
                    {
                        match &mut *self.eval_best_candidate.borrow_mut() {
                            Some(prev) if prev.cmp_key() < new.cmp_key() => {}
                            best => *best = Some(new),
                        }
                    }
                }
            });
        });
    }
}
<|endoftext|>


<commit_before>extern crate gst;

use std::env;

fn main(){
    gst::init();
    let args: Vec<String> = env::args().collect();
    let uri = if args.len() == 2 {
        gst::filename_to_uri(args[1].as_ref()).unwrap()
    }else{
        panic!("Usage: playbin file_path");
    };
    let mut playbin = gst::PlayBin::new("video_player").expect("Couldn't create playbin");
    let mut appsink = gst::AppSink::new("video_sink").expect("Couldn't create appsink");
    playbin.set_uri(uri.as_ref());
    playbin.set_video_sink(&appsink);
    appsink.set("sync", false);
	let mut bus = playbin.bus().expect("Couldn't get bus from pipeline");
	let bus_receiver = bus.receiver();
    let mut mainloop = gst::MainLoop::new();
    mainloop.spawn();
    playbin.play();
	loop {
        let mut exit = false;
        while let Ok(msg) = bus_receiver.try_recv(){
            match msg.parse(){
                gst::Message::StateChangedParsed{ref old, ref new, ..} => {
                    println!("element `{}` changed from {:?} to {:?}", msg.src_name(), old, new);
                }
                gst::Message::ErrorParsed{ref error, ref debug, ..} => {
                    println!("error msg from element `{}`: {}, {}. Quitting", msg.src_name(), error.message(), debug);
                    exit = true;
                    break;
                }
                gst::Message::Eos(_) => {
                    println!("eos received quiting");
                    exit = true;
                    break;
                }
                _ => {
                    println!("msg of type `{}` from element `{}`", msg.type_name(), msg.src_name());
                }
            }
        }
		match appsink.recv(){
            Ok(gst::appsink::Message::NewSample(sample)) | Ok(gst::appsink::Message::NewPreroll(sample)) => {
                let videoframe = sample.video_frame().unwrap();
                println!("Received sample with w: {}, h: {}", videoframe.width(), videoframe.height());
            }
            Ok(gst::appsink::Message::Eos) => {
                println!("Got no sample when polling. EOS");
                break;
            }
            Err(_) => {
                println!("Error, exiting");
                break;
            }
        }
        if exit { break; }
    }

    playbin.set_null_state();
    playbin.get_state(gst::ffi::GST_CLOCK_TIME_NONE);
	mainloop.quit();
}
<commit_msg>Fix appsink_no_sync to not block on errors<commit_after>extern crate gst;

use std::env;

fn main(){
    gst::init();
    let args: Vec<String> = env::args().collect();
    let uri = if args.len() == 2 {
        gst::filename_to_uri(args[1].as_ref()).unwrap()
    }else{
        panic!("Usage: playbin file_path");
    };
    let mut playbin = gst::PlayBin::new("video_player").expect("Couldn't create playbin");
    let mut appsink = gst::AppSink::new("video_sink").expect("Couldn't create appsink");
    playbin.set_uri(uri.as_ref());
    playbin.set_video_sink(&appsink);
    appsink.set("sync", false);
	let mut bus = playbin.bus().expect("Couldn't get bus from pipeline");
	let bus_receiver = bus.receiver();
    let mut mainloop = gst::MainLoop::new();
    mainloop.spawn();
    playbin.play();
	loop {
        let mut exit = false;
        while let Ok(msg) = bus_receiver.try_recv(){
            match msg.parse(){
                gst::Message::StateChangedParsed{ref old, ref new, ..} => {
                    println!("element `{}` changed from {:?} to {:?}", msg.src_name(), old, new);
                }
                gst::Message::ErrorParsed{ref error, ref debug, ..} => {
                    println!("error msg from element `{}`: {}, {}. Quitting", msg.src_name(), error.message(), debug);
                    exit = true;
                    break;
                }
                _ => {
                    println!("msg of type `{}` from element `{}`", msg.type_name(), msg.src_name());
                }
            }
        }
        if exit { break; }

		match appsink.recv(){
            Ok(gst::appsink::Message::NewSample(sample)) | Ok(gst::appsink::Message::NewPreroll(sample)) => {
                let videoframe = sample.video_frame().unwrap();
                println!("Received sample with w: {}, h: {}", videoframe.width(), videoframe.height());
            }
            Ok(gst::appsink::Message::Eos) => {
                println!("Got no sample when polling. EOS");
                break;
            }
            Err(_) => {
                println!("Error, exiting");
                break;
            }
        }
    }

    playbin.set_null_state();
    playbin.get_state(gst::ffi::GST_CLOCK_TIME_NONE);
	mainloop.quit();
}
<|endoftext|>


<commit_before>/* The Wizards' Wallet
 * Written in 2014 by
 *   Andrew Poelstra <apoelstra@wpsoftware.net>
 *
 * To the extent possible under law, the author(s) have dedicated all
 * copyright and related and neighboring rights to this software to
 * the public domain worldwide. This software is distributed without
 * any warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication
 * along with this software.
 * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
 */

//! # RPC Server
//!
//! Functions and data to handle RPC calls

use std::collections::TreeMap;
use std::time::Duration;
use serialize::Decodable;
use serialize::json;
use serialize::json::ToJson;

use bitcoin::util::hash::Sha256dHash;
use jsonrpc;
use jsonrpc::error::{standard_error, Error, InvalidParams, MethodNotFound};
use phf::PhfOrderedMap;

use bitcoind::IdleState;
use coinjoin::server::{Server, Session, SessionId};

pub type JsonResult = jsonrpc::JsonResult<json::Json>;

/// A single RPC command
pub struct RpcCall {
  name: &'static str,
  desc: &'static str,
  usage: &'static str,
  coinjoin: bool,
  call: fn(&RpcCall, &mut IdleState, Vec<json::Json>) -> JsonResult
}

// Forget you saw this macro...just forget it.
macro_rules! rpc_calls(
  ( $( #[doc=$doc:tt]
       #[usage=$usage:tt]
       #[coinjoin=$coinjoin:tt]
       pub fn $name:ident($($param:tt: $paramty:ty),+) $code:expr),+ ) => (
    $(
      // `tt` token trees can only be passed to a macro. On the other hand,
      // there is no other type which will accept a doccomment as a token.
      // So we accept a tt and hand it to the macro_rules! macro ;)
      //
      // Notice that we are using the same name as the outer macro...this
      // means that the macro can only be called once, since we effectively
      // overwrite it here.
      macro_rules! rpc_calls( () => (
        // I don't really want these to be public, but they don't show up
        // in the output of `cargo doc` otherwise.
        #[doc=$doc]
        pub fn $name($($param: $paramty),+) -> JsonResult { $code }
      ))
      rpc_calls!()
    )+
    // Let's do it again!
    macro_rules! rpc_calls( () => (
      static RPC_CALLS: PhfOrderedMap<&'static str, RpcCall> = phf_ordered_map! {
        $(stringify!($name) => RpcCall {
            name: stringify!($name),
            desc: $doc,
            usage: $usage,
            coinjoin: $coinjoin,
            call: $name
          }
        ),+
      };
    ))
    rpc_calls!()
    // Erase the dummy macro, to avoid confusing errors in case somebody
    // tries to use it outside of this macro.
    macro_rules! rpc_calls(
      () => (Sorry, you can only call rpc_calls! once.)
    )
  )
)

// Main RPC call list
rpc_calls!{
  #[doc="Fetches a list of commands"]
  #[usage=""]
  #[coinjoin=false]
  pub fn help(_: &RpcCall, idle_state: &mut IdleState, _: Vec<json::Json>) {
    let mut ret = TreeMap::new();
    for call in RPC_CALLS.values() {
      if !call.coinjoin || idle_state.config.coinjoin_on {
        let mut obj = TreeMap::new();
        obj.insert("description".to_string(), json::String(call.desc.to_string()));
        obj.insert("usage".to_string(), json::String(call.usage.to_string()));
        ret.insert(call.name.to_string(), json::Object(obj));
      }
    }
    Ok(json::Object(ret))
  },

  #[doc="Gets a specific block from the blockchain"]
  #[usage="<hash>"]
  #[coinjoin=false]
  pub fn getblock(rpc: &RpcCall, idle_state: &mut IdleState, params: Vec<json::Json>) {
    match params.len() {
      1 => {
        let blockchain = idle_state.blockchain.read();
        let hash: Sha256dHash = try!(decode_param(params[0].clone()));

        match blockchain.get_block(hash) {
          Some(node) => {
            let mut ret = TreeMap::new();
            ret.insert("header".to_string(), node.block.header.to_json());
            ret.insert("has_txdata".to_string(), json::Boolean(node.has_txdata));
            if node.has_txdata {
              ret.insert("transactions".to_string(), node.block.txdata.to_json());
            }
            Ok(json::Object(ret))
          }
          None => Err(bitcoin_json_error(BlockNotFound, Some(hash.to_json()))),
        }
      }
      _ => Err(usage_error(rpc))
    }
  },

  #[doc="Gets the current number of unspent outputs on the blockchain."]
  #[usage=""]
  #[coinjoin=false]
  pub fn getutxocount(rpc: &RpcCall, idle_state: &mut IdleState, params: Vec<json::Json>) {
    match params.len() {
      0 => Ok(json::Number(idle_state.utxo_set.read().n_utxos() as f64)),
      _ => Err(usage_error(rpc))
    }
  },

  #[doc="Gets the length of the longest chain, starting from the given hash or genesis."]
  #[usage="[start hash]"]
  #[coinjoin=false]
  pub fn getblockcount(rpc: &RpcCall, idle_state: &mut IdleState, params: Vec<json::Json>) {
    match params.len() {
      0 => {
        let blockchain = idle_state.blockchain.read();
        // Subtract 1 from the hash since the genesis counts as block 0
        Ok(json::Number(blockchain.iter(blockchain.genesis_hash()).count() as f64 - 1.0))
      }
      1 => {
        let blockchain = idle_state.blockchain.read();
        let hash: Sha256dHash = try!(decode_param(params[0].clone()));

        // Subtract 1 from the hash since the genesis counts as block 0
        match blockchain.iter(hash).count() {
          0 => Err(bitcoin_json_error(BlockNotFound, Some(hash.to_json()))),
          n => Ok(json::Number(n as f64 - 1.0)),
        }
      }
      _ => Err(usage_error(rpc))
    }
  },

  #[doc="Starts a new coinjoin session"]
  #[usage="<target amount (satoshi)> <join duration (seconds)> <merge duration (seconds)>"]
  #[coinjoin=true]
  pub fn coinjoin_start(rpc: &RpcCall, idle_state: &mut IdleState, params: Vec<json::Json>) {
    match params.len() {
      3 => {
        let target: u64 = try!(decode_param(params[0].clone()));
        let join_duration = Duration::milliseconds(try!(decode_param(params[1].clone())));
        let expiry_duration = Duration::milliseconds(try!(decode_param(params[2].clone())));

        // Start session manager if we haven't
        if idle_state.coinjoin.is_none() {
          idle_state.coinjoin = Some(Server::new());
        }
        // Update the server state
        let server = idle_state.coinjoin.get_mut_ref();
        server.update_all();
        // Add the new sesion
        let session = try!(Session::new(target, join_duration, expiry_duration)
                             .map_err(|e| bitcoin_json_error(BadRng,
                                                             Some(json::String(e.to_string())))));
        let id = session.id();
        server.set_current_session(session);
        Ok(id.to_json())
      }
      _ => Err(usage_error(rpc))
    }
  },

  #[doc="Gets the status of the current coinjoin session"]
  #[usage="[session id]"]
  #[coinjoin=true]
  pub fn coinjoin_status(rpc: &RpcCall, idle_state: &mut IdleState, params: Vec<json::Json>) {
    if idle_state.coinjoin.is_none() {
      return Err(bitcoin_json_error(SessionNotFound, None));
    }
    // Update the server state
    let server = idle_state.coinjoin.get_mut_ref();
    server.update_all();

    match params.len() {
      0 => server.current_session().map_or(Err(bitcoin_json_error(SessionNotFound, None)), |s| Ok(s.to_json())),
      1 => {
        let id: SessionId = try!(decode_param(params[0].clone()));
        server.session(&id).map_or(Err(bitcoin_json_error(SessionNotFound, None)), |s| Ok(s.to_json()))
      }
      _ => Err(usage_error(rpc))
    }
  }
}

enum BitcoinJsonError {
  BadRng,
  BlockNotFound,
  SessionNotFound
}

/// Decode a Json parameter
fn decode_param<T:Decodable<json::Decoder, json::DecoderError>>(param: json::Json) -> jsonrpc::JsonResult<T> {
  let mut decoder = json::Decoder::new(param);
  Decodable::decode(&mut decoder)
    .map_err(|e| standard_error(InvalidParams,
                                Some(json::String(e.to_string()))))
}

/// Create a standard error responses
fn bitcoin_json_error(code: BitcoinJsonError, data: Option<json::Json>) -> Error {
  match code {
    BadRng => Error {
      code: -1,
      message: "Bad RNG".to_string(),
      data: data
    },
    BlockNotFound => Error {
      code: -2,
      message: "Block not found".to_string(),
      data: data
    },
    SessionNotFound => Error {
      code: -3,
      message: "Coinjoin session not found".to_string(),
      data: data
    }
  }
}

/// Generates a `usage` error message
fn usage_error(rpc: &RpcCall) -> Error {
  standard_error(InvalidParams,
                 Some(json::String(format!("Usage: {} {}", rpc.name, rpc.usage))))
}

/// Handles a JSON-RPC request, returning a result to be given back to the peer
pub fn handle_rpc(request: jsonrpc::Request, idle_state: &mut IdleState) -> JsonResult {
  let method = request.method.as_slice();
  match RPC_CALLS.find_equiv(&method) {
    Some(rpc) if !rpc.coinjoin || idle_state.config.coinjoin_on =>
      (rpc.call)(rpc, idle_state, request.params),
    _ => Err(standard_error(MethodNotFound,
                            Some(json::String(request.method.clone()))))
  }
}

<commit_msg>Add `raw_trace` RPC which traces a raw transaction's script execution<commit_after>/* The Wizards' Wallet
 * Written in 2014 by
 *   Andrew Poelstra <apoelstra@wpsoftware.net>
 *
 * To the extent possible under law, the author(s) have dedicated all
 * copyright and related and neighboring rights to this software to
 * the public domain worldwide. This software is distributed without
 * any warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication
 * along with this software.
 * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
 */

//! # RPC Server
//!
//! Functions and data to handle RPC calls

use std::io::{IoError, MemReader};
use std::collections::TreeMap;
use std::time::Duration;
use serialize::Decodable;
use serialize::hex::FromHex;
use serialize::json;
use serialize::json::ToJson;

use bitcoin::network::serialize::{RawDecoder, deserialize};
use bitcoin::network::encodable::ConsensusDecodable;
use bitcoin::util::hash::Sha256dHash;
use bitcoin::blockdata::transaction::Transaction;
use jsonrpc;
use jsonrpc::error::{standard_error, Error, InvalidParams, MethodNotFound};
use phf::PhfOrderedMap;

use bitcoind::IdleState;
use coinjoin::server::{Server, Session, SessionId};

pub type JsonResult = jsonrpc::JsonResult<json::Json>;

/// A single RPC command
pub struct RpcCall {
  name: &'static str,
  desc: &'static str,
  usage: &'static str,
  coinjoin: bool,
  call: fn(&RpcCall, &mut IdleState, Vec<json::Json>) -> JsonResult
}

// Forget you saw this macro...just forget it.
macro_rules! rpc_calls(
  ( $( #[doc=$doc:tt]
       #[usage=$usage:tt]
       #[coinjoin=$coinjoin:tt]
       pub fn $name:ident($($param:tt: $paramty:ty),+) $code:expr),+ ) => (
    $(
      // `tt` token trees can only be passed to a macro. On the other hand,
      // there is no other type which will accept a doccomment as a token.
      // So we accept a tt and hand it to the macro_rules! macro ;)
      //
      // Notice that we are using the same name as the outer macro...this
      // means that the macro can only be called once, since we effectively
      // overwrite it here.
      macro_rules! rpc_calls( () => (
        // I don't really want these to be public, but they don't show up
        // in the output of `cargo doc` otherwise.
        #[doc=$doc]
        pub fn $name($($param: $paramty),+) -> JsonResult { $code }
      ))
      rpc_calls!()
    )+
    // Let's do it again!
    macro_rules! rpc_calls( () => (
      static RPC_CALLS: PhfOrderedMap<&'static str, RpcCall> = phf_ordered_map! {
        $(stringify!($name) => RpcCall {
            name: stringify!($name),
            desc: $doc,
            usage: $usage,
            coinjoin: $coinjoin,
            call: $name
          }
        ),+
      };
    ))
    rpc_calls!()
    // Erase the dummy macro, to avoid confusing errors in case somebody
    // tries to use it outside of this macro.
    macro_rules! rpc_calls(
      () => (Sorry, you can only call rpc_calls! once.)
    )
  )
)

// Main RPC call list
rpc_calls!{
  #[doc="Fetches a list of commands"]
  #[usage=""]
  #[coinjoin=false]
  pub fn help(_: &RpcCall, idle_state: &mut IdleState, _: Vec<json::Json>) {
    let mut ret = TreeMap::new();
    for call in RPC_CALLS.values() {
      if !call.coinjoin || idle_state.config.coinjoin_on {
        let mut obj = TreeMap::new();
        obj.insert("description".to_string(), json::String(call.desc.to_string()));
        obj.insert("usage".to_string(), json::String(call.usage.to_string()));
        ret.insert(call.name.to_string(), json::Object(obj));
      }
    }
    Ok(json::Object(ret))
  },

  #[doc="Gets a specific block from the blockchain"]
  #[usage="<hash>"]
  #[coinjoin=false]
  pub fn getblock(rpc: &RpcCall, idle_state: &mut IdleState, params: Vec<json::Json>) {
    match params.len() {
      1 => {
        let blockchain = idle_state.blockchain.read();
        let hash: Sha256dHash = try!(decode_param(params[0].clone()));

        match blockchain.get_block(hash) {
          Some(node) => {
            let mut ret = TreeMap::new();
            ret.insert("header".to_string(), node.block.header.to_json());
            ret.insert("has_txdata".to_string(), json::Boolean(node.has_txdata));
            if node.has_txdata {
              ret.insert("transactions".to_string(), node.block.txdata.to_json());
            }
            Ok(json::Object(ret))
          }
          None => Err(bitcoin_json_error(BlockNotFound, Some(hash.to_json()))),
        }
      }
      _ => Err(usage_error(rpc))
    }
  },

  #[doc="Gets the current number of unspent outputs on the blockchain."]
  #[usage=""]
  #[coinjoin=false]
  pub fn getutxocount(rpc: &RpcCall, idle_state: &mut IdleState, params: Vec<json::Json>) {
    match params.len() {
      0 => Ok(json::Number(idle_state.utxo_set.read().n_utxos() as f64)),
      _ => Err(usage_error(rpc))
    }
  },

  #[doc="Gets the length of the longest chain, starting from the given hash or genesis."]
  #[usage="[start hash]"]
  #[coinjoin=false]
  pub fn getblockcount(rpc: &RpcCall, idle_state: &mut IdleState, params: Vec<json::Json>) {
    match params.len() {
      0 => {
        let blockchain = idle_state.blockchain.read();
        // Subtract 1 from the hash since the genesis counts as block 0
        Ok(json::Number(blockchain.iter(blockchain.genesis_hash()).count() as f64 - 1.0))
      }
      1 => {
        let blockchain = idle_state.blockchain.read();
        let hash: Sha256dHash = try!(decode_param(params[0].clone()));

        // Subtract 1 from the hash since the genesis counts as block 0
        match blockchain.iter(hash).count() {
          0 => Err(bitcoin_json_error(BlockNotFound, Some(hash.to_json()))),
          n => Ok(json::Number(n as f64 - 1.0)),
        }
      }
      _ => Err(usage_error(rpc))
    }
  },

  #[doc="Decodes a raw transaction"]
  #[usage="<hex-encoded tx data>"]
  #[coinjoin=false]
  pub fn raw_decode(rpc: &RpcCall, _: &mut IdleState, params: Vec<json::Json>) {
    match params.len() {
      1 => {
        let tx: Transaction = try!(decode_hex_param(params[0].clone()));
        Ok(tx.to_json())
      }
      _ => Err(usage_error(rpc))
    }
  },

  #[doc="Validates a raw transaction"]
  #[usage="<hex-encoded tx data>"]
  #[coinjoin=false]
  pub fn raw_validate(rpc: &RpcCall, idle_state: &mut IdleState, params: Vec<json::Json>) {
    match params.len() {
      1 => {
        let tx: Transaction = try!(decode_hex_param(params[0].clone()));
        let utxo_set = idle_state.utxo_set.read();
        match tx.validate(&*utxo_set) {
          Ok(_) => Ok(json::Boolean(true)),
          Err(e) => Err(bitcoin_json_error(InvalidTx, Some(json::String(e.to_string()))))
        }
      }
      _ => Err(usage_error(rpc))
    }
  },

  #[doc="Traces execution of a raw transaction's scripts"]
  #[usage="<hex-encoded tx data>"]
  #[coinjoin=false]
  pub fn raw_trace(rpc: &RpcCall, idle_state: &mut IdleState, params: Vec<json::Json>) {
    match params.len() {
      1 => {
        let tx: Transaction = try!(decode_hex_param(params[0].clone()));
        let utxo_set = idle_state.utxo_set.read();
        Ok(tx.trace(&*utxo_set).to_json())
      }
      _ => Err(usage_error(rpc))
    }
  },

  #[doc="Starts a new coinjoin session"]
  #[usage="<target amount (satoshi)> <join duration (seconds)> <merge duration (seconds)>"]
  #[coinjoin=true]
  pub fn coinjoin_start(rpc: &RpcCall, idle_state: &mut IdleState, params: Vec<json::Json>) {
    match params.len() {
      3 => {
        let target: u64 = try!(decode_param(params[0].clone()));
        let join_duration = Duration::milliseconds(try!(decode_param(params[1].clone())));
        let expiry_duration = Duration::milliseconds(try!(decode_param(params[2].clone())));

        // Start session manager if we haven't
        if idle_state.coinjoin.is_none() {
          idle_state.coinjoin = Some(Server::new());
        }
        // Update the server state
        let server = idle_state.coinjoin.get_mut_ref();
        server.update_all();
        // Add the new sesion
        let session = try!(Session::new(target, join_duration, expiry_duration)
                             .map_err(|e| bitcoin_json_error(BadRng,
                                                             Some(json::String(e.to_string())))));
        let id = session.id();
        server.set_current_session(session);
        Ok(id.to_json())
      }
      _ => Err(usage_error(rpc))
    }
  },

  #[doc="Gets the status of the current coinjoin session"]
  #[usage="[session id]"]
  #[coinjoin=true]
  pub fn coinjoin_status(rpc: &RpcCall, idle_state: &mut IdleState, params: Vec<json::Json>) {
    if idle_state.coinjoin.is_none() {
      return Err(bitcoin_json_error(SessionNotFound, None));
    }
    // Update the server state
    let server = idle_state.coinjoin.get_mut_ref();
    server.update_all();

    match params.len() {
      0 => server.current_session().map_or(Err(bitcoin_json_error(SessionNotFound, None)), |s| Ok(s.to_json())),
      1 => {
        let id: SessionId = try!(decode_param(params[0].clone()));
        server.session(&id).map_or(Err(bitcoin_json_error(SessionNotFound, None)), |s| Ok(s.to_json()))
      }
      _ => Err(usage_error(rpc))
    }
  }
}

enum BitcoinJsonError {
  BadRng,
  BlockNotFound,
  InvalidTx,
  SessionNotFound
}

/// Decode a Json parameter
fn decode_param<T:Decodable<json::Decoder, json::DecoderError>>(param: json::Json) -> jsonrpc::JsonResult<T> {
  let mut decoder = json::Decoder::new(param);
  Decodable::decode(&mut decoder)
    .map_err(|e| standard_error(InvalidParams,
                                Some(json::String(e.to_string()))))
}

/// Decode a hex-encoded parameter
fn decode_hex_param<T:ConsensusDecodable<RawDecoder<MemReader>, IoError>>(param: json::Json)
                                                                          -> jsonrpc::JsonResult<T> {
  let hex: String = try!(decode_param(param));
  let raw = match hex.as_slice().from_hex() {
    Ok(raw) => raw,
    Err(e) => { return Err(standard_error(InvalidParams,
                                          Some(json::String(e.to_string())))); }
  };

  deserialize(raw)
    .map_err(|e| standard_error(InvalidParams,
                                Some(json::String(e.to_string()))))
}

/// Create a standard error responses
fn bitcoin_json_error(code: BitcoinJsonError, data: Option<json::Json>) -> Error {
  match code {
    BadRng => Error {
      code: -1,
      message: "Bad RNG".to_string(),
      data: data
    },
    BlockNotFound => Error {
      code: -2,
      message: "Block not found".to_string(),
      data: data
    },
    InvalidTx => Error {
      code: -3,
      message: "Transaction invalid".to_string(),
      data: data
    },
    SessionNotFound => Error {
      code: -4,
      message: "Coinjoin session not found".to_string(),
      data: data
    }
  }
}

/// Generates a `usage` error message
fn usage_error(rpc: &RpcCall) -> Error {
  standard_error(InvalidParams,
                 Some(json::String(format!("Usage: {} {}", rpc.name, rpc.usage))))
}

/// Handles a JSON-RPC request, returning a result to be given back to the peer
pub fn handle_rpc(request: jsonrpc::Request, idle_state: &mut IdleState) -> JsonResult {
  let method = request.method.as_slice();
  match RPC_CALLS.find_equiv(&method) {
    Some(rpc) if !rpc.coinjoin || idle_state.config.coinjoin_on =>
      (rpc.call)(rpc, idle_state, request.params),
    _ => Err(standard_error(MethodNotFound,
                            Some(json::String(request.method.clone()))))
  }
}

<|endoftext|>


<commit_before>use crate::syntax::ident;
use quote::IdentFragment;
use std::fmt::{self, Display};
use std::slice::Iter;
use syn::parse::{Parse, ParseStream, Result};
use syn::{Path, Token};

mod kw {
    syn::custom_keyword!(namespace);
}

#[derive(Clone)]
pub struct Namespace {
    pub segments: Vec<String>,
}

impl Namespace {
    pub fn none() -> Self {
        Namespace {
            segments: Vec::new(),
        }
    }

    pub fn iter(&self) -> Iter<String> {
        self.segments.iter()
    }
}

impl Parse for Namespace {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut segments = Vec::new();
        if !input.is_empty() {
            input.parse::<kw::namespace>()?;
            input.parse::<Token![=]>()?;
            let path = input.call(Path::parse_mod_style)?;
            for segment in path.segments {
                ident::check(&segment.ident)?;
                segments.push(segment.ident.to_string());
            }
            input.parse::<Option<Token![,]>>()?;
        }
        Ok(Namespace { segments })
    }
}

impl Display for Namespace {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for segment in self {
            f.write_str(segment)?;
            f.write_str("$")?;
        }
        Ok(())
    }
}

impl IdentFragment for Namespace {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(self, f)
    }
}

impl<'a> IntoIterator for &'a Namespace {
    type Item = &'a String;
    type IntoIter = Iter<'a, String>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}
<commit_msg>Revert visibility of Namespace segments from PR 67<commit_after>use crate::syntax::ident;
use quote::IdentFragment;
use std::fmt::{self, Display};
use std::slice::Iter;
use syn::parse::{Parse, ParseStream, Result};
use syn::{Path, Token};

mod kw {
    syn::custom_keyword!(namespace);
}

#[derive(Clone)]
pub struct Namespace {
    segments: Vec<String>,
}

impl Namespace {
    pub fn none() -> Self {
        Namespace {
            segments: Vec::new(),
        }
    }

    pub fn iter(&self) -> Iter<String> {
        self.segments.iter()
    }
}

impl Parse for Namespace {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut segments = Vec::new();
        if !input.is_empty() {
            input.parse::<kw::namespace>()?;
            input.parse::<Token![=]>()?;
            let path = input.call(Path::parse_mod_style)?;
            for segment in path.segments {
                ident::check(&segment.ident)?;
                segments.push(segment.ident.to_string());
            }
            input.parse::<Option<Token![,]>>()?;
        }
        Ok(Namespace { segments })
    }
}

impl Display for Namespace {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for segment in self {
            f.write_str(segment)?;
            f.write_str("$")?;
        }
        Ok(())
    }
}

impl IdentFragment for Namespace {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(self, f)
    }
}

impl<'a> IntoIterator for &'a Namespace {
    type Item = &'a String;
    type IntoIter = Iter<'a, String>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}
<|endoftext|>