<commit_before>extern crate combine;

use std::io::prelude::*;

use combine::{many, letter, Parser, ParseError};

fn parse(program: String) {
    let program = program.as_ref();

    let mut grammar = many(letter());
    let result: Result<(String, &str), ParseError<&str>> = grammar.parse(program);
    match result {
        Ok((value, _remaining_input)) => println!("{:?}", value),
        Err(err) => println!("{}", err)
    }
}

fn main() {
    println!("rusty-lisp v0.1.0");
    println!("Press 'Ctrl+C' to exit");
    println!("");

    let mut stdin = std::io::stdin();
    let mut input = String::new();

    stdin.read_to_string(&mut input).unwrap();
    parse(input);

    println!("Thanks for using!");
}
<commit_msg>we can parse atoms!<commit_after>extern crate combine;

use std::io::prelude::*;

use combine::{spaces, choice, parser, Parser, ParserExt, ParseError};
use combine::char as combine_char;
use combine::primitives::{Stream, State, ParseResult};

#[derive(Debug, PartialEq)]
enum Atom {
    Value(String)
}

fn symbol<I>(input: State<I>) -> ParseResult<String, I>
where I: Stream<Item=char>
{

    let lex_char = |c| combine_char(c).skip(spaces());

    let symbols = choice([lex_char('!'), lex_char('$'), lex_char('%'), lex_char('$'), lex_char('&'),
                    lex_char('|'), lex_char('*'), lex_char('+'), lex_char('-'), lex_char(':'),
                    lex_char('<'), lex_char('='), lex_char('>'), lex_char('?'), lex_char('@'),
                    lex_char('^'), lex_char('_'), lex_char('~')]);

    symbols.map(|c: char| {
            let mut s = String::new();
            s.push(c);
            return s;
        })
        .parse_state(input)

}

fn atom<I>(input: State<I>) -> ParseResult<Atom, I>
where I: Stream<Item=char>
{

    let atom = (parser(symbol::<I>))
        .map(|t| Atom::Value(t))
        .parse_state(input);

    atom
}

fn rusty_lisp<I>(input: State<I>) -> ParseResult<Atom, I>
where I: Stream<Item=char>
{

    let lispval = parser(atom::<I>)
        .parse_state(input);

    lispval

}

fn parse(program: String) {
    let program = program.as_ref();

    let result: Result<(Atom, &str), ParseError<&str>> = parser(rusty_lisp).parse(program);
    match result {
        Ok((value, _remaining_input)) => println!("{:?}", value),
        Err(err) => println!("{}", err)
    }
}

fn main() {
    println!("rusty-lisp v0.1.0");
    println!("Press 'Ctrl+C' to exit");
    println!("");

    let mut stdin = std::io::stdin();
    let mut input = String::new();

    stdin.read_to_string(&mut input).unwrap();
    parse(input);

    println!("Thanks for using!");
}
<|endoftext|>


<commit_before>use std::env;
use std::io::{self, Write};
use std::fs::File;
use std::io::prelude::*;

//#[cfg(unix)]
//use std::os::unix::fs::MetadataExt;

#[cfg(linux)]
use std::os::linux::fs::MetadataExt;

#[cfg(target_os="macos")]
use std::os::macos::fs::MetadataExt;

fn main() {
    let args: Vec<String> = env::args().collect();

    for file in &args[1..] {
        read_file(file);
    }
}

fn read_file(file: &String) {
    let mut buffersize: usize = 1024;
    match File::open(file) {
        Ok(mut handle) => {
            if let Ok(meta) = handle.metadata() {
                let blk = meta.st_blksize();
                if blk < std::usize::MAX as u64 {
                    buffersize = blk as usize;
                }
            }

            let mut buffer = vec![0; buffersize];

            while let Ok(n) = handle.read(&mut buffer) {
                if n == 0 {
                    break;
                };
                if let Err(e) = io::stdout().write_all(&buffer) {
                    eprintln!("{}", e);
                }
            }
        }
        Err(error) => {
            eprintln!("{}", error);
        }
    }
}
<commit_msg>Changed imports<commit_after>use std::env;
use std::io::{self, Write, Read};
use std::fs::File;
//use std::io::prelude::*;

//#[cfg(unix)]
//use std::os::unix::fs::MetadataExt;

#[cfg(linux)]
use std::os::linux::fs::MetadataExt;

#[cfg(target_os="macos")]
use std::os::macos::fs::MetadataExt;

fn main() {
    let args: Vec<String> = env::args().collect();

    for file in &args[1..] {
        read_file(file);
    }
}

fn read_file(file: &String) {
    let mut buffersize: usize = 1024;
    match File::open(file) {
        Ok(mut handle) => {
            if let Ok(meta) = handle.metadata() {
                let blk = meta.st_blksize();
                if blk < std::usize::MAX as u64 {
                    buffersize = blk as usize;
                }
            }

            let mut buffer = vec![0; buffersize];

            while let Ok(n) = handle.read(&mut buffer) {
                if n == 0 {
                    break;
                };
                if let Err(e) = io::stdout().write_all(&buffer) {
                    eprintln!("{}", e);
                }
            }
        }
        Err(error) => {
            eprintln!("{}", error);
        }
    }
}
<|endoftext|>


<commit_before>extern crate iron;

use iron::prelude::*;
use iron::status;

fn main() {
    Iron::new(|&: _: &mut Request| {
        Ok(Response::with((status::Ok, "Hello Rust Warsaw!")))
    }).listen("localhost:3000").unwrap();
}
<commit_msg>Use correct content type<commit_after>extern crate iron;

use iron::mime::Mime;
use iron::prelude::*;
use iron::status;

fn main() {
    Iron::new(|&: _: &mut Request| {
        let content_type: Mime = "text/html".parse().unwrap();
        Ok(Response::with((status::Ok, "Hello Rust Warsaw!")).set(content_type))
    }).listen("localhost:3000").unwrap();
}
<|endoftext|>


<commit_before>#[cfg(test)]
mod tests;

mod game;
mod ai;
mod human_ai;
use game::{VictoryStats};

fn main() {
    let structure = game::GameStructure::new();
    let p2 = ai::MonteCarloAI::new(3000);
    //let p2 = ai::MonteCarloAI::new(1000);
    //let p2 = ai::TreeJudgementAI::new(2);
    //let p1 = ai::RandomSogoAI::new();
    //let p1 = ai::TreeJudgementAI::new(4);
    let p1 = human_ai::HumanPlayer::Active;
    let mut statics = VictoryStats { white : 0, black : 0, draws : 0};
    for i in 0..1 {
        println!("Game {}.", i);
        let state = ai::run_match(&structure, &p1, &p2);
        match state.victory_state {
            game::VictoryState::Win(game::PlayerColor::White) => statics.white += 1,
            game::VictoryState::Win(game::PlayerColor::Black) => statics.black += 1,
            game::VictoryState::Draw      => statics.draws  += 1,
            game::VictoryState::Undecided => (),

        }
        //println!("The game took {:?} turns and ended with {:?}.", state.age, state.victory_state);
        //human_ai::print_gamestate(&state);
    }
    println!("There were {} white and {} black wins as well as {} draws.", statics.white, statics.black, statics.draws);
}
<commit_msg>Start some work on estimating AI power.<commit_after>#[cfg(test)]
mod tests;

mod game;
mod ai;
mod human_ai;
use game::{VictoryStats};

#[allow(dead_code)]
fn run_all_matches(endurance : Vec<i32>, precision : i32) -> Vec<Vec<(i32, i32, f32)>> {
    let structure = game::GameStructure::new();
    let mut result = Vec::new();
    for i in 0..endurance.len() {
        let mut result_row = Vec::new();
        for j in 0..endurance.len() {
            let mut result_cell = VictoryStats::new();
            println!("Comparing {:?} to {:?}", endurance[i], endurance[j]);
            let p1 = ai::MonteCarloAI::new(endurance[i]);
            let p2 = ai::MonteCarloAI::new(endurance[j]);
            for i in 0..precision {
                println!("    Game {} of {}", i, precision);
                let state = ai::run_match(&structure, &p1, &p2);
                match state.victory_state {
                    game::VictoryState::Win(game::PlayerColor::White) => result_cell.white += 1,
                    game::VictoryState::Win(game::PlayerColor::Black) => result_cell.black += 1,
                    game::VictoryState::Draw      => result_cell.draws  += 1,
                    game::VictoryState::Undecided => (),
                }
            }
            result_row.push(calculate_rank_difference(result_cell));
        }
        result.push(result_row);
    }
    println!("{:?}", result);
    return result;
}

#[allow(dead_code)]
fn calculate_rank_difference(stats : VictoryStats) -> (i32, i32, f32) {
    let white_loss_frequency = (stats.black as f32) / ((stats.black as f32) + (stats.white as f32));
    return (stats.white, stats.black, (1.0/white_loss_frequency - 1.0).ln());
}

fn main() {
    //run_all_matches(vec![1000], 1000);

    let structure = game::GameStructure::new();
    let p1 = ai::MonteCarloAI::new(1000);
    //let p2 = ai::MonteCarloAI::new(1000);
    //let p2 = ai::TreeJudgementAI::new(2);
    //let p1 = ai::RandomSogoAI::new();
    //let p1 = ai::TreeJudgementAI::new(4);
    let p2 = human_ai::HumanPlayer::Active;
    let mut statics = VictoryStats { white : 0, black : 0, draws : 0};
    for i in 0..1 {
        println!("Game {}.", i);
        let state = ai::run_match(&structure, &p1, &p2);
        match state.victory_state {
            game::VictoryState::Win(game::PlayerColor::White) => statics.white += 1,
            game::VictoryState::Win(game::PlayerColor::Black) => statics.black += 1,
            game::VictoryState::Draw      => statics.draws  += 1,
            game::VictoryState::Undecided => (),

        }
        //println!("The game took {:?} turns and ended with {:?}.", state.age, state.victory_state);
        //human_ai::print_gamestate(&state);
    }
    println!("There were {} white and {} black wins as well as {} draws.", statics.white, statics.black, statics.draws);
    //*/
}
<|endoftext|>


<commit_before>use std::io::{self, stdin, stdout, Write};

// TODO(tsion): Use the readline library.
fn prompt(line: &mut String) -> io::Result<usize> {
    let current_dir = try!(std::env::current_dir());
    print!("{}> ", current_dir.display());
    try!(stdout().flush());
    stdin().read_line(line)
}

#[derive(Clone, Debug)]
enum Ast {
    Empty,
    Call { command: String, args: Vec<String> }
}

fn parse(line: &str) -> Ast {
    let mut words = line.split_whitespace();

    match words.next() {
        Some(command) => Ast::Call {
            command: String::from(command),
            args: words.map(String::from).collect()
        },
        None => Ast::Empty
    }
}

fn execute(ast: &Ast) -> io::Result<()> {
    match *ast {
        Ast::Empty => Ok(()),
        Ast::Call { ref command, ref args } => {
            std::process::Command::new(command).args(args).status().map(|_| ())
        },
    }
}

fn main() {
    let mut line = String::new();
    loop {
        prompt(&mut line).unwrap();
        let ast = parse(&line);
        execute(&ast);
        line.clear();
    }
}
<commit_msg>Handle Result returned by execute.<commit_after>use std::io::{self, stdin, stdout, Write};

// TODO(tsion): Use the readline library.
fn prompt(line: &mut String) -> io::Result<usize> {
    let current_dir = try!(std::env::current_dir());
    print!("{}> ", current_dir.display());
    try!(stdout().flush());
    stdin().read_line(line)
}

#[derive(Clone, Debug)]
enum Ast {
    Empty,
    Call { command: String, args: Vec<String> }
}

fn parse(line: &str) -> Ast {
    let mut words = line.split_whitespace();

    match words.next() {
        Some(command) => Ast::Call {
            command: String::from(command),
            args: words.map(String::from).collect()
        },
        None => Ast::Empty
    }
}

fn execute(ast: &Ast) -> io::Result<()> {
    match *ast {
        Ast::Empty => Ok(()),
        Ast::Call { ref command, ref args } => {
            std::process::Command::new(command).args(args).status().map(|_| ())
        },
    }
}

fn main() {
    let mut line = String::new();
    loop {
        prompt(&mut line).unwrap();
        let ast = parse(&line);
        execute(&ast).unwrap();
        line.clear();
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate maplit;
use std::collections::BTreeMap;

pub type Message = BTreeMap<String, String>;

#[test]
fn it_works() {
}

pub enum EventType {
    Timer(TimerEvent),
    Message(Message)
}

pub struct TimerEvent;

pub trait Context {
    fn on_event(&mut self, event: &EventType) {
        match *event {
            EventType::Timer(ref event) => self.on_timer(event),
            EventType::Message(ref event) => self.on_message(event),
        }
    }
    fn on_timer(&mut self, event: &TimerEvent) {}
    fn on_message(&mut self, event: &Message) {}
}

pub struct Correlator {
    contexts: BTreeMap<String, Box<Context>>,
}

impl Correlator {
    pub fn new() -> Correlator {
        Correlator {
            contexts: BTreeMap::new(),
        }
    }

    pub fn push_message(&mut self, message: Message) {
        self.push(EventType::Message(message))
    }

    pub fn push_timer(&mut self) {
        self.push(EventType::Timer(TimerEvent))
    }

    fn push(&mut self, event: EventType) {
        match event {
            EventType::Message(ref event) => {
                let uuid = event.get("uuid").unwrap();
                let contexts = self.contexts.get(uuid);
            },
            EventType::Timer(ref event) => {
            }
        }
    }
}

pub struct CorrelationContext {
    messages: Vec<Message>
}

impl Context for CorrelationContext {
    fn on_timer(&mut self, event: &TimerEvent) {
        println!("TimerEvent");
    }
    fn on_message(&mut self, event: &Message) {
        println!("MessageEvent");
    }
}

#[derive(Debug, Copy, Clone)]
struct C<'a>(
    usize,
    &'a str
);

fn main() {
}
<commit_msg>working on dispatching<commit_after>#[macro_use]
extern crate maplit;

use std::collections::BTreeMap;
use std::sync::mpsc;
use std::thread;

const TIMER_STEP: u32 = 100;

pub type Message = BTreeMap<String, String>;

#[derive(Debug)]
pub enum EventType {
    Timer(TimerEvent),
    Message(Message)
}

#[derive(Debug)]
pub struct TimerEvent;

pub struct Timer;

impl Timer {
    pub fn from_chan(ms: u32, tx: mpsc::Sender<EventType>) {
        thread::spawn(move || {
            loop {
                thread::sleep_ms(ms);
                if tx.send(EventType::Timer(TimerEvent)).is_err() {
                    break;
                }
            }
        });
    }
}

pub struct Dispatcher {
    contexts: BTreeMap<String, Box<Vec<Context>>>,
}

impl Dispatcher {
    pub fn new() -> Dispatcher {
        let contexts = btreemap!{
            "1".to_string() => Context::new(),
            "2".to_string() => Context::new(),
            "3".to_string() => Context::new(),
        };
        Dispatcher{
            contexts: BTreeMap::new(),
        }
    }

    fn dispatch(&mut self, event: EventType) {
        match event {
            EventType::Message(event) => {
                if let Some(uuid) = event.get("uuid") {
                    if let Some(mut contexts) = self.contexts.get_mut(uuid) {
                        for i in contexts.iter_mut() {
                            i.on_message(&event);
                        }
                    }
                }
            },
            EventType::Timer(ref event) => {
            }
        }
    }
}

pub struct Correlator {
    tx: mpsc::Sender<EventType>
}

impl Correlator {
    pub fn new() -> Correlator {
        let (tx, rx) = mpsc::channel();

        let timer = Timer::from_chan(TIMER_STEP, tx.clone());

        thread::spawn(move || {
            let mut dispatcher = Dispatcher::new();

            for i in rx.iter() {
                println!("{:?}", i);
                dispatcher.dispatch(i)
            }
        });

        Correlator{
            tx: tx
        }
    }

    pub fn push_message(&mut self, message: Message) {
        self.tx.send(EventType::Message(message));
    }

}

pub struct Context {
    messages: Vec<Message>
}

impl Context {
    fn new() -> Context {
        Context{
            messages: Vec::new()
        }
    }

    fn on_event(&mut self, event: &EventType) {
        match *event {
            EventType::Timer(ref event) => self.on_timer(event),
            EventType::Message(ref event) => self.on_message(event),
        }
    }
    fn on_timer(&mut self, event: &TimerEvent) {
        println!("timer event");
    }
    fn on_message(&mut self, event: &Message) {
        println!("message event");
    }
}

fn main() {
    let mut correlator = Correlator::new();
    let mut msg1 = btreemap!{
        "uuid".to_string() => "1".to_string(),
        "uuid".to_string() => "2".to_string(),
    };
    correlator.push_message(msg1);
}
<|endoftext|>


<commit_before>extern crate num;
extern crate portaudio;
extern crate rtlsdr;

use portaudio as pa;
use rtlsdr::{RTLSDRDevice, RTLSDRError};
use num::{Num, Zero};
use num::complex::Complex;
use std::env;
use std::f32::consts::PI;
use std::error::Error;
use pa::error::Error as PAError;
use std::thread;
use std::sync::mpsc::channel;

// Make sure that the buffer size is radix-2, otherwise the read_sync function
// will fail with an error code of -8. I want the buffer sizes between the SDR
// and the audio sizes to match, but since we get two samples per read the
// buffer size needs to be double.
const SDR_BUF_SIZE: usize = 262144;

// The buffer size for the audio sink.
const AUDIO_BUF_SIZE: usize = 524288;

// Most other sample rates fail, but this one works for my particular device.
// I will investigate exactly what's happening here and generate a list of
// possible sample rates (if there are others besides this one).
const SDR_SAMPLE_RATE: u32 = 2400000;

// Here is the sample rate of the output waveform we'll try to use.
const AUDIO_SAMPLE_RATE: f32 = 48000.0;

// The number of channels being used for audio.
const CHANNELS: i32 = 2;

// We set the gain manually right now since it seems to be a better option
// than using the AGC (the SDR gets blazing hot with the AGC on).
const SDR_GAIN: i32 = 496;

fn main() {
    match run() {
        Ok(()) => (),
        Err(e) => println!("ERROR: {}", e),
    }
}

struct RTLSDR {
    rtlsdr: RTLSDRDevice,
}

unsafe impl Send for RTLSDR {}

fn run() -> Result<(), Box<Error>> {
    let sdr_index: i32 = env::args()
        .nth(1)
        .expect("Please specify the SDR index.")
        .parse::<i32>()?;
    let fm_freq_mhz: f32 = env::args()
        .nth(2)
        .expect("Please specify a center frequency in MHz.")
        .parse::<f32>()?;
    let bandwidth: u32 = env::args()
        .nth(3)
        .expect("Please specify the bandwidth.")
        .parse::<u32>()?;

    // Set up the threading channels for communication between our two threads.
    let (dongle_tx, dongle_rx) = channel();
    let (demod_tx, demod_rx) = channel();

    // This thread only collects data off of the SDR as quickly as possible and
    // sends it out.
    thread::spawn(move || {
        // Initialize the SDR based on the user's input parameters.
        let fm_freq: u32 = (fm_freq_mhz * 1e6) as u32;
        let mut sdr =
            RTLSDR { rtlsdr: init_sdr(sdr_index, fm_freq, bandwidth).unwrap() };

        loop {
            let bytes = sdr.rtlsdr.read_sync(SDR_BUF_SIZE).unwrap();
            let iq_vec = samps_to_cmplx(bytes).unwrap();
            dongle_tx.send(iq_vec).unwrap();
        }
    });

    // This thread does all of the signal processing required to demodulate
    // the signal and get it to a nice audio stream.
    thread::spawn(move || {
        // Decimating down to 100k samples seems to work the best. I don't
        // really quite get why that is, so I'll need to do more research.
        let dec_rate_filt = 6;
        let dec_rate_audio = 4;

        let taps_filt = windowed_sinc(
            bandwidth as f32,
            SDR_SAMPLE_RATE as f32,
            128,
            &hamming,
        );
        let taps_audio = windowed_sinc(
            bandwidth as f32 / dec_rate_filt as f32,
            SDR_SAMPLE_RATE as f32 / dec_rate_filt as f32,
            128,
            &hamming,
        );

        let mut prev = Complex::zero();
        loop {
            // First, low_pass and decimate the raw IQ signal.
            let mut iq_vec = dongle_rx.recv().unwrap();
            iq_vec = filter(&iq_vec, &taps_filt);
            iq_vec = decimate(iq_vec, dec_rate_filt);

            // Next, demodulate the signal and filter the signal again. The
            // second filter seems to help with the noise after demodulation.
            let res = demod_fm(iq_vec, prev);
            let mut demod_iq = filter_real(&res.0, &taps_audio);
            demod_iq = decimate(demod_iq, dec_rate_audio);
            prev = res.1;
            demod_tx.send(demod_iq).unwrap();
        }
    });

    // Initialize the PortAudio class. We use a blocking stream since we're
    // doing processing on the signal and can't keep up with non-blocking
    // timing requirements.
    let audio = try!(pa::PortAudio::new());
    let settings = try!(audio.default_output_stream_settings(
        CHANNELS,
        AUDIO_SAMPLE_RATE as f64,
        AUDIO_BUF_SIZE as u32,
    ));
    let mut stream = try!(audio.open_blocking_stream(settings));
    try!(stream.start());

    loop {
        let demod_iq = demod_rx.recv().unwrap();
        let buffer_frames = (demod_iq.len() / CHANNELS as usize) as u32;
        let mut out_frames = 0;

        while out_frames < buffer_frames {
            out_frames = match stream.write_available() {
                Ok(available) => {
                    match available {
                        pa::StreamAvailable::Frames(frames) => frames as u32,
                        pa::StreamAvailable::InputOverflowed => {
                            return Err(Box::new(PAError::InputOverflowed))
                        }
                        pa::StreamAvailable::OutputUnderflowed => {
                            return Err(Box::new(PAError::OutputUnderflowed))
                        }
                    }
                }
                Err(e) => return Err(Box::new(e)),
            };
        }

        let n_write_samples = buffer_frames as usize * CHANNELS as usize;

        stream.write(
            buffer_frames,
            |output| for ix in 0..n_write_samples {
                output[ix] = demod_iq[ix];
            },
        )?;
    }
}

fn init_sdr(
    sdr_index: i32,
    fm_freq: u32,
    bandwidth: u32,
) -> Result<RTLSDRDevice, RTLSDRError> {
    let mut sdr = try!(rtlsdr::open(sdr_index));
    try!(sdr.set_center_freq(fm_freq));
    try!(sdr.set_sample_rate(SDR_SAMPLE_RATE));
    try!(sdr.set_tuner_bandwidth(bandwidth));
    try!(sdr.set_tuner_gain(SDR_GAIN));
    try!(sdr.set_agc_mode(false));
    try!(sdr.reset_buffer());
    Ok(sdr)
}

fn decimate<T: Copy>(signal: Vec<T>, dec_rate: usize) -> Vec<T> {
    let mut ix = 0;
    let new_size = (signal.len() / dec_rate + 1) as usize;
    let mut signal_dec = Vec::<T>::with_capacity(new_size);
    while ix < signal.len() {
        signal_dec.push(signal[ix]);
        ix += dec_rate;
    }
    signal_dec
}

fn samps_to_cmplx(bytes: Vec<u8>) -> Option<Vec<Complex<f32>>> {
    // First, check that we've been given an even number of bytes. Not sure
    // what to do if we don't get I and Q.
    let bytes_len = bytes.len();
    if bytes_len % 2 != 0 {
        println!("Received an odd number of samples.");
        return None;

    }

    // Write the values to the complex value and normalize from [0, 255] to
    // [-1, 1].
    let mut iq_vec: Vec<Complex<f32>> = Vec::with_capacity(bytes_len / 2);
    for iq in bytes.chunks(2) {
        let iq_cmplx = Complex::new(
            (iq[0] as f32 - 127.0) / 127.0,
            (iq[1] as f32 - 127.0) / 127.0,
        );
        iq_vec.push(iq_cmplx);
    }
    Some(iq_vec)
}

fn demod_fm(
    iq: Vec<Complex<f32>>,
    prev: Complex<f32>,
) -> (Vec<f32>, Complex<f32>) {

    let mut p = prev.clone();
    let mut demod_queue: Vec<f32> = Vec::with_capacity(iq.len());

    let gain = SDR_SAMPLE_RATE as f32 / (2.0 * PI * 75e3);

    for samp in iq.iter() {
        let conj = p.conj() * samp;
        demod_queue.push(conj.arg() * gain);
        p = *samp;
    }
    (demod_queue, p)
}

///
/// Filters a Complex vector.
///
fn filter<T: Copy + Num + Zero>(
    samples: &Vec<Complex<T>>,
    taps: &Vec<T>,
) -> Vec<Complex<T>> {
    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<Complex<T>> =
        Vec::with_capacity(samples.len() - taps.len() + 1);

    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(Complex::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

///
/// Filter a real vector.
///
fn filter_real<T: Copy + Num + Zero>(
    samples: &Vec<T>,
    taps: &Vec<T>,
) -> Vec<T> {
    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<T> =
        Vec::with_capacity(samples.len() - taps.len() + 1);
    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(T::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

///
/// Generates taps for a Hamming window.
///
fn hamming(ntaps: usize) -> Vec<f32> {
    let m: f32 = ntaps as f32 - 1.0;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    for ix in 0..ntaps {
        taps.push(0.54 - 0.46 * (2.0 * PI * ix as f32 / m).cos());
    }
    taps
}

///
/// Generates filter taps for a sinc filter with a Hamming window.
///
fn windowed_sinc(
    cutoff_freq: f32,
    sample_rate: f32,
    ntaps: usize,
    window: &Fn(usize) -> Vec<f32>,
) -> Vec<f32> {
    // Convert the frequency to radians and make it a ratio of the sample rate.
    let wc: f32 = 2.0 * PI * cutoff_freq / sample_rate;

    let win_taps: Vec<f32> = window(ntaps);
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);

    let ntaps_i: i32 = ntaps as i32;
    let m: i32 = (ntaps_i - 1) / 2;

    for ix in -m..m + 1 {
        let ix_f: f32 = ix as f32;

        // The windowed sinc function is undefined at zero, so set it to
        // something sensible here.
        if ix == 0 {
            let hi = wc / PI * win_taps[(ix + m) as usize];
            taps.push(hi);
        } else {
            let hi = (ix_f * wc).sin() / (ix_f * PI) *
                win_taps[(ix + m) as usize];
            taps.push(hi);
        }
    }
    taps
}
<commit_msg>Adding documentation for the functions<commit_after>extern crate num;
extern crate portaudio;
extern crate rtlsdr;

use portaudio as pa;
use rtlsdr::{RTLSDRDevice, RTLSDRError};
use num::{Num, Zero};
use num::complex::Complex;
use std::env;
use std::f32::consts::PI;
use std::error::Error;
use pa::error::Error as PAError;
use std::thread;
use std::sync::mpsc::channel;

// Make sure that the buffer size is radix-2, otherwise the read_sync function
// will fail with an error code of -8. I want the buffer sizes between the SDR
// and the audio sizes to match, but since we get two samples per read the
// buffer size needs to be double.
const SDR_BUF_SIZE: usize = 262144;

// The buffer size for the audio sink.
const AUDIO_BUF_SIZE: usize = 524288;

// Most other sample rates fail, but this one works for my particular device.
// I will investigate exactly what's happening here and generate a list of
// possible sample rates (if there are others besides this one).
const SDR_SAMPLE_RATE: u32 = 2400000;

// Here is the sample rate of the output waveform we'll try to use.
const AUDIO_SAMPLE_RATE: f32 = 48000.0;

// The number of channels being used for audio.
const CHANNELS: i32 = 2;

// We set the gain manually right now since it seems to be a better option
// than using the AGC (the SDR gets blazing hot with the AGC on).
const SDR_GAIN: i32 = 496;

fn main() {
    match run() {
        Ok(()) => (),
        Err(e) => println!("ERROR: {}", e),
    }
}

struct RTLSDR {
    rtlsdr: RTLSDRDevice,
}

unsafe impl Send for RTLSDR {}

fn run() -> Result<(), Box<Error>> {
    let sdr_index: i32 = env::args()
        .nth(1)
        .expect("Please specify the SDR index.")
        .parse::<i32>()?;
    let fm_freq_mhz: f32 = env::args()
        .nth(2)
        .expect("Please specify a center frequency in MHz.")
        .parse::<f32>()?;
    let bandwidth: u32 = env::args()
        .nth(3)
        .expect("Please specify the bandwidth.")
        .parse::<u32>()?;

    // Set up the threading channels for communication between our two threads.
    let (dongle_tx, dongle_rx) = channel();
    let (demod_tx, demod_rx) = channel();

    // This thread only collects data off of the SDR as quickly as possible and
    // sends it out.
    thread::spawn(move || {
        // Initialize the SDR based on the user's input parameters.
        let fm_freq: u32 = (fm_freq_mhz * 1e6) as u32;
        let mut sdr =
            RTLSDR { rtlsdr: init_sdr(sdr_index, fm_freq, bandwidth).unwrap() };

        loop {
            let bytes = sdr.rtlsdr.read_sync(SDR_BUF_SIZE).unwrap();
            let iq_vec = samps_to_cmplx(bytes).unwrap();
            dongle_tx.send(iq_vec).unwrap();
        }
    });

    // This thread does all of the signal processing required to demodulate
    // the signal and get it to a nice audio stream.
    thread::spawn(move || {
        // Decimating down to 100k samples seems to work the best. I don't
        // really quite get why that is, so I'll need to do more research.
        let dec_rate_filt = 6;
        let dec_rate_audio = 4;

        let taps_filt = windowed_sinc(
            bandwidth as f32,
            SDR_SAMPLE_RATE as f32,
            128,
            &hamming,
        );
        let taps_audio = windowed_sinc(
            bandwidth as f32 / dec_rate_filt as f32,
            SDR_SAMPLE_RATE as f32 / dec_rate_filt as f32,
            128,
            &hamming,
        );

        let mut prev = Complex::zero();
        loop {
            // First, low_pass and decimate the raw IQ signal.
            let mut iq_vec = dongle_rx.recv().unwrap();
            iq_vec = filter(&iq_vec, &taps_filt);
            iq_vec = decimate(iq_vec, dec_rate_filt);

            // Next, demodulate the signal and filter the signal again. The
            // second filter seems to help with the noise after demodulation.
            let res = demod_fm(iq_vec, prev);
            let mut demod_iq = filter_real(&res.0, &taps_audio);
            demod_iq = decimate(demod_iq, dec_rate_audio);
            prev = res.1;
            demod_tx.send(demod_iq).unwrap();
        }
    });

    // Initialize the PortAudio class. We use a blocking stream since we're
    // doing processing on the signal and can't keep up with non-blocking
    // timing requirements.
    let audio = try!(pa::PortAudio::new());
    let settings = try!(audio.default_output_stream_settings(
        CHANNELS,
        AUDIO_SAMPLE_RATE as f64,
        AUDIO_BUF_SIZE as u32,
    ));
    let mut stream = try!(audio.open_blocking_stream(settings));
    try!(stream.start());

    loop {
        let demod_iq = demod_rx.recv().unwrap();
        let buffer_frames = (demod_iq.len() / CHANNELS as usize) as u32;
        let mut out_frames = 0;

        while out_frames < buffer_frames {
            out_frames = match stream.write_available() {
                Ok(available) => {
                    match available {
                        pa::StreamAvailable::Frames(frames) => frames as u32,
                        pa::StreamAvailable::InputOverflowed => {
                            return Err(Box::new(PAError::InputOverflowed))
                        }
                        pa::StreamAvailable::OutputUnderflowed => {
                            return Err(Box::new(PAError::OutputUnderflowed))
                        }
                    }
                }
                Err(e) => return Err(Box::new(e)),
            };
        }

        let n_write_samples = buffer_frames as usize * CHANNELS as usize;

        stream.write(
            buffer_frames,
            |output| for ix in 0..n_write_samples {
                output[ix] = demod_iq[ix];
            },
        )?;
    }
}

fn init_sdr(
    sdr_index: i32,
    fm_freq: u32,
    bandwidth: u32,
) -> Result<RTLSDRDevice, RTLSDRError> {
    let mut sdr = try!(rtlsdr::open(sdr_index));
    try!(sdr.set_center_freq(fm_freq));
    try!(sdr.set_sample_rate(SDR_SAMPLE_RATE));
    try!(sdr.set_tuner_bandwidth(bandwidth));
    try!(sdr.set_tuner_gain(SDR_GAIN));
    try!(sdr.set_agc_mode(false));
    try!(sdr.reset_buffer());
    Ok(sdr)
}

/// Decimates a signal by an integer factor.
///
/// # Arguments
///
/// * `signal` - The signal to decimate
/// * `dec_rate` - The decimation factor
///
fn decimate<T: Copy>(signal: Vec<T>, dec_rate: usize) -> Vec<T> {
    let mut ix = 0;
    let new_size = (signal.len() / dec_rate + 1) as usize;
    let mut signal_dec = Vec::<T>::with_capacity(new_size);
    while ix < signal.len() {
        signal_dec.push(signal[ix]);
        ix += dec_rate;
    }
    signal_dec
}

/// Converts samples from the SDR into complex IQ pairs.
///
/// # Arguments
///
/// * `bytes` - The unsigned bytes from the SDR.
///
fn samps_to_cmplx(bytes: Vec<u8>) -> Option<Vec<Complex<f32>>> {
    // First, check that we've been given an even number of bytes. Not sure
    // what to do if we don't get I and Q.
    let bytes_len = bytes.len();
    if bytes_len % 2 != 0 {
        println!("Received an odd number of samples.");
        return None;

    }

    // Write the values to the complex value and normalize from [0, 255] to
    // [-1, 1].
    let mut iq_vec: Vec<Complex<f32>> = Vec::with_capacity(bytes_len / 2);
    for iq in bytes.chunks(2) {
        let iq_cmplx = Complex::new(
            (iq[0] as f32 - 127.0) / 127.0,
            (iq[1] as f32 - 127.0) / 127.0,
        );
        iq_vec.push(iq_cmplx);
    }
    Some(iq_vec)
}

/// Performs FM demodulation on a complex signal.
///
/// # Arguments
///
/// * `iq` - The IQ samples to demodulate
/// * `prev` - The previous sample from the previous demodulation.
///
fn demod_fm(
    iq: Vec<Complex<f32>>,
    prev: Complex<f32>,
) -> (Vec<f32>, Complex<f32>) {

    let mut p = prev.clone();
    let mut demod_queue: Vec<f32> = Vec::with_capacity(iq.len());

    let gain = SDR_SAMPLE_RATE as f32 / (2.0 * PI * 75e3);

    for samp in iq.iter() {
        let conj = p.conj() * samp;
        demod_queue.push(conj.arg() * gain);
        p = *samp;
    }
    (demod_queue, p)
}

/// Filters a Complex vector and returns a new vector.
///
/// # Arguments
///
/// * `samples` - The complex samples to filter
/// * `taps` - The taps of the filter
///
fn filter<T: Copy + Num + Zero>(
    samples: &Vec<Complex<T>>,
    taps: &Vec<T>,
) -> Vec<Complex<T>> {
    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<Complex<T>> =
        Vec::with_capacity(samples.len() - taps.len() + 1);

    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(Complex::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

/// Filters a real vector and returns a new vector.
///
/// # Arguments
///
/// * `samples` - The real samples to filter
/// * `taps` - The taps of the filter
///
fn filter_real<T: Copy + Num + Zero>(
    samples: &Vec<T>,
    taps: &Vec<T>,
) -> Vec<T> {
    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<T> =
        Vec::with_capacity(samples.len() - taps.len() + 1);
    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(T::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

/// Generates a vector containing the taps for a Hamming window.
///
/// # Arguments
///
/// * `ntaps` - The number of taps to generate for the filter
///
fn hamming(ntaps: usize) -> Vec<f32> {
    let m: f32 = ntaps as f32 - 1.0;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    for ix in 0..ntaps {
        taps.push(0.54 - 0.46 * (2.0 * PI * ix as f32 / m).cos());
    }
    taps
}

/// Generates filter taps for a sinc filter with a windowing function.
///
/// # Arguments
///
/// * `cutoff_freq` - The cutoff frequency in Hertz
/// * `sample_rate` - The sample frequency in Hertz
/// * `ntaps` - The number of taps to generate for the window
/// * `window` - THe windowing function used to generate the taps for the window
///
fn windowed_sinc(
    cutoff_freq: f32,
    sample_rate: f32,
    ntaps: usize,
    window: &Fn(usize) -> Vec<f32>,
) -> Vec<f32> {
    // Convert the frequency to radians and make it a ratio of the sample rate.
    let wc: f32 = 2.0 * PI * cutoff_freq / sample_rate;

    let win_taps: Vec<f32> = window(ntaps);
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);

    let ntaps_i: i32 = ntaps as i32;
    let m: i32 = (ntaps_i - 1) / 2;

    for ix in -m..m + 1 {
        let ix_f: f32 = ix as f32;

        // The windowed sinc function is undefined at zero, so set it to
        // something sensible here.
        if ix == 0 {
            let hi = wc / PI * win_taps[(ix + m) as usize];
            taps.push(hi);
        } else {
            let hi = (ix_f * wc).sin() / (ix_f * PI) *
                win_taps[(ix + m) as usize];
            taps.push(hi);
        }
    }
    taps
}
<|endoftext|>


<commit_before>#[macro_use] extern crate log;

use std::num::{Int, FromPrimitive};
use std::os;
use std::io::File;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::iter::{range_step, count};

// Index source
struct InputSource {
    haystack: Vec<char>,
    indexed_haystack: HashMap<char, Vec<usize>>,
}

fn index_chars(input: &Vec<char>) -> HashMap<char, Vec<usize>> {
    let mut indexed_haystack = HashMap::new();
    for (idx, &c) in input.iter().enumerate() {
        match indexed_haystack.entry(c) {
            Vacant(entry) => { entry.insert(vec![idx]); },
            Occupied(mut entry) => { (*entry.get_mut()).push(idx); }
        }
    }

    indexed_haystack
}

impl InputSource {
    fn new(haystack: Vec<char>) -> InputSource {
        let indexed_haystack = index_chars(&haystack);

        InputSource {
            haystack: haystack,
            indexed_haystack: indexed_haystack,
        }
    }

    fn search_for<'a>(&'a self, needle: &'a Vec<char>) -> Option<EDS> {
        EDS::new(self, needle)
    }
}

// This is a struct for doing the searching
struct EDS<'a, 'b> {
    source: &'a InputSource,

    // String to search for
    needle: &'b Vec<char>,

    first_poses: Vec<usize>,
    second_poses: Vec<usize>,

    // keep track of state between runs
    first_poses_idx: usize,
    second_poses_idx: usize,
}

impl<'a, 'b> Iterator for EDS<'a, 'b> {
    // (start, offset)
    type Item = (usize, i64);

    // This actually does the searching
    fn next(&mut self) -> Option<(usize, i64)> {
        debug!("Start of next call");
        let len_first_poses = self.first_poses.len();
        let len_second_poses = self.second_poses.len();

        if self.first_poses_idx == len_first_poses {
            debug!("Reached end, finishing");
            // reached the end
            return None;
        }

        let len_needle = self.needle.len();
        let len_haystack = self.source.haystack.len();
        let mut have_done_one_loop = false;
        let first_run = (self.first_poses_idx == 0 && self.second_poses_idx == 0);

        loop {
            debug!("Start of loop");
            // Starts off at 0/0, and we don't want to increment it the first time
            if ! (self.first_poses_idx == 0 && self.second_poses_idx == 0 && !have_done_one_loop) {
                debug!("Incrementing counters");
                if self.second_poses_idx == len_second_poses - 1 {
                    self.second_poses_idx = 0;
                    self.first_poses_idx += 1;
                } else{
                    self.second_poses_idx += 1;
                }
            }
            have_done_one_loop = true;
            if self.first_poses_idx == len_first_poses {
                debug!("Reached end, finishing");
                // reached the end
                return None;
            }

            debug!("first_poses_idx {} second_poses_idx {}", self.first_poses_idx, self.second_poses_idx);
            let first_pos = self.first_poses[self.first_poses_idx];
            let second_pos = self.second_poses[self.second_poses_idx];
            debug!("first_pos {} second_pos {}", first_pos, second_pos);

            let step: i64 = (second_pos as i64) - (first_pos as i64);
            if step == 1 {
                continue;
            }
            let positions: Vec<i64> = std::iter::count(first_pos as i64, step as i64).take(len_needle).collect();
            //let positions: Vec<i64> = range_step(first_pos as i64, step*len_needle, step).collect();
            debug!("Start {} step {}", first_pos, step);
            if positions.iter().any(|&x| { x<0 }) {
                // TODO there's probably a better maths way to do this
                continue;
            }
            let positions: Vec<usize> = positions.iter().map(|&x| { FromPrimitive::from_i64(x).unwrap() }).collect();
            debug!("positions {:?}", positions);
            if positions.len() == 0 {
                // WTF
                continue;
            }

            if positions[positions.len()-1] > len_haystack - 1 {
                debug!("Past end");
                continue;
            }
            if positions.iter().map(|&c| { &self.source.haystack[c] }).zip(self.needle.iter()).all(|(&a, &b)| { a == b }) {
                //println!("Found starting at {} with step of {}", first_pos, step);
                return Some((first_pos, step));
            }
        }
        None
    }
}

impl<'a, 'b> EDS<'a, 'b> {
    fn new(source: &'a InputSource, needle: &'b Vec<char>) -> Option<EDS<'a, 'b>> {
        let first_poses;
        match source.indexed_haystack.get(&needle[0]) {
            None => { return None ; }
            Some(ref entries) => {
                first_poses = (**entries).clone();
            }
        }

        let second_poses;
        match source.indexed_haystack.get(&needle[1]) {
            None => { return None ; }
            Some(ref entries) => {
                second_poses = (**entries).clone();
            }
        }

        let result = EDS {
            needle: needle, source: source,
            first_poses: first_poses, second_poses: second_poses,
            first_poses_idx: 0, second_poses_idx: 0,
        };

        return Some(result);

    }
}

fn print_results(source: &InputSource, start: usize, step: i64, len: usize) {
    let total_rows = (len + 2) as i64;
    let width: usize = 31; // 15 + 1 + 15
    let start_i = start as i64;

    for row_num in range(0, total_rows) {
        println!("{}", count((row_num-1)*step + start_i - 15, 1).take(width).map(|i| { if i < 0 { ' ' } else { source.haystack[i as usize] } }).collect::<String>());
    }

}

fn only_alphanumeric(input: String) -> Vec<char> {
    input.chars().filter(|c| { c.is_alphabetic() }).map(|c| { c.to_lowercase() }).collect()
}

fn main() {
    let file_to_search = &os::args()[1];
    println!("Reading in {}", file_to_search);
    let haystack: Vec<char> = only_alphanumeric(File::open(&Path::new(file_to_search)).read_to_string().unwrap());
    let source = InputSource::new(haystack);

    let needle = (&os::args()[2]).to_string();
    println!("Looking for {}", needle);
    let needle = only_alphanumeric(needle);
    let len_needle = needle.len();

    let needle2 = (&os::args()[3]).to_string();
    println!("Looking also for {}", needle2);
    let needle2 = only_alphanumeric(needle2);
    let len_needle2 = needle2.len();

    match source.search_for(&needle) {
        None => {
            println!("Cannot look for this string");
        }
        Some(eds_searcher) => {
            for (start, step) in eds_searcher.take(10) {
                println!("Found starting at {} with step of {}", start, step);
                print_results(&source, start, step, len_needle);
                // now try to find the second needle2
                match source.search_for(&needle2) {
                    None => {
                        println!("Cannot look for {:?}", needle2);
                    }
                    Some(needle2_searcher) => {
                        for (start2, step2) in needle2_searcher.take(1) {
                            println!("Found {:?} starting at {} with step of {}", needle2, start2, step2);

                        }
                    }
                }
            }
        }
    }

}
<commit_msg>better printin<commit_after>#[macro_use] extern crate log;

use std::num::{Int, FromPrimitive};
use std::os;
use std::io::File;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::iter::{range_step, count};

fn vec_to_string(input: &Vec<char>) -> String {
    input.iter().map(|&c| { c }).collect()
}

// Index source
struct InputSource {
    haystack: Vec<char>,
    indexed_haystack: HashMap<char, Vec<usize>>,
}

fn index_chars(input: &Vec<char>) -> HashMap<char, Vec<usize>> {
    let mut indexed_haystack = HashMap::new();
    for (idx, &c) in input.iter().enumerate() {
        match indexed_haystack.entry(c) {
            Vacant(entry) => { entry.insert(vec![idx]); },
            Occupied(mut entry) => { (*entry.get_mut()).push(idx); }
        }
    }

    indexed_haystack
}

impl InputSource {
    fn new(haystack: Vec<char>) -> InputSource {
        let indexed_haystack = index_chars(&haystack);

        InputSource {
            haystack: haystack,
            indexed_haystack: indexed_haystack,
        }
    }

    fn search_for<'a>(&'a self, needle: &'a Vec<char>) -> Option<EDS> {
        EDS::new(self, needle)
    }
}

// This is a struct for doing the searching
struct EDS<'a, 'b> {
    source: &'a InputSource,

    // String to search for
    needle: &'b Vec<char>,

    first_poses: Vec<usize>,
    second_poses: Vec<usize>,

    // keep track of state between runs
    first_poses_idx: usize,
    second_poses_idx: usize,
}

impl<'a, 'b> Iterator for EDS<'a, 'b> {
    // (start, offset)
    type Item = (usize, i64);

    // This actually does the searching
    fn next(&mut self) -> Option<(usize, i64)> {
        debug!("Start of next call");
        let len_first_poses = self.first_poses.len();
        let len_second_poses = self.second_poses.len();

        if self.first_poses_idx == len_first_poses {
            debug!("Reached end, finishing");
            // reached the end
            return None;
        }

        let len_needle = self.needle.len();
        let len_haystack = self.source.haystack.len();
        let mut have_done_one_loop = false;
        let first_run = (self.first_poses_idx == 0 && self.second_poses_idx == 0);

        loop {
            debug!("Start of loop");
            // Starts off at 0/0, and we don't want to increment it the first time
            if ! (self.first_poses_idx == 0 && self.second_poses_idx == 0 && !have_done_one_loop) {
                debug!("Incrementing counters");
                if self.second_poses_idx == len_second_poses - 1 {
                    self.second_poses_idx = 0;
                    self.first_poses_idx += 1;
                } else{
                    self.second_poses_idx += 1;
                }
            }
            have_done_one_loop = true;
            if self.first_poses_idx == len_first_poses {
                debug!("Reached end, finishing");
                // reached the end
                return None;
            }

            debug!("first_poses_idx {} second_poses_idx {}", self.first_poses_idx, self.second_poses_idx);
            let first_pos = self.first_poses[self.first_poses_idx];
            let second_pos = self.second_poses[self.second_poses_idx];
            debug!("first_pos {} second_pos {}", first_pos, second_pos);

            let step: i64 = (second_pos as i64) - (first_pos as i64);
            if step == 1 {
                continue;
            }
            let positions: Vec<i64> = std::iter::count(first_pos as i64, step as i64).take(len_needle).collect();
            //let positions: Vec<i64> = range_step(first_pos as i64, step*len_needle, step).collect();
            debug!("Start {} step {}", first_pos, step);
            if positions.iter().any(|&x| { x<0 }) {
                // TODO there's probably a better maths way to do this
                continue;
            }
            let positions: Vec<usize> = positions.iter().map(|&x| { FromPrimitive::from_i64(x).unwrap() }).collect();
            debug!("positions {:?}", positions);
            if positions.len() == 0 {
                // WTF
                continue;
            }

            if positions[positions.len()-1] > len_haystack - 1 {
                debug!("Past end");
                continue;
            }
            if positions.iter().map(|&c| { &self.source.haystack[c] }).zip(self.needle.iter()).all(|(&a, &b)| { a == b }) {
                //println!("Found starting at {} with step of {}", first_pos, step);
                return Some((first_pos, step));
            }
        }
        None
    }
}

impl<'a, 'b> EDS<'a, 'b> {
    fn new(source: &'a InputSource, needle: &'b Vec<char>) -> Option<EDS<'a, 'b>> {
        let first_poses;
        match source.indexed_haystack.get(&needle[0]) {
            None => { return None ; }
            Some(ref entries) => {
                first_poses = (**entries).clone();
            }
        }

        let second_poses;
        match source.indexed_haystack.get(&needle[1]) {
            None => { return None ; }
            Some(ref entries) => {
                second_poses = (**entries).clone();
            }
        }

        let result = EDS {
            needle: needle, source: source,
            first_poses: first_poses, second_poses: second_poses,
            first_poses_idx: 0, second_poses_idx: 0,
        };

        return Some(result);

    }
}

fn print_results(source: &InputSource, start: usize, step: i64, len: usize) {
    let total_rows = (len + 2) as i64;
    let width: usize = 31; // 15 + 1 + 15
    let start_i = start as i64;

    for row_num in range(0, total_rows) {
        println!("{}", count((row_num-1)*step + start_i - 15, 1).take(width).map(|i| { if i < 0 { ' ' } else { source.haystack[i as usize] } }).collect::<String>());
    }

}

fn only_alphanumeric(input: String) -> Vec<char> {
    input.chars().filter(|c| { c.is_alphabetic() }).map(|c| { c.to_lowercase() }).collect()
}

fn main() {
    let file_to_search = &os::args()[1];
    println!("Reading in {}", file_to_search);
    let haystack: Vec<char> = only_alphanumeric(File::open(&Path::new(file_to_search)).read_to_string().unwrap());
    let source = InputSource::new(haystack);

    let needle = (&os::args()[2]).to_string();
    println!("Looking for {}", needle);
    let needle = only_alphanumeric(needle);
    let len_needle = needle.len();

    let needle2 = (&os::args()[3]).to_string();
    println!("Looking also for {}", needle2);
    let needle2 = only_alphanumeric(needle2);
    let len_needle2 = needle2.len();

    match source.search_for(&needle) {
        None => {
            println!("Cannot look for this string");
        }
        Some(eds_searcher) => {
            for (start, step) in eds_searcher.take(10) {
                println!("Found starting at {} with step of {}", start, step);
                print_results(&source, start, step, len_needle);
                // now try to find the second needle2
                match source.search_for(&needle2) {
                    None => {
                        println!("Cannot look for {:?}", vec_to_string(&needle2));
                    }
                    Some(needle2_searcher) => {
                        for (start2, step2) in needle2_searcher.take(1) {
                            println!("Found {:?} starting at {} with step of {}", vec_to_string(&needle2), start2, step2);

                        }
                    }
                }
            }
        }
    }

}
<|endoftext|>


<commit_before>#![allow(unstable, dead_code)]

extern crate libc;

mod args;
mod ansi;
mod matching;
mod screen;

use std::os;
use std::io;
use std::cmp::min;
use screen::Screen;
use screen::Key::*;
use self::SearchState::*;

fn main() {
  let args = match args::parse_args() {
    Some(args) => args,
    None => {
      os::set_exit_status(1);
      return;
    },
  };

  if args.help { return; }

  let choices = read_choices();
  let initial_search = args.initial_search.clone();
  if args.use_first {
    let matches = matching::compute_matches(&choices, initial_search.as_slice());
    println!("{}", matches[0]);
    return;
  } else {
    event_loop(choices, initial_search.as_slice());
  }
}

fn event_loop(choices: Vec<String>, initial_search: &str) {
  let mut search = Search::new(&choices, initial_search.to_string());
  let mut screen = Screen::open_screen();

  loop {
    search.recompute_matches();

    match search.state {
      InProgress => draw_screen(&mut screen, &search),
      _ => break,
    }

    let chars = screen.get_buffered_keys();
    for char in chars.iter() {
      match *char {
        Char(x) => search.append(x),
        Backspace => search.backspace(),
        Control('h') => search.backspace(),
        Control('u') => search.clear_query(),
        Control('c') => search.cancel(),
        Control('g') => search.cancel(),
        Control('n') => search.down(screen.visible_choices),
        Control('p') => search.up(),
        Enter => search.done(),
        _ => {}
      }
    }
  }

  screen.move_cursor_to_bottom();
  println!("{}", search.get_selection());
}

struct Search<'a> {
  choices: &'a Vec<String>,
  query: String,
  matches: Vec<&'a String>,
  stale: bool,
  index: usize,
  state: SearchState,
}

#[derive(PartialEq, Eq)]
enum SearchState {
  InProgress,
  Done,
  Canceled,
}

impl<'a> Search<'a> {
  fn new(choices: &'a Vec<String>, initial_search: String) -> Search<'a> {
    Search {
      choices: choices,
      query: initial_search,
      matches: Vec::new(),
      stale: true,
      index: 0,
      state: InProgress,
    }
  }

  fn up(&mut self) {
    self.index = if self.index == 0 { 0 } else { self.index - 1 };
  }

  fn down(&mut self, visible_choices: u16) {
    let limit = min(visible_choices as usize - 1, self.matches.len() - 1);
    self.index = min(self.index + 1, limit);
  }

  fn backspace(&mut self) {
    self.query.pop();
    self.stale = true;
    self.index = 0;
  }

  fn append(&mut self, c: char) {
    self.query.push(c);
    self.stale = true;
  }

  fn clear_query(&mut self) {
    self.query.clear();
    self.stale = true;
  }

  fn recompute_matches(&mut self) {
    if self.stale {
      self.matches = matching::compute_matches(self.choices, self.query.as_slice());
      self.stale = false;
    }
  }

  fn get_selection(&mut self) -> &str {
    if self.state == Canceled {
      ""
    } else {
      self.recompute_matches();
      self.matches[self.index].as_slice()
    }
  }

  fn cancel(&mut self) {
    self.state = Canceled
  }

  fn done(&mut self) {
    self.state = Done
  }
}

fn draw_screen(screen: &mut Screen, search: &Search) {
  screen.hide_cursor();
  screen.blank_screen();
  screen.write(format!("> {} ({} choices)\n", search.query, search.matches.len()).as_slice());

  print_matches(screen, &search.matches, search.index);

  let start = screen.start_line;
  screen.move_cursor(start, 2 + search.query.len() as u16);
  screen.show_cursor();
}

fn print_matches(screen: &mut Screen, matches: &Vec<&String>, index: usize) {
  let mut i = 1;
  for choice in matches.iter() {
    if i == index + 1 {
      screen.write_inverted(choice.as_slice());
    } else {
      screen.write(choice.as_slice());
    }
    if i >= screen.visible_choices as usize {
      return;
    } else {
      screen.write("\n");
    }
    i += 1;
  }
}

fn read_choices() -> Vec<String> {
  let mut stdin = io::stdio::stdin();
  let mut lines = Vec::new();

  while let Ok(mut s) = stdin.read_line() {
    trim(&mut s);
    lines.push(s);
  }

  lines
}

fn trim(s: &mut String) {
  while let Some(x) = s.pop() {
    if x != '\n' {
      s.push(x);
      return;
    }
  }
}
<commit_msg>Add 'delete_word' and tests<commit_after>#![allow(unstable, dead_code)]

extern crate libc;

mod args;
mod ansi;
mod matching;
mod screen;

use std::os;
use std::io;
use std::cmp::min;
use screen::Screen;
use screen::Key::*;
use self::SearchState::*;

fn main() {
  let args = match args::parse_args() {
    Some(args) => args,
    None => {
      os::set_exit_status(1);
      return;
    },
  };

  if args.help { return; }

  let choices = read_choices();
  let initial_search = args.initial_search.clone();
  if args.use_first {
    let matches = matching::compute_matches(&choices, initial_search.as_slice());
    println!("{}", matches[0]);
    return;
  } else {
    event_loop(choices, initial_search.as_slice());
  }
}

fn event_loop(choices: Vec<String>, initial_search: &str) {
  let mut search = Search::new(&choices, initial_search.to_string());
  let mut screen = Screen::open_screen();

  loop {
    search.recompute_matches();

    match search.state {
      InProgress => draw_screen(&mut screen, &search),
      _ => break,
    }

    let chars = screen.get_buffered_keys();
    for char in chars.iter() {
      match *char {
        Char(x) => search.append(x),
        Backspace => search.backspace(),
        Control('h') => search.backspace(),
        Control('w') => search.delete_word(),
        Control('u') => search.clear_query(),
        Control('c') => search.cancel(),
        Control('g') => search.cancel(),
        Control('n') => search.down(screen.visible_choices),
        Control('p') => search.up(),
        Enter => search.done(),
        _ => {}
      }
    }
  }

  screen.move_cursor_to_bottom();
  println!("{}", search.get_selection());
}

struct Search<'a> {
  choices: &'a Vec<String>,
  query: String,
  matches: Vec<&'a String>,
  stale: bool,
  index: usize,
  state: SearchState,
}

#[derive(PartialEq, Eq)]
enum SearchState {
  InProgress,
  Done,
  Canceled,
}

impl<'a> Search<'a> {
  fn new(choices: &'a Vec<String>, initial_search: String) -> Search<'a> {
    Search {
      choices: choices,
      query: initial_search,
      matches: Vec::new(),
      stale: true,
      index: 0,
      state: InProgress,
    }
  }

  fn up(&mut self) {
    self.index = if self.index == 0 { 0 } else { self.index - 1 };
  }

  fn down(&mut self, visible_choices: u16) {
    let limit = min(visible_choices as usize - 1, self.matches.len() - 1);
    self.index = min(self.index + 1, limit);
  }

  fn backspace(&mut self) {
    self.query.pop();
    self.stale = true;
    self.index = 0;
  }

  fn delete_word(&mut self) {
    self.stale = true;
    delete_last_word(&mut self.query);
  }

  fn append(&mut self, c: char) {
    self.query.push(c);
    self.stale = true;
  }

  fn clear_query(&mut self) {
    self.query.clear();
    self.stale = true;
  }

  fn recompute_matches(&mut self) {
    if self.stale {
      self.matches = matching::compute_matches(self.choices, self.query.as_slice());
      self.stale = false;
    }
  }

  fn get_selection(&mut self) -> &str {
    if self.state == Canceled {
      ""
    } else {
      self.recompute_matches();
      self.matches[self.index].as_slice()
    }
  }

  fn cancel(&mut self) {
    self.state = Canceled
  }

  fn done(&mut self) {
    self.state = Done
  }
}

fn draw_screen(screen: &mut Screen, search: &Search) {
  screen.hide_cursor();
  screen.blank_screen();
  screen.write(format!("> {} ({} choices)\n", search.query, search.matches.len()).as_slice());

  print_matches(screen, &search.matches, search.index);

  let start = screen.start_line;
  screen.move_cursor(start, 2 + search.query.len() as u16);
  screen.show_cursor();
}

fn print_matches(screen: &mut Screen, matches: &Vec<&String>, index: usize) {
  let mut i = 1;
  for choice in matches.iter() {
    if i == index + 1 {
      screen.write_inverted(choice.as_slice());
    } else {
      screen.write(choice.as_slice());
    }
    if i >= screen.visible_choices as usize {
      return;
    } else {
      screen.write("\n");
    }
    i += 1;
  }
}

fn read_choices() -> Vec<String> {
  let mut stdin = io::stdio::stdin();
  let mut lines = Vec::new();

  while let Ok(mut s) = stdin.read_line() {
    trim(&mut s);
    lines.push(s);
  }

  lines
}

fn trim(s: &mut String) {
  while let Some(x) = s.pop() {
    if x != '\n' {
      s.push(x);
      return;
    }
  }
}

fn delete_last_word(s: &mut String) {
  let mut deleted_something = false;
  while let Some(x) = s.pop() {
    if x == ' ' {
      if deleted_something {
        s.push(x);
        return;
      }
    } else {
      deleted_something = true;
    }
  }
}

#[test]
fn trim_test() {
  fn should_become(before: &str, after: &str) {
    let mut x = before.to_string();
    trim(&mut x);
    assert_eq!(after.to_string(), x);
  }
  should_become("", "");
  should_become("\n", "");
  should_become("\n\n", "");
  should_become("asdf", "asdf");
  should_become("asdf\n", "asdf");
  should_become("asdf\nasdf\n", "asdf\nasdf");
}

#[test]
fn delete_word_test() {
  fn should_become(before: &str, after: &str) {
    let mut x = before.to_string();
    delete_last_word(&mut x);
    assert_eq!(after.to_string(), x);
  }
  should_become("", "");
  should_become("a", "");
  should_become("asdf", "");
  should_become("asdf asdf asdf", "asdf asdf ");
  should_become("asdf asdf asdf ", "asdf asdf ");
  should_become("asdf asdf asdf  ", "asdf asdf ");
}
<|endoftext|>


<commit_before>use std::cell::Cell;

struct Coordinates {
    x: Cell<i32>,
    y: Cell<i32>,
}

fn main() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(50) };
    let bike_two = Coordinates { x: Cell::new(100), y: Cell::new(50) };
    let mut one_pos = vec![];
    let mut two_pos = vec![];
    let mut all_pos = vec![];

    move_up(&bike_one.y);
    move_up(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_down(&bike_one.y);
    move_down(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_right(&bike_one.x);
    move_left(&bike_two.x);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_left(&bike_one.x);
    move_left(&bike_two.x);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    println!("Bike One");
    println!("X is {:?}, Y is {:?}", bike_one.x, bike_one.y);
    println!("{:?}", one_pos);

    println!("Bike Two");
    println!("X is {:?}, Y is {:?}", bike_two.x, bike_two.y);
    println!("{:?}", two_pos);

    println!("Final combined positions are: {:?}", all_pos)

}

fn add_positions<'a>(v_cc: &'a mut Vec<i32>, y: &Cell<i32>, x: &Cell<i32>) -> &'a mut Vec<i32> {
    v_cc.push(x.get());
    v_cc.push(y.get());
    v_cc
}

fn combined_positions<'a>(a_p: &'a mut Vec<i32>, o_p: &mut Vec<i32>, t_p: &mut Vec<i32>) -> &'a mut Vec<i32> {
    a_p.extend_from_slice(o_p);
    a_p.extend_from_slice(t_p);
    a_p
}

fn move_up(y_cord: &Cell<i32>) -> &Cell<i32> {
    y_cord.set(y_cord.get() + 1);
    y_cord
}

fn move_down(y_cord: &Cell<i32>) -> &Cell<i32> {
    y_cord.set(y_cord.get() - 1);
    y_cord
}

fn move_right(x_cord: &Cell<i32>) -> &Cell<i32> {
    x_cord.set(x_cord.get() + 1);
    x_cord
}

fn move_left(x_cord: &Cell<i32>) -> &Cell<i32> {
    x_cord.set(x_cord.get() - 1);
    x_cord
}

#[test]
fn it_can_move() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(0) };
    let mut one_pos = vec![];

    // test it starts at 0

    assert_eq!(0, bike_one.y.get());

    // test it can move up one and can add positions to the vector

    move_up(&bike_one.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);

    assert_eq!(1, bike_one.y.get());
    assert_eq!(0, one_pos[0]);
    assert_eq!(1, one_pos[1]);

    // test it can continue to move up and theat move logic is valid

    move_up(&bike_one.y);
    move_up(&bike_one.y);
    move_up(&bike_one.y);

    assert_eq!(4, bike_one.y.get());

    for _ in 0..19 { // _ instead of x so that rust does not complain about x not being used
        move_up(&bike_one.y); // moves up 19 times
    }

    assert_eq!(23, bike_one.y.get());

    // test it can move down

    for _ in 0..19 {
        move_down(&bike_one.y);
    }

    assert_eq!(4, bike_one.y.get());

    // test it can move right

    for _ in 0..19 {
        move_right(&bike_one.x);
    }

    assert_eq!(19, bike_one.x.get());

    // test it can move left

    for _ in 0..10 {
        move_left(&bike_one.x);
    }

    assert_eq!(9, bike_one.x.get());
}

#[test]
fn it_can_log_all_positions() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(50) };
    let bike_two = Coordinates { x: Cell::new(100), y: Cell::new(50) };
    let mut one_pos = vec![];
    let mut two_pos = vec![];
    let mut all_pos = vec![];

    move_up(&bike_one.y);
    move_up(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);

    assert_eq!(51, bike_one.x.get() + bike_one.y.get());

    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);

    assert_eq!(151, bike_two.x.get() + bike_two.y.get());

    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    let sum = all_pos.iter()
           .fold(0, |acc, &x| acc + x);

    assert_eq!(202, sum);
}
<commit_msg>removed position storage logic out of the first test<commit_after>use std::cell::Cell;

struct Coordinates {
    x: Cell<i32>,
    y: Cell<i32>,
}

fn main() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(50) };
    let bike_two = Coordinates { x: Cell::new(100), y: Cell::new(50) };
    let mut one_pos = vec![];
    let mut two_pos = vec![];
    let mut all_pos = vec![];

    move_up(&bike_one.y);
    move_up(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_down(&bike_one.y);
    move_down(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_right(&bike_one.x);
    move_left(&bike_two.x);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_left(&bike_one.x);
    move_left(&bike_two.x);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    println!("Bike One");
    println!("X is {:?}, Y is {:?}", bike_one.x, bike_one.y);
    println!("{:?}", one_pos);

    println!("Bike Two");
    println!("X is {:?}, Y is {:?}", bike_two.x, bike_two.y);
    println!("{:?}", two_pos);

    println!("Final combined positions are: {:?}", all_pos)

}

fn add_positions<'a>(v_cc: &'a mut Vec<i32>, y: &Cell<i32>, x: &Cell<i32>) -> &'a mut Vec<i32> {
    v_cc.push(x.get());
    v_cc.push(y.get());
    v_cc
}

fn combined_positions<'a>(a_p: &'a mut Vec<i32>, o_p: &mut Vec<i32>, t_p: &mut Vec<i32>) -> &'a mut Vec<i32> {
    a_p.extend_from_slice(o_p);
    a_p.extend_from_slice(t_p);
    a_p
}

fn move_up(y_cord: &Cell<i32>) -> &Cell<i32> {
    y_cord.set(y_cord.get() + 1);
    y_cord
}

fn move_down(y_cord: &Cell<i32>) -> &Cell<i32> {
    y_cord.set(y_cord.get() - 1);
    y_cord
}

fn move_right(x_cord: &Cell<i32>) -> &Cell<i32> {
    x_cord.set(x_cord.get() + 1);
    x_cord
}

fn move_left(x_cord: &Cell<i32>) -> &Cell<i32> {
    x_cord.set(x_cord.get() - 1);
    x_cord
}

#[test]
fn it_can_move() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(0) };
    let mut one_pos = vec![];

    // test it starts at 0

    assert_eq!(0, bike_one.y.get());

    // test it can move up one and can add positions to the vector

    move_up(&bike_one.y);

    assert_eq!(0, one_pos[0]);
    assert_eq!(1, one_pos[1]);

    // test it can continue to move up and theat move logic is valid

    move_up(&bike_one.y);
    move_up(&bike_one.y);
    move_up(&bike_one.y);

    assert_eq!(4, bike_one.y.get());

    for _ in 0..19 { // _ instead of x so that rust does not complain about x not being used
        move_up(&bike_one.y); // moves up 19 times
    }

    assert_eq!(23, bike_one.y.get());

    // test it can move down

    for _ in 0..19 {
        move_down(&bike_one.y);
    }

    assert_eq!(4, bike_one.y.get());

    // test it can move right

    for _ in 0..19 {
        move_right(&bike_one.x);
    }

    assert_eq!(19, bike_one.x.get());

    // test it can move left

    for _ in 0..10 {
        move_left(&bike_one.x);
    }

    assert_eq!(9, bike_one.x.get());
}

#[test]
fn it_can_log_all_positions() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(50) };
    let bike_two = Coordinates { x: Cell::new(100), y: Cell::new(50) };
    let mut one_pos = vec![];
    let mut two_pos = vec![];
    let mut all_pos = vec![];

    move_up(&bike_one.y);
    move_up(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);

    assert_eq!(51, bike_one.x.get() + bike_one.y.get());

    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);

    assert_eq!(151, bike_two.x.get() + bike_two.y.get());

    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    let sum = all_pos.iter()
           .fold(0, |acc, &x| acc + x);

    assert_eq!(202, sum);
}
<|endoftext|>


<commit_before>
use std::mem;
use std::rand;
use std::num;
use std::num::One;

/// Map a value from range in to range out.
pub fn map(val: f32, in_min: f32, in_max: f32, out_min: f32, out_max: f32) -> f32 {
    if (in_min - in_max).abs() < Float::epsilon() {
        println!("jmath Warning: map(): avoiding possible divide by zero, in_min ({}) and in_max({})", in_min, in_max);
        return out_min;
    }
    (val - in_min) / (in_max - in_min) * (out_max - out_min) + out_min
}

/// Clamp a value to a range.
pub fn clamp(val: f32, min: f32, max: f32) -> f32 {
    if val < min { min } else { if val > max { max } else { val } }
}

/// Check if value is in range.
pub fn inrange(val: f32, min: f32, max: f32) -> bool {
    val >= min && val <= max
}

/// Interpolate from start to stop 'amt' amount.
pub fn lerp(start: f32, stop: f32, amt: f32) -> f32 {
    start + (stop - start) * amt
}

/// Wrap value to a range.
pub fn wrap(val: f32, mut from: f32, mut to: f32) -> f32 {
    if from > to { mem::swap(&mut from, &mut to); }
    let cycle = to - from;
    if cycle == 0.0 { return to; }
    val - cycle * ((val - from) / cycle).floor()
}

/// Floors value.
pub fn fast_floor<F: Float + FromPrimitive + ToPrimitive>(f: F) -> int {
    return if f > FromPrimitive::from_int(0).unwrap() {
        f.to_int().unwrap()
    } else {
        f.to_int().unwrap() - One::one()
    }
}

/// Implementation of grad1 for the ported _slang_library_noise1 method.
/// (This is used for `get_noise_walk` in signal).
pub fn grad1(hash: int, x: f32) -> f32 {
    let h: int = hash & 15;
    let mut grad: f32 = 1.0f32 + ((h & 7) as f32);
    if h & 8 > 0 { grad = (-1.0f32) * grad; }
    grad * x
}

/// Implementation of `perm` for the ported _slang_library_noise1 method
/// (This is used for `get_noise_walk` in signal).
static PERM : [u8, ..512] = [151u8, 160u8, 137u8, 91u8, 90u8, 15u8,
      131u8, 13u8, 201u8,95u8,96u8,53u8,194u8,233u8,7u8,225u8,140u8,36u8,103u8,30u8,69u8,142u8,8u8,99u8,37u8,240u8,21u8,10u8,23u8,
      190u8, 6u8,148u8,247u8,120u8,234u8,75u8,0u8,26u8,197u8,62u8,94u8,252u8,219u8,203u8,117u8,35u8,11u8,32u8,57u8,177u8,33u8,
      88u8,237u8,149u8,56u8,87u8,174u8,20u8,125u8,136u8,171u8,168u8, 68u8,175u8,74u8,165u8,71u8,134u8,139u8,48u8,27u8,166u8,
      77u8,146u8,158u8,231u8,83u8,111u8,229u8,122u8,60u8,211u8,133u8,230u8,220u8,105u8,92u8,41u8,55u8,46u8,245u8,40u8,244u8,
      102u8,143u8,54u8, 65u8,25u8,63u8,161u8, 1u8,216u8,80u8,73u8,209u8,76u8,132u8,187u8,208u8, 89u8,18u8,169u8,200u8,196u8,
      135u8,130u8,116u8,188u8,159u8,86u8,164u8,100u8,109u8,198u8,173u8,186u8, 3u8,64u8,52u8,217u8,226u8,250u8,124u8,123u8,
      5u8,202u8,38u8,147u8,118u8,126u8,255u8,82u8,85u8,212u8,207u8,206u8,59u8,227u8,47u8,16u8,58u8,17u8,182u8,189u8,28u8,42u8,
      223u8,183u8,170u8,213u8,119u8,248u8,152u8, 2u8,44u8,154u8,163u8, 70u8,221u8,153u8,101u8,155u8,167u8, 43u8,172u8,9u8,
      129u8,22u8,39u8,253u8, 19u8,98u8,108u8,110u8,79u8,113u8,224u8,232u8,178u8,185u8, 112u8,104u8,218u8,246u8,97u8,228u8,
      251u8,34u8,242u8,193u8,238u8,210u8,144u8,12u8,191u8,179u8,162u8,241u8, 81u8,51u8,145u8,235u8,249u8,14u8,239u8,107u8,
      49u8,192u8,214u8, 31u8,181u8,199u8,106u8,157u8,184u8, 84u8,204u8,176u8,115u8,121u8,50u8,45u8,127u8, 4u8,150u8,254u8,
      138u8,236u8,205u8,93u8,222u8,114u8,67u8,29u8,24u8,72u8,243u8,141u8,128u8,195u8,78u8,66u8,215u8,61u8,156u8,180u8,
      151u8,160u8,137u8,91u8,90u8,15u8,
      131u8,13u8,201u8,95u8,96u8,53u8,194u8,233u8,7u8,225u8,140u8,36u8,103u8,30u8,69u8,142u8,8u8,99u8,37u8,240u8,21u8,10u8,23u8,
      190u8, 6u8,148u8,247u8,120u8,234u8,75u8,0u8,26u8,197u8,62u8,94u8,252u8,219u8,203u8,117u8,35u8,11u8,32u8,57u8,177u8,33u8,
      88u8,237u8,149u8,56u8,87u8,174u8,20u8,125u8,136u8,171u8,168u8, 68u8,175u8,74u8,165u8,71u8,134u8,139u8,48u8,27u8,166u8,
      77u8,146u8,158u8,231u8,83u8,111u8,229u8,122u8,60u8,211u8,133u8,230u8,220u8,105u8,92u8,41u8,55u8,46u8,245u8,40u8,244u8,
      102u8,143u8,54u8, 65u8,25u8,63u8,161u8, 1u8,216u8,80u8,73u8,209u8,76u8,132u8,187u8,208u8, 89u8,18u8,169u8,200u8,196u8,
      135u8,130u8,116u8,188u8,159u8,86u8,164u8,100u8,109u8,198u8,173u8,186u8, 3u8,64u8,52u8,217u8,226u8,250u8,124u8,123u8,
      5u8,202u8,38u8,147u8,118u8,126u8,255u8,82u8,85u8,212u8,207u8,206u8,59u8,227u8,47u8,16u8,58u8,17u8,182u8,189u8,28u8,42u8,
      223u8,183u8,170u8,213u8,119u8,248u8,152u8, 2u8,44u8,154u8,163u8, 70u8,221u8,153u8,101u8,155u8,167u8, 43u8,172u8,9u8,
      129u8,22u8,39u8,253u8, 19u8,98u8,108u8,110u8,79u8,113u8,224u8,232u8,178u8,185u8, 112u8,104u8,218u8,246u8,97u8,228u8,
      251u8,34u8,242u8,193u8,238u8,210u8,144u8,12u8,191u8,179u8,162u8,241u8, 81u8,51u8,145u8,235u8,249u8,14u8,239u8,107u8,
      49u8,192u8,214u8, 31u8,181u8,199u8,106u8,157u8,184u8, 84u8,204u8,176u8,115u8,121u8,50u8,45u8,127u8, 4u8,150u8,254u8,
      138u8,236u8,205u8,93u8,222u8,114u8,67u8,29u8,24u8,72u8,243u8,141u8,128u8,195u8,78u8,66u8,215u8,61u8,156u8,180u8];

/// Implementation of perm lookup for the ported _slang_library_noise1 method
pub fn get_perm_val(i: uint) -> u8 { PERM[i] }

#[test]
pub fn test() {
    println!("Testing map - 0..10 -> -100.0..100.0");
    for i in range(0, 10) {
        print!("{}, ", map(i as f32, 0.0, 10.0, -100.0, 100.0));
    }
    println!("");

    println!("Testing wrap - wrapping 0..10 to 0..2.66");
    for i in range(0, 10) {
        print!("{}, ", wrap(i as f32, 0.0, 2.66));
    }
    println!("");

    println!("Testing fast_floor - for 0, 10 mapped to -2 to 2");
    for i in range(0.0f32, 10.0f32) {
        print!("{}, ", fast_floor(map(i as f32, 0.0f32, 10.0f32, -0.99f32, 0.99f32)));
    }
    println!("");

    println!("U8 PERM LIST! {} ", get_perm_val(30));

}
  */

//------------------------------
<commit_msg>fixed docs and tests<commit_after>
use std::mem;
use std::rand;
use std::num;
use std::num::One;

/// Map a value from range in to range out.
pub fn map(val: f32, in_min: f32, in_max: f32, out_min: f32, out_max: f32) -> f32 {
    if (in_min - in_max).abs() < Float::epsilon() {
        println!("jmath Warning: map(): avoiding possible divide by zero, in_min ({}) and in_max({})", in_min, in_max);
        return out_min;
    }
    (val - in_min) / (in_max - in_min) * (out_max - out_min) + out_min
}

/// Clamp a value to a range.
pub fn clamp(val: f32, min: f32, max: f32) -> f32 {
    if val < min { min } else { if val > max { max } else { val } }
}

/// Check if value is in range.
pub fn inrange(val: f32, min: f32, max: f32) -> bool {
    val >= min && val <= max
}

/// Interpolate from start to stop 'amt' amount.
pub fn lerp(start: f32, stop: f32, amt: f32) -> f32 {
    start + (stop - start) * amt
}

/// Wrap value to a range.
pub fn wrap(val: f32, mut from: f32, mut to: f32) -> f32 {
    if from > to { mem::swap(&mut from, &mut to); }
    let cycle = to - from;
    if cycle == 0.0 { return to; }
    val - cycle * ((val - from) / cycle).floor()
}

/// Floors value.
pub fn fast_floor<F: Float + FromPrimitive + ToPrimitive>(f: F) -> int {
    return if f > FromPrimitive::from_int(0).unwrap() {
        f.to_int().unwrap()
    } else {
        f.to_int().unwrap() - One::one()
    }
}

/// Implementation of grad1 for the ported _slang_library_noise1 method.
/// (This is used for `get_noise_walk` in signal).
pub fn grad1(hash: int, x: f32) -> f32 {
    let h: int = hash & 15;
    let mut grad: f32 = 1.0f32 + ((h & 7) as f32);
    if h & 8 > 0 { grad = (-1.0f32) * grad; }
    grad * x
}

/// Implementation of `perm` for the ported _slang_library_noise1 method
/// (This is used for `get_noise_walk` in signal).
static PERM : [u8, ..512] = [151u8, 160u8, 137u8, 91u8, 90u8, 15u8,
      131u8, 13u8, 201u8,95u8,96u8,53u8,194u8,233u8,7u8,225u8,140u8,36u8,103u8,30u8,69u8,142u8,8u8,99u8,37u8,240u8,21u8,10u8,23u8,
      190u8, 6u8,148u8,247u8,120u8,234u8,75u8,0u8,26u8,197u8,62u8,94u8,252u8,219u8,203u8,117u8,35u8,11u8,32u8,57u8,177u8,33u8,
      88u8,237u8,149u8,56u8,87u8,174u8,20u8,125u8,136u8,171u8,168u8, 68u8,175u8,74u8,165u8,71u8,134u8,139u8,48u8,27u8,166u8,
      77u8,146u8,158u8,231u8,83u8,111u8,229u8,122u8,60u8,211u8,133u8,230u8,220u8,105u8,92u8,41u8,55u8,46u8,245u8,40u8,244u8,
      102u8,143u8,54u8, 65u8,25u8,63u8,161u8, 1u8,216u8,80u8,73u8,209u8,76u8,132u8,187u8,208u8, 89u8,18u8,169u8,200u8,196u8,
      135u8,130u8,116u8,188u8,159u8,86u8,164u8,100u8,109u8,198u8,173u8,186u8, 3u8,64u8,52u8,217u8,226u8,250u8,124u8,123u8,
      5u8,202u8,38u8,147u8,118u8,126u8,255u8,82u8,85u8,212u8,207u8,206u8,59u8,227u8,47u8,16u8,58u8,17u8,182u8,189u8,28u8,42u8,
      223u8,183u8,170u8,213u8,119u8,248u8,152u8, 2u8,44u8,154u8,163u8, 70u8,221u8,153u8,101u8,155u8,167u8, 43u8,172u8,9u8,
      129u8,22u8,39u8,253u8, 19u8,98u8,108u8,110u8,79u8,113u8,224u8,232u8,178u8,185u8, 112u8,104u8,218u8,246u8,97u8,228u8,
      251u8,34u8,242u8,193u8,238u8,210u8,144u8,12u8,191u8,179u8,162u8,241u8, 81u8,51u8,145u8,235u8,249u8,14u8,239u8,107u8,
      49u8,192u8,214u8, 31u8,181u8,199u8,106u8,157u8,184u8, 84u8,204u8,176u8,115u8,121u8,50u8,45u8,127u8, 4u8,150u8,254u8,
      138u8,236u8,205u8,93u8,222u8,114u8,67u8,29u8,24u8,72u8,243u8,141u8,128u8,195u8,78u8,66u8,215u8,61u8,156u8,180u8,
      151u8,160u8,137u8,91u8,90u8,15u8,
      131u8,13u8,201u8,95u8,96u8,53u8,194u8,233u8,7u8,225u8,140u8,36u8,103u8,30u8,69u8,142u8,8u8,99u8,37u8,240u8,21u8,10u8,23u8,
      190u8, 6u8,148u8,247u8,120u8,234u8,75u8,0u8,26u8,197u8,62u8,94u8,252u8,219u8,203u8,117u8,35u8,11u8,32u8,57u8,177u8,33u8,
      88u8,237u8,149u8,56u8,87u8,174u8,20u8,125u8,136u8,171u8,168u8, 68u8,175u8,74u8,165u8,71u8,134u8,139u8,48u8,27u8,166u8,
      77u8,146u8,158u8,231u8,83u8,111u8,229u8,122u8,60u8,211u8,133u8,230u8,220u8,105u8,92u8,41u8,55u8,46u8,245u8,40u8,244u8,
      102u8,143u8,54u8, 65u8,25u8,63u8,161u8, 1u8,216u8,80u8,73u8,209u8,76u8,132u8,187u8,208u8, 89u8,18u8,169u8,200u8,196u8,
      135u8,130u8,116u8,188u8,159u8,86u8,164u8,100u8,109u8,198u8,173u8,186u8, 3u8,64u8,52u8,217u8,226u8,250u8,124u8,123u8,
      5u8,202u8,38u8,147u8,118u8,126u8,255u8,82u8,85u8,212u8,207u8,206u8,59u8,227u8,47u8,16u8,58u8,17u8,182u8,189u8,28u8,42u8,
      223u8,183u8,170u8,213u8,119u8,248u8,152u8, 2u8,44u8,154u8,163u8, 70u8,221u8,153u8,101u8,155u8,167u8, 43u8,172u8,9u8,
      129u8,22u8,39u8,253u8, 19u8,98u8,108u8,110u8,79u8,113u8,224u8,232u8,178u8,185u8, 112u8,104u8,218u8,246u8,97u8,228u8,
      251u8,34u8,242u8,193u8,238u8,210u8,144u8,12u8,191u8,179u8,162u8,241u8, 81u8,51u8,145u8,235u8,249u8,14u8,239u8,107u8,
      49u8,192u8,214u8, 31u8,181u8,199u8,106u8,157u8,184u8, 84u8,204u8,176u8,115u8,121u8,50u8,45u8,127u8, 4u8,150u8,254u8,
      138u8,236u8,205u8,93u8,222u8,114u8,67u8,29u8,24u8,72u8,243u8,141u8,128u8,195u8,78u8,66u8,215u8,61u8,156u8,180u8];

/// Implementation of perm lookup for the ported _slang_library_noise1 method
pub fn get_perm_val(i: uint) -> u8 { PERM[i] }

#[test]
pub fn test() {
    println!("Testing map - 0..10 -> -100.0..100.0");
    for i in range(0, 10) {
        print!("{}, ", map(i as f32, 0.0, 10.0, -100.0, 100.0));
    }
    println!("");

    println!("Testing wrap - wrapping 0..10 to 0..2.66");
    for i in range(0, 10) {
        print!("{}, ", wrap(i as f32, 0.0, 2.66));
    }
    println!("");

    println!("Testing fast_floor - for 0, 10 mapped to -2 to 2");
    for i in range(0.0f32, 10.0f32) {
        print!("{}, ", fast_floor(map(i as f32, 0.0f32, 10.0f32, -0.99f32, 0.99f32)));
    }
    println!("");

    println!("U8 PERM LIST! {} ", get_perm_val(30));

}

<|endoftext|>


<commit_before>//! Module with the self-pipe pattern.
//!
//! One of the common patterns around signals is to have a pipe with both ends in the same program.
//! Whenever there's a signal, the signal handler writes one byte of garbage data to the write end,
//! unless the pipe's already full. The application then can handle the read end.
//!
//! This has two advantages. First, the real signal action moves outside of the signal handler
//! where there are a lot less restrictions. Second, it fits nicely in all kinds of asynchronous
//! loops and has less chance of race conditions.
//!
//! This module offers premade functions for the write end (and doesn't insist that it must be a
//! pipe ‒ anything that can be written to is fine ‒ sockets too, therefore `UnixStream::pair` is a
//! good candidate).
//!
//! If you want to integrate with some asynchronous library, plugging streams from `mio-uds` or
//! `tokio-uds` libraries should work.
//!
//! If it looks too low-level for your needs, the [`iterator`](../iterator/) module contains some
//! higher-lever interface that also uses a self-pipe pattern under the hood.
//!
//! # Correct order of handling
//!
//! A care needs to be taken to avoid race conditions, especially when handling the same signal in
//! a loop. Specifically, another signal might come when the action for the previous signal is
//! being taken. The correct order is first to clear the content of the pipe (read some/all data
//! from it) and then take the action. This way a spurious wakeup can happen (the pipe could wake
//! up even when no signal came after the signal was taken, because ‒ it arrived between cleaning
//! the pipe and taking the action). Note that some OS primitives (eg. `select`) suffer from
//! spurious wakeups themselves (they can claim a FD is readable when it is not true) and blocking
//! `read` might return prematurely (with eg. `EINTR`).
//!
//! The reverse order of first taking the action and then clearing the pipe might lose signals,
//! which is usually worse.
//!
//! This is not a problem with blocking on reading from the pipe (because both the blocking and
//! cleaning is the same action), but in case of asynchronous handling it matters.
//!
//! If you want to combine setting some flags with a self-pipe pattern, the flag needs to be set
//! first, then the pipe written. On the read end, first the pipe needs to be cleaned, then the
//! flag and then the action taken. This is what the [`Signals`](../iterator/struct.Signals.html)
//! structure does internally.
//!
//! # Write collating
//!
//! While unlikely if handled correctly, it is possible the write end is full when a signal comes.
//! In such case the signal handler simply does nothing. If the write end is full, the read end is
//! readable and therefore will wake up. On the other hand, blocking in the signal handler would
//! definitely be a bad idea.
//!
//! However, this also means the number of bytes read from the end might be lower than the number
//! of signals that arrived. This should not generally be a problem, since the OS already collates
//! signals of the same kind together.
//!
//! # Examples
//!
//! This example waits for at last one `SIGUSR1` signal to come before continuing (and
//! terminating). It sends the signal to itself, so it correctly terminates.
//!
//! ```rust
//! extern crate libc;
//! extern crate signal_hook;
//!
//! use std::io::{Error, Read};
//! use std::os::unix::net::UnixStream;
//!
//! fn main() -> Result<(), Error> {
//!     let (mut read, write) = UnixStream::pair()?;
//!     signal_hook::pipe::register(signal_hook::SIGUSR1, write)?;
//!     // This will write into the pipe write end through the signal handler
//!     unsafe { libc::raise(signal_hook::SIGUSR1) };
//!     let mut buff = [0];
//!     read.read_exact(&mut buff)?;
//!     println!("Happily terminating");
//!     Ok(())
//! }

use std::io::Error;
use std::os::unix::io::{AsRawFd, RawFd};

use libc::{self, c_int};

use SigId;

struct OwnedFd(RawFd);

impl OwnedFd {
    /// Sets close on exec and nonblock on the inner file descriptor.
    fn set_flags(&self) -> Result<(), Error> {
        unsafe {
            let flags = libc::fcntl(self.as_raw_fd(), libc::F_GETFL, 0);
            if flags == -1 {
                return Err(Error::last_os_error());
            }
            let flags = flags | libc::O_NONBLOCK | libc::O_CLOEXEC;
            if libc::fcntl(self.as_raw_fd(), libc::F_SETFL, flags) == -1 {
                return Err(Error::last_os_error());
            }
        }
        Ok(())
    }
}

impl AsRawFd for OwnedFd {
    fn as_raw_fd(&self) -> RawFd {
        self.0
    }
}

impl Drop for OwnedFd {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.0);
        }
    }
}

pub(crate) fn wake(pipe: RawFd) {
    unsafe {
        // This writes some data into the pipe.
        //
        // There are two tricks:
        // * First, the crazy cast. The first part turns reference into pointer. The second part
        //   turns pointer to u8 into a pointer to void, which is what write requires.
        // * Second, we ignore errors, on purpose. We don't have any means to handling them. The
        //   two conceivable errors are EBADFD, if someone passes a non-existent file descriptor or
        //   if it is closed. The second is EAGAIN, in which case the pipe is full ‒ there were
        //   many signals, but the reader didn't have time to read the data yet. It'll still get
        //   woken up, so not fitting another letter in it is fine.
        libc::write(pipe, b"X" as *const _ as *const _, 1);
    }
}

/// Registers a write to a self-pipe whenever there's the signal.
///
/// In this case, the pipe is taken as the `RawFd`. It is still the caller's responsibility to
/// close it.
pub fn register_raw(signal: c_int, pipe: RawFd) -> Result<SigId, Error> {
    // A trick here:
    // We want to set the FD non-blocking. But it belongs to the caller. Therefore, we make our own
    // copy with `dup` to play on instead.
    let duped = unsafe { libc::dup(pipe) };
    if duped == -1 {
        return Err(Error::last_os_error());
    }
    let duped = OwnedFd(duped);
    duped.set_flags()?;
    let action = move || wake(duped.as_raw_fd());
    unsafe { ::register(signal, action) }
}

/// Registers a write to a self-pipe whenever there's the signal.
///
/// The ownership of pipe is taken and will be closed whenever the created action is unregistered.
///
/// Note that if you want to register the same pipe for multiple signals, there's `try_clone`
/// method on many unix socket primitives.
pub fn register<P>(signal: c_int, pipe: P) -> Result<SigId, Error>
where
    P: AsRawFd + Send + Sync + 'static,
{
    let id = register_raw(signal, pipe.as_raw_fd())?;
    // Close the original
    drop(pipe);
    Ok(id)
}

#[cfg(test)]
mod tests {
    use std::io::Read;
    use std::os::unix::net::{UnixDatagram, UnixStream};

    use super::*;

    // Note: multiple tests share the SIGUSR1 signal. This is fine, we only need to know the signal
    // arrives. It's OK to arrive multiple times, from multiple tests.
    fn wakeup() {
        unsafe { assert_eq!(0, libc::raise(libc::SIGUSR1)) }
    }

    #[test]
    fn register_with_socket() -> Result<(), Error> {
        let (mut read, write) = UnixStream::pair()?;
        register(libc::SIGUSR1, write)?;
        read.set_nonblocking(true)?;
        wakeup();
        let mut buff = [0; 1];
        read.read_exact(&mut buff)?;
        assert_eq!(b"X", &buff);
        Ok(())
    }

    #[test]
    fn register_dgram_socket() -> Result<(), Error> {
        let (read, write) = UnixDatagram::pair()?;
        register(libc::SIGUSR1, write)?;
        read.set_nonblocking(true)?;
        wakeup();
        let mut buff = [0; 1];
        read.recv(&mut buff)?;
        assert_eq!(b"X", &buff);
        Ok(())
    }

    #[test]
    fn register_with_pipe() -> Result<(), Error> {
        let mut fds = [0; 2];
        unsafe { assert_eq!(0, libc::pipe(fds.as_mut_ptr())) };
        let read = OwnedFd(fds[0]);
        let write = OwnedFd(fds[1]);
        register(libc::SIGUSR1, write)?;
        read.set_flags()?;
        wakeup();
        let mut buff = [0; 1];
        unsafe {
            assert_eq!(
                1,
                libc::read(read.as_raw_fd(), buff.as_mut_ptr() as *mut _, 1)
            )
        }
        assert_eq!(b"X", &buff);
        Ok(())
    }
}
<commit_msg>A note about danger inside the pipe::register_raw<commit_after>//! Module with the self-pipe pattern.
//!
//! One of the common patterns around signals is to have a pipe with both ends in the same program.
//! Whenever there's a signal, the signal handler writes one byte of garbage data to the write end,
//! unless the pipe's already full. The application then can handle the read end.
//!
//! This has two advantages. First, the real signal action moves outside of the signal handler
//! where there are a lot less restrictions. Second, it fits nicely in all kinds of asynchronous
//! loops and has less chance of race conditions.
//!
//! This module offers premade functions for the write end (and doesn't insist that it must be a
//! pipe ‒ anything that can be written to is fine ‒ sockets too, therefore `UnixStream::pair` is a
//! good candidate).
//!
//! If you want to integrate with some asynchronous library, plugging streams from `mio-uds` or
//! `tokio-uds` libraries should work.
//!
//! If it looks too low-level for your needs, the [`iterator`](../iterator/) module contains some
//! higher-lever interface that also uses a self-pipe pattern under the hood.
//!
//! # Correct order of handling
//!
//! A care needs to be taken to avoid race conditions, especially when handling the same signal in
//! a loop. Specifically, another signal might come when the action for the previous signal is
//! being taken. The correct order is first to clear the content of the pipe (read some/all data
//! from it) and then take the action. This way a spurious wakeup can happen (the pipe could wake
//! up even when no signal came after the signal was taken, because ‒ it arrived between cleaning
//! the pipe and taking the action). Note that some OS primitives (eg. `select`) suffer from
//! spurious wakeups themselves (they can claim a FD is readable when it is not true) and blocking
//! `read` might return prematurely (with eg. `EINTR`).
//!
//! The reverse order of first taking the action and then clearing the pipe might lose signals,
//! which is usually worse.
//!
//! This is not a problem with blocking on reading from the pipe (because both the blocking and
//! cleaning is the same action), but in case of asynchronous handling it matters.
//!
//! If you want to combine setting some flags with a self-pipe pattern, the flag needs to be set
//! first, then the pipe written. On the read end, first the pipe needs to be cleaned, then the
//! flag and then the action taken. This is what the [`Signals`](../iterator/struct.Signals.html)
//! structure does internally.
//!
//! # Write collating
//!
//! While unlikely if handled correctly, it is possible the write end is full when a signal comes.
//! In such case the signal handler simply does nothing. If the write end is full, the read end is
//! readable and therefore will wake up. On the other hand, blocking in the signal handler would
//! definitely be a bad idea.
//!
//! However, this also means the number of bytes read from the end might be lower than the number
//! of signals that arrived. This should not generally be a problem, since the OS already collates
//! signals of the same kind together.
//!
//! # Examples
//!
//! This example waits for at last one `SIGUSR1` signal to come before continuing (and
//! terminating). It sends the signal to itself, so it correctly terminates.
//!
//! ```rust
//! extern crate libc;
//! extern crate signal_hook;
//!
//! use std::io::{Error, Read};
//! use std::os::unix::net::UnixStream;
//!
//! fn main() -> Result<(), Error> {
//!     let (mut read, write) = UnixStream::pair()?;
//!     signal_hook::pipe::register(signal_hook::SIGUSR1, write)?;
//!     // This will write into the pipe write end through the signal handler
//!     unsafe { libc::raise(signal_hook::SIGUSR1) };
//!     let mut buff = [0];
//!     read.read_exact(&mut buff)?;
//!     println!("Happily terminating");
//!     Ok(())
//! }

use std::io::Error;
use std::os::unix::io::{AsRawFd, RawFd};

use libc::{self, c_int};

use SigId;

struct OwnedFd(RawFd);

impl OwnedFd {
    /// Sets close on exec and nonblock on the inner file descriptor.
    fn set_flags(&self) -> Result<(), Error> {
        unsafe {
            let flags = libc::fcntl(self.as_raw_fd(), libc::F_GETFL, 0);
            if flags == -1 {
                return Err(Error::last_os_error());
            }
            let flags = flags | libc::O_NONBLOCK | libc::O_CLOEXEC;
            if libc::fcntl(self.as_raw_fd(), libc::F_SETFL, flags) == -1 {
                return Err(Error::last_os_error());
            }
        }
        Ok(())
    }
}

impl AsRawFd for OwnedFd {
    fn as_raw_fd(&self) -> RawFd {
        self.0
    }
}

impl Drop for OwnedFd {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.0);
        }
    }
}

pub(crate) fn wake(pipe: RawFd) {
    unsafe {
        // This writes some data into the pipe.
        //
        // There are two tricks:
        // * First, the crazy cast. The first part turns reference into pointer. The second part
        //   turns pointer to u8 into a pointer to void, which is what write requires.
        // * Second, we ignore errors, on purpose. We don't have any means to handling them. The
        //   two conceivable errors are EBADFD, if someone passes a non-existent file descriptor or
        //   if it is closed. The second is EAGAIN, in which case the pipe is full ‒ there were
        //   many signals, but the reader didn't have time to read the data yet. It'll still get
        //   woken up, so not fitting another letter in it is fine.
        libc::write(pipe, b"X" as *const _ as *const _, 1);
    }
}

/// Registers a write to a self-pipe whenever there's the signal.
///
/// In this case, the pipe is taken as the `RawFd`. It is still the caller's responsibility to
/// close it.
///
/// Note that passing the wrong file descriptor won't cause UB, but can still lead to severe bugs ‒
/// like data corruptions in files.
pub fn register_raw(signal: c_int, pipe: RawFd) -> Result<SigId, Error> {
    // A trick here:
    // We want to set the FD non-blocking. But it belongs to the caller. Therefore, we make our own
    // copy with `dup` to play on instead.
    let duped = unsafe { libc::dup(pipe) };
    if duped == -1 {
        return Err(Error::last_os_error());
    }
    let duped = OwnedFd(duped);
    duped.set_flags()?;
    let action = move || wake(duped.as_raw_fd());
    unsafe { ::register(signal, action) }
}

/// Registers a write to a self-pipe whenever there's the signal.
///
/// The ownership of pipe is taken and will be closed whenever the created action is unregistered.
///
/// Note that if you want to register the same pipe for multiple signals, there's `try_clone`
/// method on many unix socket primitives.
pub fn register<P>(signal: c_int, pipe: P) -> Result<SigId, Error>
where
    P: AsRawFd + Send + Sync + 'static,
{
    let id = register_raw(signal, pipe.as_raw_fd())?;
    // Close the original
    drop(pipe);
    Ok(id)
}

#[cfg(test)]
mod tests {
    use std::io::Read;
    use std::os::unix::net::{UnixDatagram, UnixStream};

    use super::*;

    // Note: multiple tests share the SIGUSR1 signal. This is fine, we only need to know the signal
    // arrives. It's OK to arrive multiple times, from multiple tests.
    fn wakeup() {
        unsafe { assert_eq!(0, libc::raise(libc::SIGUSR1)) }
    }

    #[test]
    fn register_with_socket() -> Result<(), Error> {
        let (mut read, write) = UnixStream::pair()?;
        register(libc::SIGUSR1, write)?;
        read.set_nonblocking(true)?;
        wakeup();
        let mut buff = [0; 1];
        read.read_exact(&mut buff)?;
        assert_eq!(b"X", &buff);
        Ok(())
    }

    #[test]
    fn register_dgram_socket() -> Result<(), Error> {
        let (read, write) = UnixDatagram::pair()?;
        register(libc::SIGUSR1, write)?;
        read.set_nonblocking(true)?;
        wakeup();
        let mut buff = [0; 1];
        read.recv(&mut buff)?;
        assert_eq!(b"X", &buff);
        Ok(())
    }

    #[test]
    fn register_with_pipe() -> Result<(), Error> {
        let mut fds = [0; 2];
        unsafe { assert_eq!(0, libc::pipe(fds.as_mut_ptr())) };
        let read = OwnedFd(fds[0]);
        let write = OwnedFd(fds[1]);
        register(libc::SIGUSR1, write)?;
        read.set_flags()?;
        wakeup();
        let mut buff = [0; 1];
        unsafe {
            assert_eq!(
                1,
                libc::read(read.as_raw_fd(), buff.as_mut_ptr() as *mut _, 1)
            )
        }
        assert_eq!(b"X", &buff);
        Ok(())
    }
}
<|endoftext|>