<commit_before>#[macro_use]
extern crate glium;
use glium::glutin;

use std::collections::HashMap;

#[macro_use]
mod support;

pub type Color = [f32; 4];

enum Shape {
    Clear(Color),
    Polygon(Vec<(f32, f32)>, Color),
    Line(f32, f32, f32, f32, Color),
}

pub struct Window {
    display: glium::Display,
    events_loop: glium::glutin::EventsLoop,
    color: [f32; 4],
    shapes: Vec<Shape>,
    keys: HashMap<glutin::VirtualKeyCode, bool>,
}

impl Window {
    pub fn new(title: &str, width: u32, height: u32) -> Self {
        let events_loop = glutin::EventsLoop::new();
        let window = glutin::WindowBuilder::new()
            .with_title(title)
            .with_dimensions(width, height);
        let context = glutin::ContextBuilder::new();
        let display = glium::Display::new(window, context, &events_loop).unwrap();

        Window {
            display: display,
            events_loop: events_loop,
            color: [1.0, 1.0, 1.0, 1.0],
            shapes: Vec::new(),
            keys: HashMap::new(),
        }
    }

    pub fn start_loop<F>(&mut self, mut callback: F)
    where
        F: FnMut(&mut Window, f32) -> support::Action,
    {
        let program = support::shaders::load_program(&self.display).unwrap();
        let params = glium::DrawParameters {
            blend: glium::draw_parameters::Blend::alpha_blending(),
            ..Default::default()
        };

        use glium::Surface;
        support::start_loop(|delta| {

            let mut target = self.display.draw();

            let mut rtn = callback(self, delta);
            for shape in self.shapes.iter() {
                match shape {
                    &Shape::Clear(color) => {
                        target.clear_color(color[0], color[1], color[2], color[3])
                    }
                    &Shape::Line(x1, y1, x2, y2, color) => {
                        let vert_buff =
                            support::buffer::line_vert_buff(&self.display, x1, y1, x2, y2, color)
                                .unwrap();
                        let indices =
                            glium::index::NoIndices(glium::index::PrimitiveType::LineStrip);
                        target
                            .draw(
                                &vert_buff,
                                &indices,
                                &program,
                                &glium::uniforms::EmptyUniforms,
                                &params,
                            )
                            .unwrap();
                    }
                    &Shape::Polygon(ref points, color) => {
                        let vert_buff =
                            support::buffer::poly_vert_buffer(&self.display, &points, color)
                                .unwrap();
                        let indices =
                            glium::index::NoIndices(glium::index::PrimitiveType::TriangleFan);
                        target
                            .draw(
                                &vert_buff,
                                &indices,
                                &program,
                                &glium::uniforms::EmptyUniforms,
                                &params,
                            )
                            .unwrap();
                    }
                }
            }

            self.shapes.clear();

            target.finish().unwrap();

            let mut keys: HashMap<glutin::VirtualKeyCode, bool> = HashMap::new();
            self.events_loop.poll_events(|ev| match ev {
                glium::glutin::Event::WindowEvent { event, .. } => {
                    match event {
                        glutin::WindowEvent::Closed => rtn = support::Action::Stop,
                        glutin::WindowEvent::KeyboardInput { input, .. } => {
                            match input.virtual_keycode {
                                Some(key) => {
                                    keys.insert(
                                        key,
                                        match input.state {
                                            glutin::ElementState::Pressed => true,
                                            glutin::ElementState::Released => false,
                                        },
                                    );
                                }
                                None => (),
                            }
                        }
                        _ => (),
                    }
                }
                _ => (),
            });

            for (key, value) in keys {
                self.keys.insert(key, value);
            }

            rtn
        });
    }

    pub fn clear_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) {
        let shape = Shape::Clear([red, green, blue, alpha]);
        self.shapes.push(shape);
    }

    pub fn set_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) {
        self.color = [red, green, blue, alpha];
    }

    pub fn set_color_html(&mut self, color: &str) {
        let mut bytes = color.as_bytes();
        if bytes[0] == b'#' {
            bytes = &bytes[1..];
        }

        use std::str::from_utf8;
        use std::u8;

        if bytes.len() == 3 {
            let r = u8::from_str_radix(from_utf8(&vec![bytes[0], bytes[0]]).unwrap(), 16).unwrap();
            let g = u8::from_str_radix(from_utf8(&vec![bytes[1], bytes[1]]).unwrap(), 16).unwrap();
            let b = u8::from_str_radix(from_utf8(&vec![bytes[2], bytes[2]]).unwrap(), 16).unwrap();
            self.set_color(
                (r as f32) / 255.0,
                (g as f32) / 255.0,
                (b as f32) / 255.0,
                1.0,
            );
        } else if bytes.len() == 6 {
            let r = u8::from_str_radix(from_utf8(&bytes[0..2]).unwrap(), 16).unwrap();
            let g = u8::from_str_radix(from_utf8(&bytes[2..4]).unwrap(), 16).unwrap();
            let b = u8::from_str_radix(from_utf8(&bytes[4..6]).unwrap(), 16).unwrap();
            self.set_color(
                (r as f32) / 255.0,
                (g as f32) / 255.0,
                (b as f32) / 255.0,
                1.0,
            );
        }
    }

    pub fn draw(&mut self, points: &[(f32, f32)]) {
        let shape = Shape::Polygon(Vec::from(points), self.color);
        self.shapes.push(shape);
    }

    pub fn draw_line(&mut self, x1: f32, y1: f32, x2: f32, y2: f32) {
        let shape = Shape::Line(x1, y1, x2, y2, self.color);
        self.shapes.push(shape);
    }

    pub fn draw_rect(&mut self, p1: (f32, f32), p2: (f32, f32)) {
        let shape = Shape::Polygon(
            vec![(p1.0, p1.1), (p1.0, p2.1), (p2.0, p2.1), (p2.0, p1.1)],
            self.color,
        );
        self.shapes.push(shape);
    }

    pub fn draw_circle(&mut self, x: f32, y: f32, rx: f32, ry: f32, step_size: u32) {
        let circle: Vec<(f32, f32)> = (0u32..360)
            .filter(|d| d % step_size == 0)
            .map(|d| {
                let r = (d as f32).to_radians();
                (r.cos() * rx, r.sin() * ry)
            })
            .collect();
        let shape = Shape::Polygon(circle, self.color);
        self.shapes.push(shape);
    }
}

fn main() {
    let mut window = Window::new("Hello World", 640, 480);

    window.start_loop(|app, delta| {
        app.clear_color(0.1, 0.3, 0.2, 1.0);

        app.set_color_html("312");
        app.draw_rect((-0.5, -0.5), (0.5, 0.5));

        app.set_color_html("#033112");
        app.draw_rect((0.0, 0.0), (-1.0, -1.0));

        app.set_color(1.0, 0.0, 0.0, 1.0);
        app.draw_line(0.0, 0.0, 1.0, 1.0);

        app.set_color(0.0, 0.0, 1.0, 0.3);
        app.draw(&[(0.0, 0.0), (1.0, 1.0), (1.0, 0.0)]);

        app.set_color(0.0, 1.0, 0.0, 0.3);
        app.draw(&[(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)]);

        app.set_color(1.0, 0.0, 0.0, 0.3);
        app.draw_circle(0.0, 0.0, 0.75, 0.25, 10);

        support::Action::Continue
    });
}
<commit_msg>Replaced clear_color with clear_to_color, added clear<commit_after>#[macro_use]
extern crate glium;
use glium::glutin;

use std::collections::HashMap;

#[macro_use]
mod support;

pub type Color = [f32; 4];

enum Shape {
    Clear(Color),
    Polygon(Vec<(f32, f32)>, Color),
    Line(f32, f32, f32, f32, Color),
}

pub struct Window {
    display: glium::Display,
    events_loop: glium::glutin::EventsLoop,
    color: [f32; 4],
    shapes: Vec<Shape>,
    keys: HashMap<glutin::VirtualKeyCode, bool>,
}

impl Window {
    pub fn new(title: &str, width: u32, height: u32) -> Self {
        let events_loop = glutin::EventsLoop::new();
        let window = glutin::WindowBuilder::new()
            .with_title(title)
            .with_dimensions(width, height);
        let context = glutin::ContextBuilder::new();
        let display = glium::Display::new(window, context, &events_loop).unwrap();

        Window {
            display: display,
            events_loop: events_loop,
            color: [1.0, 1.0, 1.0, 1.0],
            shapes: Vec::new(),
            keys: HashMap::new(),
        }
    }

    pub fn start_loop<F>(&mut self, mut callback: F)
    where
        F: FnMut(&mut Window, f32) -> support::Action,
    {
        let program = support::shaders::load_program(&self.display).unwrap();
        let params = glium::DrawParameters {
            blend: glium::draw_parameters::Blend::alpha_blending(),
            ..Default::default()
        };

        use glium::Surface;
        support::start_loop(|delta| {

            let mut target = self.display.draw();

            let mut rtn = callback(self, delta);
            for shape in self.shapes.iter() {
                match shape {
                    &Shape::Clear(color) => {
                        target.clear_color(color[0], color[1], color[2], color[3])
                    }
                    &Shape::Line(x1, y1, x2, y2, color) => {
                        let vert_buff =
                            support::buffer::line_vert_buff(&self.display, x1, y1, x2, y2, color)
                                .unwrap();
                        let indices =
                            glium::index::NoIndices(glium::index::PrimitiveType::LineStrip);
                        target
                            .draw(
                                &vert_buff,
                                &indices,
                                &program,
                                &glium::uniforms::EmptyUniforms,
                                &params,
                            )
                            .unwrap();
                    }
                    &Shape::Polygon(ref points, color) => {
                        let vert_buff =
                            support::buffer::poly_vert_buffer(&self.display, &points, color)
                                .unwrap();
                        let indices =
                            glium::index::NoIndices(glium::index::PrimitiveType::TriangleFan);
                        target
                            .draw(
                                &vert_buff,
                                &indices,
                                &program,
                                &glium::uniforms::EmptyUniforms,
                                &params,
                            )
                            .unwrap();
                    }
                }
            }

            self.shapes.clear();

            target.finish().unwrap();

            let mut keys: HashMap<glutin::VirtualKeyCode, bool> = HashMap::new();
            self.events_loop.poll_events(|ev| match ev {
                glium::glutin::Event::WindowEvent { event, .. } => {
                    match event {
                        glutin::WindowEvent::Closed => rtn = support::Action::Stop,
                        glutin::WindowEvent::KeyboardInput { input, .. } => {
                            match input.virtual_keycode {
                                Some(key) => {
                                    keys.insert(
                                        key,
                                        match input.state {
                                            glutin::ElementState::Pressed => true,
                                            glutin::ElementState::Released => false,
                                        },
                                    );
                                }
                                None => (),
                            }
                        }
                        _ => (),
                    }
                }
                _ => (),
            });

            for (key, value) in keys {
                self.keys.insert(key, value);
            }

            rtn
        });
    }

    pub fn clear_to_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) {
        let shape = Shape::Clear([red, green, blue, alpha]);
        self.shapes.push(shape);
    }

    pub fn clear(&mut self) {
        self.clear_to_color(0.0, 0.0, 0.0, 1.0);
    }

    pub fn set_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) {
        self.color = [red, green, blue, alpha];
    }

    pub fn set_color_html(&mut self, color: &str) {
        let mut bytes = color.as_bytes();
        if bytes[0] == b'#' {
            bytes = &bytes[1..];
        }

        use std::str::from_utf8;
        use std::u8;

        if bytes.len() == 3 {
            let r = u8::from_str_radix(from_utf8(&vec![bytes[0], bytes[0]]).unwrap(), 16).unwrap();
            let g = u8::from_str_radix(from_utf8(&vec![bytes[1], bytes[1]]).unwrap(), 16).unwrap();
            let b = u8::from_str_radix(from_utf8(&vec![bytes[2], bytes[2]]).unwrap(), 16).unwrap();
            self.set_color(
                (r as f32) / 255.0,
                (g as f32) / 255.0,
                (b as f32) / 255.0,
                1.0,
            );
        } else if bytes.len() == 6 {
            let r = u8::from_str_radix(from_utf8(&bytes[0..2]).unwrap(), 16).unwrap();
            let g = u8::from_str_radix(from_utf8(&bytes[2..4]).unwrap(), 16).unwrap();
            let b = u8::from_str_radix(from_utf8(&bytes[4..6]).unwrap(), 16).unwrap();
            self.set_color(
                (r as f32) / 255.0,
                (g as f32) / 255.0,
                (b as f32) / 255.0,
                1.0,
            );
        }
    }

    pub fn draw(&mut self, points: &[(f32, f32)]) {
        let shape = Shape::Polygon(Vec::from(points), self.color);
        self.shapes.push(shape);
    }

    pub fn draw_line(&mut self, x1: f32, y1: f32, x2: f32, y2: f32) {
        let shape = Shape::Line(x1, y1, x2, y2, self.color);
        self.shapes.push(shape);
    }

    pub fn draw_rect(&mut self, p1: (f32, f32), p2: (f32, f32)) {
        let shape = Shape::Polygon(
            vec![(p1.0, p1.1), (p1.0, p2.1), (p2.0, p2.1), (p2.0, p1.1)],
            self.color,
        );
        self.shapes.push(shape);
    }

    pub fn draw_circle(&mut self, x: f32, y: f32, rx: f32, ry: f32, step_size: u32) {
        let circle: Vec<(f32, f32)> = (0u32..360)
            .filter(|d| d % step_size == 0)
            .map(|d| {
                let r = (d as f32).to_radians();
                (r.cos() * rx, r.sin() * ry)
            })
            .collect();
        let shape = Shape::Polygon(circle, self.color);
        self.shapes.push(shape);
    }
}

fn main() {
    let mut window = Window::new("Hello World", 640, 480);

    window.start_loop(|app, delta| {
        app.clear();

        app.set_color_html("312");
        app.draw_rect((-0.5, -0.5), (0.5, 0.5));

        app.set_color_html("#033112");
        app.draw_rect((0.0, 0.0), (-1.0, -1.0));

        app.set_color(1.0, 0.0, 0.0, 1.0);
        app.draw_line(0.0, 0.0, 1.0, 1.0);

        app.set_color(0.0, 0.0, 1.0, 0.3);
        app.draw(&[(0.0, 0.0), (1.0, 1.0), (1.0, 0.0)]);

        app.set_color(0.0, 1.0, 0.0, 0.3);
        app.draw(&[(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)]);

        app.set_color(1.0, 0.0, 0.0, 0.3);
        app.draw_circle(0.0, 0.0, 0.75, 0.25, 10);

        support::Action::Continue
    });
}
<|endoftext|>


<commit_before>#![feature(advanced_slice_patterns, slice_patterns)]

extern crate git_together;

use std::env;
use std::process::Command;
use git_together::GitTogether;
use git_together::config::GitConfig;
use git_together::errors::*;

fn main() {
  run(|| {
    let config = GitConfig { namespace: "git-together".into() };
    let gt = GitTogether { config: config };

    let all_args: Vec<_> = env::args().skip(1).collect();
    let args: Vec<&str> = all_args.iter().map(String::as_ref).collect();

    match &args[..] {
      &["with", ref inits..] => {
        try!(gt.set_active(inits));
      }
      &[sub_cmd, ref rest..] if sub_cmd == "commit" => {
        let mut git_cmd = Command::new("git");
        let cmd = git_cmd.arg(sub_cmd).args(rest);
        let signoff = try!(gt.signoff(cmd));

        try!(signoff.status().chain_err(|| ""));
        try!(gt.rotate_active());
      }
      args => {
        try!(Command::new("git").args(args).status().chain_err(|| ""));
      }
    };

    Ok(())
  })
}

fn run<F>(f: F)
  where F: Fn() -> Result<()>
{
  if let Err(e) = f() {
    println!("{}", e);
    std::process::exit(1);
  }
}
<commit_msg>only rotate on success<commit_after>#![feature(advanced_slice_patterns, slice_patterns)]

extern crate git_together;

use std::env;
use std::process::Command;
use git_together::GitTogether;
use git_together::config::GitConfig;
use git_together::errors::*;

fn main() {
  run(|| {
    let config = GitConfig { namespace: "git-together".into() };
    let gt = GitTogether { config: config };

    let all_args: Vec<_> = env::args().skip(1).collect();
    let args: Vec<&str> = all_args.iter().map(String::as_ref).collect();

    match &args[..] {
      &["with", ref inits..] => {
        try!(gt.set_active(inits));
      }
      &[sub_cmd, ref rest..] if sub_cmd == "commit" => {
        let mut git_cmd = Command::new("git");
        let cmd = git_cmd.arg(sub_cmd).args(rest);
        let signoff = try!(gt.signoff(cmd));

        let status = try!(signoff.status().chain_err(|| ""));
        if status.success() {
          try!(gt.rotate_active());
        }
      }
      args => {
        try!(Command::new("git").args(args).status().chain_err(|| ""));
      }
    };

    Ok(())
  })
}

fn run<F>(f: F)
  where F: Fn() -> Result<()>
{
  if let Err(e) = f() {
    println!("{}", e);
    std::process::exit(1);
  }
}
<|endoftext|>


<commit_before>pub use self::pipe::Awakener;

/// Default *nix awakener implementation
mod pipe {
    use {io, Evented, Ready, Poll, PollOpt, Token};
    use deprecated::unix::{self, PipeReader, PipeWriter};
    use std::io::{Read, Write};

    /*
     *
     * ===== Awakener =====
     *
     */

    pub struct Awakener {
        reader: PipeReader,
        writer: PipeWriter,
    }

    impl Awakener {
        pub fn new() -> io::Result<Awakener> {
            let (rd, wr) = try!(unix::pipe());

            Ok(Awakener {
                reader: rd,
                writer: wr,
            })
        }

        pub fn wakeup(&self) -> io::Result<()> {
            match (&self.writer).write(b"0x01") {
                Ok(_) => Ok(()),
                Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        Ok(())
                    } else {
                        Err(e)
                    }
                }
            }
        }

        pub fn cleanup(&self) {
            let mut buf = [0; 128];

            loop {
                // Consume data until all bytes are purged
                match (&self.reader).read(&mut buf) {
                    Ok(i) if i > 0 => {},
                    _ => return,
                }
            }
        }

        fn reader(&self) -> &PipeReader {
            &self.reader
        }
    }

    impl Evented for Awakener {
        fn register(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
            self.reader().register(poll, token, interest, opts)
        }

        fn reregister(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
            self.reader().reregister(poll, token, interest, opts)
        }

        fn deregister(&self, poll: &Poll) -> io::Result<()> {
            self.reader().deregister(poll)
        }
    }
}
<commit_msg>unix awakener: send 1 byte instead of 4<commit_after>pub use self::pipe::Awakener;

/// Default *nix awakener implementation
mod pipe {
    use {io, Evented, Ready, Poll, PollOpt, Token};
    use deprecated::unix::{self, PipeReader, PipeWriter};
    use std::io::{Read, Write};

    /*
     *
     * ===== Awakener =====
     *
     */

    pub struct Awakener {
        reader: PipeReader,
        writer: PipeWriter,
    }

    impl Awakener {
        pub fn new() -> io::Result<Awakener> {
            let (rd, wr) = try!(unix::pipe());

            Ok(Awakener {
                reader: rd,
                writer: wr,
            })
        }

        pub fn wakeup(&self) -> io::Result<()> {
            match (&self.writer).write(&[1]) {
                Ok(_) => Ok(()),
                Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        Ok(())
                    } else {
                        Err(e)
                    }
                }
            }
        }

        pub fn cleanup(&self) {
            let mut buf = [0; 128];

            loop {
                // Consume data until all bytes are purged
                match (&self.reader).read(&mut buf) {
                    Ok(i) if i > 0 => {},
                    _ => return,
                }
            }
        }

        fn reader(&self) -> &PipeReader {
            &self.reader
        }
    }

    impl Evented for Awakener {
        fn register(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
            self.reader().register(poll, token, interest, opts)
        }

        fn reregister(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
            self.reader().reregister(poll, token, interest, opts)
        }

        fn deregister(&self, poll: &Poll) -> io::Result<()> {
            self.reader().deregister(poll)
        }
    }
}
<|endoftext|>


<commit_before>use crate::{event, poll, Interest, Registry, Token};

use std::io;
use std::os::unix::io::RawFd;

/// Adapter for [`RawFd`] providing an [`event::Source`] implementation.
///
/// `SourceFd` enables registering any type with an FD with [`Poll`].
///
/// While only implementations for TCP and UDP are provided, Mio supports
/// registering any FD that can be registered with the underlying OS selector.
/// `SourceFd` provides the necessary bridge.
///
/// Note that `SourceFd` takes a `&RawFd`. This is because `SourceFd` **does
/// not** take ownership of the FD. Specifically, it will not manage any
/// lifecycle related operations, such as closing the FD on drop. It is expected
/// that the `SourceFd` is constructed right before a call to
/// [`Registry::register`]. See the examples for more detail.
///
/// [`event::Source`]: ../event/trait.Source.html
/// [`Poll`]: ../struct.Poll.html
/// [`Registry::register`]: ../struct.Registry.html#method.register
///
/// # Examples
///
/// Basic usage.
///
#[cfg_attr(all(feature = "os-poll", feature = "net"), doc = "```")]
#[cfg_attr(not(all(feature = "os-poll", feature = "net")), doc = "```ignore")]
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use mio::{Interest, Poll, Token};
/// use mio::unix::SourceFd;
///
/// use std::os::unix::io::AsRawFd;
/// use std::net::TcpListener;
///
/// // Bind a std listener
/// let listener = TcpListener::bind("127.0.0.1:0")?;
///
/// let poll = Poll::new()?;
///
/// // Register the listener
/// poll.registry().register(
///     &mut SourceFd(&listener.as_raw_fd()),
///     Token(0),
///     Interest::READABLE)?;
/// #     Ok(())
/// # }
/// ```
///
/// Implementing [`event::Source`] for a custom type backed by a [`RawFd`].
///
#[cfg_attr(all(feature = "os-poll", feature = "os-ext"), doc = "```")]
#[cfg_attr(not(all(feature = "os-poll", feature = "os-ext")), doc = "```ignore")]
/// use mio::{event, Interest, Registry, Token};
/// use mio::unix::SourceFd;
///
/// use std::os::unix::io::RawFd;
/// use std::io;
///
/// # #[allow(dead_code)]
/// pub struct MyIo {
///     fd: RawFd,
/// }
///
/// impl event::Source for MyIo {
///     fn register(&mut self, registry: &Registry, token: Token, interests: Interest)
///         -> io::Result<()>
///     {
///         SourceFd(&self.fd).register(registry, token, interests)
///     }
///
///     fn reregister(&mut self, registry: &Registry, token: Token, interests: Interest)
///         -> io::Result<()>
///     {
///         SourceFd(&self.fd).reregister(registry, token, interests)
///     }
///
///     fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
///         SourceFd(&self.fd).deregister(registry)
///     }
/// }
/// ```
#[derive(Debug)]
pub struct SourceFd<'a>(pub &'a RawFd);

impl<'a> event::Source for SourceFd<'a> {
    fn register(
        &mut self,
        registry: &Registry,
        token: Token,
        interests: Interest,
    ) -> io::Result<()> {
        poll::selector(registry).register(*self.0, token, interests)
    }

    fn reregister(
        &mut self,
        registry: &Registry,
        token: Token,
        interests: Interest,
    ) -> io::Result<()> {
        poll::selector(registry).reregister(*self.0, token, interests)
    }

    fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
        poll::selector(registry).deregister(*self.0)
    }
}
<commit_msg>test(sys) Doctest imports `unix::SourceFd` which is behind the `os-ext` feature.<commit_after>use crate::{event, poll, Interest, Registry, Token};

use std::io;
use std::os::unix::io::RawFd;

/// Adapter for [`RawFd`] providing an [`event::Source`] implementation.
///
/// `SourceFd` enables registering any type with an FD with [`Poll`].
///
/// While only implementations for TCP and UDP are provided, Mio supports
/// registering any FD that can be registered with the underlying OS selector.
/// `SourceFd` provides the necessary bridge.
///
/// Note that `SourceFd` takes a `&RawFd`. This is because `SourceFd` **does
/// not** take ownership of the FD. Specifically, it will not manage any
/// lifecycle related operations, such as closing the FD on drop. It is expected
/// that the `SourceFd` is constructed right before a call to
/// [`Registry::register`]. See the examples for more detail.
///
/// [`event::Source`]: ../event/trait.Source.html
/// [`Poll`]: ../struct.Poll.html
/// [`Registry::register`]: ../struct.Registry.html#method.register
///
/// # Examples
///
/// Basic usage.
///
#[cfg_attr(
    all(feature = "os-poll", feature = "net", feature = "os-ext"),
    doc = "```"
)]
#[cfg_attr(
    not(all(feature = "os-poll", feature = "net", feature = "os-ext")),
    doc = "```ignore"
)]
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use mio::{Interest, Poll, Token};
/// use mio::unix::SourceFd;
///
/// use std::os::unix::io::AsRawFd;
/// use std::net::TcpListener;
///
/// // Bind a std listener
/// let listener = TcpListener::bind("127.0.0.1:0")?;
///
/// let poll = Poll::new()?;
///
/// // Register the listener
/// poll.registry().register(
///     &mut SourceFd(&listener.as_raw_fd()),
///     Token(0),
///     Interest::READABLE)?;
/// #     Ok(())
/// # }
/// ```
///
/// Implementing [`event::Source`] for a custom type backed by a [`RawFd`].
///
#[cfg_attr(all(feature = "os-poll", feature = "os-ext"), doc = "```")]
#[cfg_attr(not(all(feature = "os-poll", feature = "os-ext")), doc = "```ignore")]
/// use mio::{event, Interest, Registry, Token};
/// use mio::unix::SourceFd;
///
/// use std::os::unix::io::RawFd;
/// use std::io;
///
/// # #[allow(dead_code)]
/// pub struct MyIo {
///     fd: RawFd,
/// }
///
/// impl event::Source for MyIo {
///     fn register(&mut self, registry: &Registry, token: Token, interests: Interest)
///         -> io::Result<()>
///     {
///         SourceFd(&self.fd).register(registry, token, interests)
///     }
///
///     fn reregister(&mut self, registry: &Registry, token: Token, interests: Interest)
///         -> io::Result<()>
///     {
///         SourceFd(&self.fd).reregister(registry, token, interests)
///     }
///
///     fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
///         SourceFd(&self.fd).deregister(registry)
///     }
/// }
/// ```
#[derive(Debug)]
pub struct SourceFd<'a>(pub &'a RawFd);

impl<'a> event::Source for SourceFd<'a> {
    fn register(
        &mut self,
        registry: &Registry,
        token: Token,
        interests: Interest,
    ) -> io::Result<()> {
        poll::selector(registry).register(*self.0, token, interests)
    }

    fn reregister(
        &mut self,
        registry: &Registry,
        token: Token,
        interests: Interest,
    ) -> io::Result<()> {
        poll::selector(registry).reregister(*self.0, token, interests)
    }

    fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
        poll::selector(registry).deregister(*self.0)
    }
}
<|endoftext|>


<commit_before>//! LossyCounter implementation.

use std::collections::hash_map::{Entry, HashMap};
use std::hash::Hash;

#[derive(Debug)]
struct KnownEntry {
    f: usize,
    delta: usize,
}

/// TODO
///
/// # References
/// - ["Approximate Frequency Counts over Data Streams", Gurmeet S. Manku, Rajeev Motwani, 2002](https://www.vldb.org/conf/2002/S10P03.pdf)
/// - [Wikipedia: Lossy Count Algorithm](https://en.wikipedia.org/wiki/Lossy_Count_Algorithm)
/// - ["Top K Frequent Items Algorithm", Zhipeng Jiang, 2017](https://zpjiang.me/2017/11/13/top-k-elementes-system-design/)
#[derive(Debug)]
pub struct LossyCounter<T>
where
    T: Clone + Eq + Hash,
{
    epsilon: f64,
    known: HashMap<T, KnownEntry>,
    n: usize,
    width: usize,
}

impl<T> LossyCounter<T>
where
    T: Clone + Eq + Hash,
{
    /// Creates new lossy counter so that for reported frequencies `f_e` it holds:
    ///
    /// ```text
    /// f <= f_e <= epsilon * n
    /// ```
    ///
    /// where `f` is the true frequency and `n` the number of data points seen so far.
    pub fn with_properties(epsilon: f64) -> Self {
        assert!(
            (epsilon > 0.) & (epsilon < 1.),
            "epsilon ({}) must be greater than 0 and smaller than 1",
            epsilon
        );

        Self {
            epsilon,
            known: HashMap::new(),
            n: 0,
            width: (1. / epsilon).ceil() as usize,
        }
    }

    /// Epsilon error.
    pub fn epsilon(&self) -> f64 {
        self.epsilon
    }

    /// Number of data points seen so far.
    pub fn n(&self) -> usize {
        self.n
    }

    /// Add new element to the counter.
    ///
    /// Reports, if the element was considered new (`true`) or not (`false`).
    pub fn add(&mut self, t: T) -> bool {
        // pre-inc, since "N denotes the current length of the stream"
        self.n += 1;

        let b_current = self.n / self.width + 1;

        // add new data
        let was_new = match self.known.entry(t) {
            Entry::Occupied(mut o) => {
                let mut value = o.get_mut();
                value.f += 1;
                false
            }
            Entry::Vacant(v) => {
                v.insert(KnownEntry {
                    f: 1,
                    delta: b_current - 1,
                });
                true
            }
        };

        // pruning
        if self.n % self.width == 0 {
            self.known = self
                .known
                .drain()
                .filter(|(_k, v)| v.f + v.delta > b_current)
                .collect();
        }

        was_new
    }

    /// Query elements for which, with their guessed frequency `f`, it holds:
    ///
    /// ```text
    /// f >= (threshold - epsilon) * n
    /// ```
    ///
    /// The order of the elements is undefined.
    pub fn query<'a>(&'a self, threshold: f64) -> impl 'a + Iterator<Item = T> {
        let bound = (((threshold - self.epsilon) * (self.n as f64)).ceil()).max(0.) as usize;
        self.known
            .iter()
            .filter(move |(_k, v)| v.f >= bound)
            .map(|(k, _v)| k)
            .cloned()
    }
}

#[cfg(test)]
mod tests {
    use super::LossyCounter;

    #[test]
    fn new() {
        let counter = LossyCounter::<u64>::with_properties(0.5);
        assert_eq!(counter.epsilon(), 0.5);
        assert_eq!(counter.n(), 0);
    }

    #[test]
    #[should_panic(expected = "epsilon (0) must be greater than 0 and smaller than 1")]
    fn new_panics_epsilon_0() {
        LossyCounter::<u64>::with_properties(0.);
    }

    #[test]
    #[should_panic(expected = "epsilon (1) must be greater than 0 and smaller than 1")]
    fn new_panics_epsilon_1() {
        LossyCounter::<u64>::with_properties(1.);
    }

    #[test]
    fn add() {
        let mut counter = LossyCounter::<u64>::with_properties(0.5);
        assert!(counter.add(13));
        assert_eq!(counter.n(), 1);
    }

    #[test]
    fn double_add() {
        let mut counter = LossyCounter::<u64>::with_properties(0.5);
        assert!(counter.add(13));
        assert!(!counter.add(13));
        assert_eq!(counter.n(), 2);
    }

    #[test]
    fn query_all() {
        let mut counter = LossyCounter::<u64>::with_properties(0.2);
        assert!(counter.add(13));
        assert!(counter.add(42));

        let mut data: Vec<u64> = counter.query(0.).collect();
        data.sort();
        assert_eq!(data, vec![13, 42]);
    }

    #[test]
    fn query_part() {
        let mut counter = LossyCounter::<u64>::with_properties(0.001);
        assert!(counter.add(13));
        assert!(!counter.add(13));
        assert!(counter.add(42));

        let mut data: Vec<u64> = counter.query(0.6).collect();
        data.sort();
        assert_eq!(data, vec![13]);
    }

    #[test]
    fn query_large() {
        let mut counter = LossyCounter::<u64>::with_properties(0.01);
        for i in 0..1000 {
            let j = i % 10;
            if j <= 6 {
                counter.add(i);
            } else {
                counter.add(j);
            }
        }

        let mut data: Vec<u64> = counter.query(0.02).collect();
        data.sort();
        assert_eq!(data, vec![7, 8, 9]);
    }
}
<commit_msg>lossycounter: docs<commit_after>//! LossyCounter implementation.

use std::collections::hash_map::{Entry, HashMap};
use std::hash::Hash;

#[derive(Debug)]
struct KnownEntry {
    f: usize,
    delta: usize,
}

/// A LossyCounter is a data structure that memorizes the most frequent elements in data stream.
///
/// # Examples
/// ```
/// use pdatastructs::topk::lossycounter::LossyCounter;
///
/// // set up filter
/// let epsilon = 0.01;  // error threshold
/// let mut lc = LossyCounter::with_properties(epsilon);
///
/// // add some data
/// for i in 0..1000 {
///     let x = i % 10;
///     let y = if x < 4 {
///         0
///     } else if x < 7 {
///         1
///     } else {
///         x
///     };
///     lc.add(y);
/// }
///
/// // later
/// let threshold = 0.2;
/// let mut elements: Vec<u64> = lc.query(threshold).collect();
/// elements.sort();  // normalize order for testing purposes
/// assert_eq!(elements, vec![0, 1]);
/// ```
///
/// # Applications
/// - getting a fixed number of most common example of a large data set
/// - detect hotspots / very common events
///
/// # How It Works
/// The LossyCounter is initialized with an relative error bound `epsilon`. Depending on that, a
/// window size will be set. A window is the number of elements after which the counter will be
/// pruned.
///
/// ## Insertion
/// If the element is unknown (i.e. it was never seen before or was already pruned), it will be
/// stored with a frequency of 1. Also, the current window index will be stored alongside.
///
/// ```text
/// window size    = 4
///
///
/// insert(a):
///              n = 1
/// current window = 1
///
/// +---------+-------+-----------+
/// | element | delta | frequency |
/// +=========+=======+===========+
/// |       a |     0 |         1 |  <-- inserted
/// +---------+-------+-----------+
///
///
/// insert(b):
///              n = 2
/// current window = 1
///
/// +---------+-------+-----------+
/// | element | delta | frequency |
/// +=========+=======+===========+
/// |       a |     0 |         1 |
/// |       b |     0 |         1 |  <-- inserted
/// +---------+-------+-----------+
/// ```
///
/// If the element is know, the counter will be increased by 1.
///
/// ```text
/// window size    = 4
///
///
/// insert(a):
///              n = 3
/// current window = 1
///
/// +---------+-------+-----------+
/// | element | delta | frequency |
/// +=========+=======+===========+
/// |       a |     0 |         2 |  <-- incremented
/// |       b |     0 |         1 |
/// +---------+-------+-----------+
///
///
/// insert(a):
///              n = 4
/// current window = 1
///
/// +---------+-------+-----------+
/// | element | delta | frequency |
/// +=========+=======+===========+
/// |       a |     0 |         3 |  <-- incremented
/// |       b |     0 |         1 |
/// +---------+-------+-----------+
/// ```
///
/// If the window ends, pruning takes place. Elements will only be kept if their recorded frequency
/// plus the window index stored with them (i.e. the index they where recorded first) is at least
/// as large as the current window index. So elements that where not seen for a while will slowly
/// be kicked out of the counter, hence the name "Lossy Counter". In other words: an element will
/// only stay in the counter if it was seen more often than the number of windows since it was
/// inserted (i.e. number of windows plus 1).
///
/// ```text
/// window size    = 4
///
///
/// prune:
///              n = 4
/// current window = 1
///
/// +---------+-------+-----------+
/// | element | delta | frequency |
/// +=========+=======+===========+
/// |       a |     0 |         2 |
/// |       b |     0 |         1 |  <-- remove
/// +---------+-------+-----------+
///
/// +---------+-------+-----------+
/// | element | delta | frequency |
/// +=========+=======+===========+
/// |       a |     0 |         2 |
/// +---------+-------+-----------+
/// ```
///
/// ## Query
/// Given a relative threshold, all elements will be returned for which the following holds:
///
/// ```text
/// f >= (threshold - epsilon) * n
/// ```
///
/// # See Also
/// - `std::collections::HashSet`: has a false positive rate of 0%, but also needs to store all
///   elements
/// - `pdatastructs::topk::cmsheap::CMSHeap`: uses a different approach to solve the same problem
///
/// # References
/// - ["Approximate Frequency Counts over Data Streams", Gurmeet S. Manku, Rajeev Motwani, 2002](https://www.vldb.org/conf/2002/S10P03.pdf)
/// - [Wikipedia: Lossy Count Algorithm](https://en.wikipedia.org/wiki/Lossy_Count_Algorithm)
/// - ["Top K Frequent Items Algorithm", Zhipeng Jiang, 2017](https://zpjiang.me/2017/11/13/top-k-elementes-system-design/)
#[derive(Debug)]
pub struct LossyCounter<T>
where
    T: Clone + Eq + Hash,
{
    epsilon: f64,
    known: HashMap<T, KnownEntry>,
    n: usize,
    width: usize,
}

impl<T> LossyCounter<T>
where
    T: Clone + Eq + Hash,
{
    /// Creates new lossy counter so that for reported frequencies `f_e` it holds:
    ///
    /// ```text
    /// f <= f_e <= epsilon * n
    /// ```
    ///
    /// where `f` is the true frequency and `n` the number of data points seen so far.
    pub fn with_properties(epsilon: f64) -> Self {
        assert!(
            (epsilon > 0.) & (epsilon < 1.),
            "epsilon ({}) must be greater than 0 and smaller than 1",
            epsilon
        );

        Self {
            epsilon,
            known: HashMap::new(),
            n: 0,
            width: (1. / epsilon).ceil() as usize,
        }
    }

    /// Epsilon error.
    pub fn epsilon(&self) -> f64 {
        self.epsilon
    }

    /// Number of data points seen so far.
    pub fn n(&self) -> usize {
        self.n
    }

    /// Add new element to the counter.
    ///
    /// Reports, if the element was considered new (`true`) or not (`false`).
    pub fn add(&mut self, t: T) -> bool {
        // pre-inc, since "N denotes the current length of the stream"
        self.n += 1;

        let at_window_end = self.n % self.width == 0;
        let b_current = self.n / self.width + if at_window_end { 0 } else { 1 };

        // add new data
        let was_new = match self.known.entry(t) {
            Entry::Occupied(mut o) => {
                let mut value = o.get_mut();
                value.f += 1;
                false
            }
            Entry::Vacant(v) => {
                v.insert(KnownEntry {
                    f: 1,
                    delta: b_current - 1,
                });
                true
            }
        };

        // pruning
        if at_window_end {
            self.known = self
                .known
                .drain()
                .filter(|(_k, v)| v.f + v.delta > b_current)
                .collect();
        }

        was_new
    }

    /// Query elements for which, with their guessed frequency `f`, it holds:
    ///
    /// ```text
    /// f >= (threshold - epsilon) * n
    /// f > epsilon * n
    /// ```
    ///
    /// The order of the elements is undefined.
    pub fn query<'a>(&'a self, threshold: f64) -> impl 'a + Iterator<Item = T> {
        let bound = (((threshold - self.epsilon) * (self.n as f64)).ceil()).max(0.) as usize;
        self.known
            .iter()
            .filter(move |(_k, v)| v.f >= bound)
            .map(|(k, _v)| k)
            .cloned()
    }
}

#[cfg(test)]
mod tests {
    use super::LossyCounter;

    #[test]
    fn new() {
        let counter = LossyCounter::<u64>::with_properties(0.5);
        assert_eq!(counter.epsilon(), 0.5);
        assert_eq!(counter.n(), 0);
    }

    #[test]
    #[should_panic(expected = "epsilon (0) must be greater than 0 and smaller than 1")]
    fn new_panics_epsilon_0() {
        LossyCounter::<u64>::with_properties(0.);
    }

    #[test]
    #[should_panic(expected = "epsilon (1) must be greater than 0 and smaller than 1")]
    fn new_panics_epsilon_1() {
        LossyCounter::<u64>::with_properties(1.);
    }

    #[test]
    fn add() {
        let mut counter = LossyCounter::<u64>::with_properties(0.5);
        assert!(counter.add(13));
        assert_eq!(counter.n(), 1);
    }

    #[test]
    fn double_add() {
        let mut counter = LossyCounter::<u64>::with_properties(0.5);
        assert!(counter.add(13));
        assert!(!counter.add(13));
        assert_eq!(counter.n(), 2);
    }

    #[test]
    fn query_all() {
        let mut counter = LossyCounter::<u64>::with_properties(0.2);
        assert!(counter.add(13));
        assert!(counter.add(42));

        let mut data: Vec<u64> = counter.query(0.).collect();
        data.sort();
        assert_eq!(data, vec![13, 42]);
    }

    #[test]
    fn query_part() {
        let mut counter = LossyCounter::<u64>::with_properties(0.001);
        assert!(counter.add(13));
        assert!(!counter.add(13));
        assert!(counter.add(42));

        let mut data: Vec<u64> = counter.query(0.6).collect();
        data.sort();
        assert_eq!(data, vec![13]);
    }

    #[test]
    fn query_large() {
        let mut counter = LossyCounter::<u64>::with_properties(0.01);
        for i in 0..1000 {
            let j = i % 10;
            if j <= 6 {
                counter.add(i);
            } else {
                counter.add(j);
            }
        }

        let mut data: Vec<u64> = counter.query(0.02).collect();
        data.sort();
        assert_eq!(data, vec![7, 8, 9]);
    }
}
<|endoftext|>


<commit_before>//!
//! Desync pipes provide a way to generate and process streams via a `Desync` object
//!

use super::desync::*;

use futures::*;
use futures::executor;
use futures::executor::Spawn;

use std::sync::*;
use std::result::Result;

lazy_static! {
    /// The shared queue where we monitor for updates to the active pipe streams
    static ref PIPE_MONITOR: PipeMonitor = PipeMonitor::new();
}

///
/// Pipes a stream into a desync object. Whenever an item becomes available on the stream, the
/// processing function is called asynchronously with the item that was received.
///
/// Piping a stream to a `Desync` like this will cause it to start executing: ie, this is
/// similar to calling `executor::spawn(stream)`, except that the stream will immediately
/// start draining into the `Desync` object.
///
pub fn pipe_in<Core, S, ProcessFn>(desync: Arc<Desync<Core>>, stream: S, process: ProcessFn)
where   Core:       'static+Send,
        S:          'static+Send+Stream,
        S::Item:    Send,
        S::Error:   Send,
        ProcessFn:  'static+Send+FnMut(&mut Core, Result<S::Item, S::Error>) -> () {

    // Need a mutable version of the stream
    let mut stream = stream;

    // Wrap the process fn up so we can call it asynchronously
    // (it doesn't really need to be in a mutex as it's only called by our object but we need to make it pass Rust's checks and we don't have a way to specify this at the moment)
    let process = Arc::new(Mutex::new(process));

    // Poll the stream on the poll thread
    PIPE_MONITOR.monitor(move || {
        loop {
            // Read the current status of the stream
            let process     = Arc::clone(&process);
            let next        = stream.poll();

            match next {
                // Just wait if the stream is not ready
                Ok(Async::NotReady) => { return Ok(Async::NotReady); },

                // Stream returned a value
                Ok(Async::Ready(Some(next))) => {
                    // Process the value on the stream
                    desync.async(move |core| {
                        let mut process = process.lock().unwrap();
                        let process     = &mut *process;
                        process(core, Ok(next));
                    });
                },

                // Stream returned an error
                Err(e) => {
                    // Process the error on the stream
                    desync.async(move |core| {
                        let mut process = process.lock().unwrap();
                        let process     = &mut *process;
                        process(core, Err(e));
                    });
                },

                // Stream finished
                Ok(Async::Ready(None)) => { return Ok(Async::Ready(())); }
            }
        }
    });
}

/*
///
/// Pipes a stream into this object. Whenever an item becomes available on the stream, the
/// processing function is called asynchronously with the item that was received. The
/// return value is placed onto the output stream.
///
pub fn pipe<Core, S, Output, OutputErr, ProcessFn>(desync: Arc<Desync<Core>>, stream: S, process: ProcessFn) -> Box<dyn Stream<Item=Output, Error=OutputErr>>
where   Core:       'static+Send,
        S:          'static+Send+Stream,
        S::Item:    Send,
        S::Error:   Send,
        Output:     Send,
        OutputErr:  Send,
        ProcessFn:  'static+Send+FnMut(&mut Core, Result<S::Item, S::Error>) -> Result<Output, OutputErr> {
    unimplemented!()
}
*/

///
/// The main polling component for that implements the stream pipes
///
struct PipeMonitor {
}

///
/// Provides the 'Notify' interface for a polling function with a particular ID
///
struct PipeNotify<PollFn: Send> {
    next_poll: Arc<Desync<Option<Spawn<PollFn>>>>
}

impl PipeMonitor {
    ///
    /// Creates a new poll thread
    ///
    pub fn new() -> PipeMonitor {
        PipeMonitor {
        }
    }

    ///
    /// Performs a polling operation on a poll
    ///
    fn poll<PollFn>(this_poll: &mut Option<Spawn<PollFn>>, next_poll: Arc<Desync<Option<Spawn<PollFn>>>>)
    where PollFn: 'static+Send+Future<Item=(), Error=()> {
        // If the polling function exists...
        if let Some(mut poll) = this_poll.take() {
            // Create a notification
            let notify = PipeNotify {
                next_poll: next_poll
            };
            let notify = Arc::new(notify);

            // Poll the function
            let poll_result = poll.poll_future_notify(&notify, 0);

            // Keep the polling function alive if it has not finished yet
            if poll_result != Ok(Async::Ready(())) {
                // The take() call means that the polling won't continue unless we pass it forward like this
                *this_poll = Some(poll);
            }
        }
    }

    ///
    /// Adds a polling function to the current thread. It will be called using the futures
    /// notification system (ie, can call things like the stream poll function)
    ///
    pub fn monitor<PollFn>(&self, poll_fn: PollFn)
    where PollFn: 'static+Send+FnMut() -> Poll<(), ()> {
        // Turn the polling function into a future (it will complete when monitoring is complete)
        let poll_fn     = future::poll_fn(poll_fn);

        // Spawn it with an executor
        let poll_fn     = executor::spawn(poll_fn);

        // Create a desync object for polling
        let poll_fn     = Arc::new(Desync::new(Some(poll_fn)));
        let next_poll   = Arc::clone(&poll_fn);

        // Perform the initial polling
        poll_fn.sync(move |poll_fn| Self::poll(poll_fn, next_poll));
    }
}

impl<PollFn> executor::Notify for PipeNotify<PollFn>
where PollFn: 'static+Send+Future<Item=(), Error=()> {
    fn notify(&self, _id: usize) {
        // Poll the future whenever we're notified
        let next_poll = Arc::clone(&self.next_poll);
        self.next_poll.async(move |poll_fn| PipeMonitor::poll(poll_fn, next_poll));
    }
}
<commit_msg>With the new way that monitors work, we can run the processing function in 'sync' mode rather than desync<commit_after>//!
//! Desync pipes provide a way to generate and process streams via a `Desync` object
//!

use super::desync::*;

use futures::*;
use futures::executor;
use futures::executor::Spawn;

use std::sync::*;
use std::result::Result;

lazy_static! {
    /// The shared queue where we monitor for updates to the active pipe streams
    static ref PIPE_MONITOR: PipeMonitor = PipeMonitor::new();
}

///
/// Pipes a stream into a desync object. Whenever an item becomes available on the stream, the
/// processing function is called asynchronously with the item that was received.
///
/// Piping a stream to a `Desync` like this will cause it to start executing: ie, this is
/// similar to calling `executor::spawn(stream)`, except that the stream will immediately
/// start draining into the `Desync` object.
///
pub fn pipe_in<Core, S, ProcessFn>(desync: Arc<Desync<Core>>, stream: S, process: ProcessFn)
where   Core:       'static+Send,
        S:          'static+Send+Stream,
        S::Item:    Send,
        S::Error:   Send,
        ProcessFn:  'static+Send+FnMut(&mut Core, Result<S::Item, S::Error>) -> () {

    // Need a mutable version of the stream
    let mut stream = stream;

    // Wrap the process fn up so we can call it asynchronously
    // (it doesn't really need to be in a mutex as it's only called by our object but we need to make it pass Rust's checks and we don't have a way to specify this at the moment)
    let process = Arc::new(Mutex::new(process));

    // Poll the stream on the poll thread
    PIPE_MONITOR.monitor(move || {
        loop {
            // Read the current status of the stream
            let process     = Arc::clone(&process);
            let next        = stream.poll();

            match next {
                // Just wait if the stream is not ready
                Ok(Async::NotReady) => { return Ok(Async::NotReady); },

                // Stream returned a value
                Ok(Async::Ready(Some(next))) => {
                    // Process the value on the stream
                    desync.sync(move |core| {
                        let mut process = process.lock().unwrap();
                        let process     = &mut *process;
                        process(core, Ok(next));
                    });
                },

                // Stream returned an error
                Err(e) => {
                    // Process the error on the stream
                    desync.sync(move |core| {
                        let mut process = process.lock().unwrap();
                        let process     = &mut *process;
                        process(core, Err(e));
                    });
                },

                // Stream finished
                Ok(Async::Ready(None)) => { return Ok(Async::Ready(())); }
            }
        }
    });
}

/*
///
/// Pipes a stream into this object. Whenever an item becomes available on the stream, the
/// processing function is called asynchronously with the item that was received. The
/// return value is placed onto the output stream.
///
pub fn pipe<Core, S, Output, OutputErr, ProcessFn>(desync: Arc<Desync<Core>>, stream: S, process: ProcessFn) -> Box<dyn Stream<Item=Output, Error=OutputErr>>
where   Core:       'static+Send,
        S:          'static+Send+Stream,
        S::Item:    Send,
        S::Error:   Send,
        Output:     Send,
        OutputErr:  Send,
        ProcessFn:  'static+Send+FnMut(&mut Core, Result<S::Item, S::Error>) -> Result<Output, OutputErr> {
    unimplemented!()
}
*/

///
/// The main polling component for that implements the stream pipes
///
struct PipeMonitor {
}

///
/// Provides the 'Notify' interface for a polling function with a particular ID
///
struct PipeNotify<PollFn: Send> {
    next_poll: Arc<Desync<Option<Spawn<PollFn>>>>
}

impl PipeMonitor {
    ///
    /// Creates a new poll thread
    ///
    pub fn new() -> PipeMonitor {
        PipeMonitor {
        }
    }

    ///
    /// Performs a polling operation on a poll
    ///
    fn poll<PollFn>(this_poll: &mut Option<Spawn<PollFn>>, next_poll: Arc<Desync<Option<Spawn<PollFn>>>>)
    where PollFn: 'static+Send+Future<Item=(), Error=()> {
        // If the polling function exists...
        if let Some(mut poll) = this_poll.take() {
            // Create a notification
            let notify = PipeNotify {
                next_poll: next_poll
            };
            let notify = Arc::new(notify);

            // Poll the function
            let poll_result = poll.poll_future_notify(&notify, 0);

            // Keep the polling function alive if it has not finished yet
            if poll_result != Ok(Async::Ready(())) {
                // The take() call means that the polling won't continue unless we pass it forward like this
                *this_poll = Some(poll);
            }
        }
    }

    ///
    /// Adds a polling function to the current thread. It will be called using the futures
    /// notification system (ie, can call things like the stream poll function)
    ///
    pub fn monitor<PollFn>(&self, poll_fn: PollFn)
    where PollFn: 'static+Send+FnMut() -> Poll<(), ()> {
        // Turn the polling function into a future (it will complete when monitoring is complete)
        let poll_fn     = future::poll_fn(poll_fn);

        // Spawn it with an executor
        let poll_fn     = executor::spawn(poll_fn);

        // Create a desync object for polling
        let poll_fn     = Arc::new(Desync::new(Some(poll_fn)));
        let next_poll   = Arc::clone(&poll_fn);

        // Perform the initial polling
        poll_fn.sync(move |poll_fn| Self::poll(poll_fn, next_poll));
    }
}

impl<PollFn> executor::Notify for PipeNotify<PollFn>
where PollFn: 'static+Send+Future<Item=(), Error=()> {
    fn notify(&self, _id: usize) {
        // Poll the future whenever we're notified
        let next_poll = Arc::clone(&self.next_poll);
        self.next_poll.async(move |poll_fn| PipeMonitor::poll(poll_fn, next_poll));
    }
}
<|endoftext|>


<commit_before>//
// FlightVars
// Copyright (c) 2015, 2016 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::io;
use std::net;
use std::sync::mpsc;
use std::thread;

use comm::Transport;
use proto;
use proto::ProtocolRead;

pub struct Port {
    thread: thread::JoinHandle<()>
}

impl Port {
    fn new<T, P>(trans: T, proto_read: P, chan: mpsc::Sender<proto::Message>) -> Port
    where T: Transport + Send + 'static,
          P: ProtocolRead<T::Input> + Send + 'static,
          P::IntoIter: Send {
        Port { thread: spawn_port_listener(trans, proto_read, chan) }
    }
}

fn spawn_port_listener<T, P>(
    mut trans: T, proto_read: P, chan: mpsc::Sender<proto::Message>) -> thread::JoinHandle<()>
where T: Transport + Send + 'static,
      P: ProtocolRead<T::Input> + Send + 'static,
      P::IntoIter: Send {
    thread::spawn(move || {
        loop {
            match trans.wait_conn() {
                Ok((r, _)) => {
                    let input = proto_read.iter_from(r);
                    let _reader = spawn_port_reader(input, chan.clone());
                },
                Err(_) => return,
            }
        }
    })
}

fn spawn_port_reader<I>(input: I, chan: mpsc::Sender<proto::Message>) -> thread::JoinHandle<()>
where I: IntoIterator<Item=proto::Message> + Send + 'static {
    thread::spawn(move|| {
        for msg in input.into_iter() {
            chan.send(msg).unwrap();
        }
    })
}

fn oacsp_tcp_port<A>(addr: A, incoming: mpsc::Sender<proto::Message>) -> io::Result<Port>
where A: net::ToSocketAddrs {
    let trans = try!(net::TcpListener::bind(addr));
    let proto = proto::oacsp();
    Ok(Port::new(trans, proto, incoming))
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::sync::mpsc;

    use comm;
    use proto;

    use super::*;

    struct FakeTransport {
        connections: Vec<(mpsc::Receiver<proto::Message>, ())>
    }

    impl FakeTransport {
        fn new(input: mpsc::Receiver<proto::Message>) -> FakeTransport {
            FakeTransport {
                connections: vec![(input, ())]
            }
        }
    }

    struct FakeShutdownHandler;

    impl comm::ShutdownHandle for FakeShutdownHandler {
        fn shutdown(self) {}
    }

    impl comm::Transport for FakeTransport {
        type Input = mpsc::Receiver<proto::Message>;
        type Output = ();
        type Shutdown = FakeShutdownHandler;

        fn wait_conn(&mut self) -> io::Result<(mpsc::Receiver<proto::Message>, ())> {
            self.connections.pop().ok_or(io::Error::new(io::ErrorKind::ConnectionReset, ""))
        }

        fn shutdown_handle(&mut self) -> FakeShutdownHandler { FakeShutdownHandler }
    }

    #[test]
    fn should_receive_from_port() {
        let (net_tx, net_rx) = mpsc::channel();
        let (port_tx, port_rx) = mpsc::channel();
        net_tx.send(proto::Message::Open).unwrap();
        let transport = FakeTransport::new(net_rx);
        let _port = Port::new(transport, proto::id_proto(), port_tx);
        assert_eq!(proto::Message::Open, port_rx.recv().unwrap());
    }
}
<commit_msg>Integrate transport shutdown in port<commit_after>//
// FlightVars
// Copyright (c) 2015, 2016 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::io;
use std::net;
use std::sync::mpsc;
use std::thread;

use comm;
use comm::Transport;
use proto;
use proto::ProtocolRead;

pub struct Port<S: comm::ShutdownHandle> {
    port_listener: thread::JoinHandle<()>,
    shutdown: S
}

impl<S: comm::ShutdownHandle> Port<S> {
    fn new<T, P>(trans: T, proto_read: P, chan: mpsc::Sender<proto::Message>) -> Port<S>
    where T: Transport<Shutdown=S> + Send + 'static,
          P: ProtocolRead<T::Input> + Send + 'static,
          P::IntoIter: Send {
        let mut trans = trans;
        let shutdown = trans.shutdown_handle();
        Port {
            port_listener: spawn_port_listener(trans, proto_read, chan),
            shutdown: shutdown
        }
    }

    fn shutdown(self) {
        self.shutdown.shutdown();
        self.port_listener.join().unwrap();
    }
}

fn spawn_port_listener<T, P>(
    mut trans: T, proto_read: P, chan: mpsc::Sender<proto::Message>) -> thread::JoinHandle<()>
where T: Transport + Send + 'static,
      P: ProtocolRead<T::Input> + Send + 'static,
      P::IntoIter: Send {
    thread::spawn(move || {
        loop {
            match trans.wait_conn() {
                Ok((r, _)) => {
                    let input = proto_read.iter_from(r);
                    let _reader = spawn_port_reader(input, chan.clone());
                },
                Err(_) => return,
            }
        }
    })
}

fn spawn_port_reader<I>(input: I, chan: mpsc::Sender<proto::Message>) -> thread::JoinHandle<()>
where I: IntoIterator<Item=proto::Message> + Send + 'static {
    thread::spawn(move|| {
        for msg in input.into_iter() {
            chan.send(msg).unwrap();
        }
    })
}

fn oacsp_tcp_port<A>(addr: A, incoming: mpsc::Sender<proto::Message>) -> io::Result<Port<comm::tcp::TcpShutdownHandler>>
where A: net::ToSocketAddrs {
    let trans = try!(net::TcpListener::bind(addr));
    let proto = proto::oacsp();
    Ok(Port::new(trans, proto, incoming))
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::sync::mpsc;

    use comm;
    use proto;

    use super::*;

    struct FakeTransport {
        connections: Vec<(mpsc::Receiver<proto::Message>, ())>
    }

    impl FakeTransport {
        fn new(input: mpsc::Receiver<proto::Message>) -> FakeTransport {
            FakeTransport {
                connections: vec![(input, ())]
            }
        }
    }

    struct FakeShutdownHandler;

    impl comm::ShutdownHandle for FakeShutdownHandler {
        fn shutdown(self) {}
    }

    impl comm::Transport for FakeTransport {
        type Input = mpsc::Receiver<proto::Message>;
        type Output = ();
        type Shutdown = FakeShutdownHandler;

        fn wait_conn(&mut self) -> io::Result<(mpsc::Receiver<proto::Message>, ())> {
            self.connections.pop().ok_or(io::Error::new(io::ErrorKind::ConnectionReset, ""))
        }

        fn shutdown_handle(&mut self) -> FakeShutdownHandler { FakeShutdownHandler }
    }

    #[test]
    fn should_receive_from_port() {
        let (net_tx, net_rx) = mpsc::channel();
        let (port_tx, port_rx) = mpsc::channel();
        net_tx.send(proto::Message::Open).unwrap();
        let transport = FakeTransport::new(net_rx);
        let port = Port::new(transport, proto::id_proto(), port_tx);
        assert_eq!(proto::Message::Open, port_rx.recv().unwrap());
        port.shutdown();
    }
}
<|endoftext|>


<commit_before>use std::time::SystemTime;

const PI: f64 = 3.141592654;
pub const RAND_MAX: f64 = 2147483647.0;

pub enum Style {
    PMrand,
    Gauss,
    BMrand,
    Marsaglia,
    Lazy,
    Crand,
}

pub struct Rand {
    style: Style,
    seed: i64,
    attachment: Vec<f64>,
}

impl Rand {
    /// Is used to create a new random sequence core
    pub fn new(style: Style) -> Self {
        Rand {
            style: style,
            seed: 1,
            attachment: Vec::new(),
        }
    }

    /// Is used to generate a fixed sequence
    pub fn srand(&mut self, seed: i64) {
        self.seed = seed;
    }

    /// Is used to set random seed
    pub fn lazy_srand(&mut self) {
        let sys_time = SystemTime::now();
        let foo_string = format!("{:?}", sys_time);
        let mut seed: i64 = 0;
        let mut flag = false;
        for num in foo_string.chars() {
            match num {
                e @ '0'...'9' => {
                    flag = true;
                    seed = seed * 10 + (e as u8 - 48) as i64;
                    if seed >= i32::max_value() as i64 {
                        break;
                    }
                }
                _ => {
                    if flag {
                        break;
                    }
                }
            }
        }
        if seed > 0 {
            match self.style {
                Style::Lazy | Style::PMrand => self.seed = seed,
                Style::Crand => self.seed = 1,
                _ => self.seed = seed >> 32,
            }
        } else {
            self.seed = 1;
        }
    }

    pub fn get_rand(&mut self) -> f64 {
        match self.style {
            Style::PMrand => {
                self.seed = Rand::pmrand(self.seed, 48271);
                self.seed as f64 / RAND_MAX.abs()
            }
            Style::Gauss => (Rand::gauss(&mut self.seed, 25) / RAND_MAX).abs(),
            Style::BMrand => (Rand::bmrand(&mut self.seed, &mut self.attachment) / RAND_MAX).abs(),
            Style::Marsaglia => {
                (Rand::marsaglia(&mut self.seed, &mut self.attachment) / RAND_MAX).abs()
            }
            Style::Crand => (Rand::crand(&mut self.seed) as f64 / RAND_MAX).abs(),
            _ => {
                self.seed = Rand::lazy(self.seed);
                (self.seed as f64 / RAND_MAX).abs()
            }
        }
    }

    fn pmrand(seed: i64, a: i64) -> i64 {
        let m = RAND_MAX as i64;
        let q = m / a;
        let r = m % a;
        let hi = seed / q;
        let lo = seed % q;
        let test = a * lo - r * hi;
        if test > 0 { test } else { test + m }
    }

    fn gauss(seed: &mut i64, nsum: i64) -> f64 {
        let mut x = 0.0;
        for _ in 0..nsum {
            *seed = Rand::pmrand(*seed, 48271);
            x += *seed as f64 / RAND_MAX;
        }
        x -= nsum as f64 / 2.0;
        x /= (nsum as f64 / 12.0).sqrt();
        x
    }

    fn bmrand(seed: &mut i64, attachment: &mut Vec<f64>) -> f64 {
        // FIXME: value assigned to `z` is never read
        #[allow(unused_assignments)]
        let mut z = 0.0;
        if attachment.len() == 0 {
            attachment.push(0.0);
            attachment.push(0.0);
            attachment.push(0.0);
        }
        if attachment[2] == 0.0 {
            *seed = Rand::pmrand(*seed, 48271);
            attachment[0] = (*seed as f64 + 1.0) / (RAND_MAX + 2.0);
            *seed = Rand::pmrand(*seed, 48271);
            attachment[1] = *seed as f64 / (RAND_MAX + 1.0);
            z = (2.0 * PI * attachment[1]).sin();
        } else {
            z = (2.0 * PI * attachment[1]).cos();
        }
        z *= (-2.0 * attachment[0].log(10.0)).sqrt();
        attachment[2] = 1.0 - attachment[2];
        z
    }

    fn marsaglia(seed: &mut i64, attachment: &mut Vec<f64>) -> f64 {
        // FIXME: value assigned to `x` is never read
        #[allow(unused_assignments)]
        let mut x = 0.0;
        if attachment.len() == 0 {
            attachment.push(0.0);
            attachment.push(0.0);
            attachment.push(0.0);
            attachment.push(0.0);
        }
        if attachment[3] == 0.0 {
            loop {
                *seed = Rand::pmrand(*seed, 48271);
                let u1 = *seed as f64 / RAND_MAX;
                *seed = Rand::pmrand(*seed, 48271);
                let u2 = *seed as f64 / RAND_MAX;
                attachment[0] = 2.0 * u1 - 1.0;
                attachment[1] = 2.0 * u2 - 1.0;
                attachment[2] = attachment[0] * attachment[0] + attachment[1] * attachment[1];
                if attachment[2] < 1.0 && attachment[2] != 0.0 {
                    break;
                }
            }
            x = attachment[0] * (-2.0 * attachment[2].log(10.0) / attachment[2]);
        } else {
            x = attachment[1] * (-2.0 * attachment[2].log(10.0) / attachment[2]);
        }
        attachment[3] = 1.0 - attachment[3];
        x
    }

    fn lazy(seed: i64) -> i64 {
        Rand::pmrand(seed, 16807)
    }

    fn crand(seed: &mut i64) -> i64 {
        *seed = *seed * 1103515245 + 12345;
        (*seed >> 16) & (RAND_MAX as i64)
    }
}

/// A macro that generates random numbers
///
/// #Example
///
/// ```Rust
/// #[macro_use]
/// extern crate xiangyun;
/// use xiangyun::{Rand, Style};
/// fn main() {
///     println!("Style::Lazy");
///     let foo = rand!(2);
///     println!("{}, {}", foo[0], foo[1]);
///     println!("Style::PMrand");
///     let foo = rand!(Style::PMrand, 2);
///     println!("{}, {}", foo[0], foo[1]);
///     println!("Style::Gauss");
///     let foo = rand!(Style::Gauss, 2);
///     println!("{}, {}", foo[0], foo[1]);
/// }
/// ```
#[macro_export]
macro_rules! rand {
    () => {{
        let mut foo = Rand::new(Style::Lazy);
        foo.lazy_srand();
        foo.get_rand()
    }};
    ($num: expr) => {{
        let mut foo = Rand::new(Style::Lazy);
        let mut bar: Vec<f64> = Vec::new();
        foo.lazy_srand();
        for _ in 0..$num {
            bar.push(foo.get_rand());
        }
        bar
    }};
    ($style: path) => {{
        let mut foo = Rand::new($style);
        foo.lazy_srand();
        foo.get_rand()
    }};
    ($style: path, $num: expr) => {{
        let mut foo = Rand::new($style);
        let mut bar: Vec<f64> = Vec::new();
        foo.lazy_srand();
        for _ in 0..$num {
            bar.push(foo.get_rand());
        }
        bar
    }};
}
<commit_msg>Update<commit_after>use std::time::SystemTime;

const PI: f64 = 3.141592654;
pub const RAND_MAX: f64 = 2147483647.0;

pub enum Style {
    PMrand,
    Gauss,
    BMrand,
    Marsaglia,
    Lazy,
    Crand,
}

pub struct Rand {
    style: Style,
    seed: i64,
    attachment: Vec<f64>,
}

impl Rand {
    /// Is used to create a new random sequence core
    pub fn new(style: Style) -> Self {
        Rand {
            style: style,
            seed: 1,
            attachment: Vec::new(),
        }
    }

    /// Is used to generate a fixed sequence
    pub fn srand(&mut self, seed: i64) {
        self.seed = seed;
    }

    /// Is used to set random seed
    pub fn lazy_srand(&mut self) {
        let sys_time = SystemTime::now();
        let foo_string = format!("{:?}", sys_time);
        let mut seed: i64 = 0;
        let mut flag = false;
        for num in foo_string.chars() {
            match num {
                e @ '0'...'9' => {
                    flag = true;
                    seed = seed * 10 + (e as u8 - 48) as i64;
                    if seed >= i32::max_value() as i64 {
                        break;
                    }
                }
                _ => {
                    if flag {
                        break;
                    }
                }
            }
        }
        if seed > 0 {
            match self.style {
                Style::Lazy | Style::PMrand => self.seed = seed,
                Style::Crand => self.seed = 1,
                _ => self.seed = seed >> 32,
            }
        } else {
            self.seed = 1;
        }
    }

    pub fn get_rand(&mut self) -> f64 {
        match self.style {
            Style::PMrand => {
                self.seed = Rand::pmrand(self.seed, 48271);
                self.seed as f64 / RAND_MAX.abs()
            }
            Style::Gauss => (Rand::gauss(&mut self.seed, 25) / RAND_MAX).abs(),
            Style::BMrand => (Rand::bmrand(&mut self.seed, &mut self.attachment) / RAND_MAX).abs(),
            Style::Marsaglia => {
                (Rand::marsaglia(&mut self.seed, &mut self.attachment) / RAND_MAX).abs()
            }
            Style::Crand => (Rand::crand(&mut self.seed) as f64 / RAND_MAX).abs(),
            _ => {
                self.seed = Rand::lazy(self.seed);
                (self.seed as f64 / RAND_MAX).abs()
            }
        }
    }

    pub fn lazy_rand(&mut self, min: i64, max: i64) -> i64 {
        min + (self.get_rand() * (max - min + 1) as f64) as i64
    }

    pub fn lazy_randf(&mut self, min: f64, max: f64) -> f64 {
        min + self.get_rand() * (max - min + 1.0)
    }

    fn pmrand(seed: i64, a: i64) -> i64 {
        let m = RAND_MAX as i64;
        let q = m / a;
        let r = m % a;
        let hi = seed / q;
        let lo = seed % q;
        let test = a * lo - r * hi;
        if test > 0 { test } else { test + m }
    }

    fn gauss(seed: &mut i64, nsum: i64) -> f64 {
        let mut x = 0.0;
        for _ in 0..nsum {
            *seed = Rand::pmrand(*seed, 48271);
            x += *seed as f64 / RAND_MAX;
        }
        x -= nsum as f64 / 2.0;
        x /= (nsum as f64 / 12.0).sqrt();
        x
    }

    fn bmrand(seed: &mut i64, attachment: &mut Vec<f64>) -> f64 {
        // FIXME: value assigned to `z` is never read
        #[allow(unused_assignments)]
        let mut z = 0.0;
        if attachment.len() == 0 {
            attachment.push(0.0);
            attachment.push(0.0);
            attachment.push(0.0);
        }
        if attachment[2] == 0.0 {
            *seed = Rand::pmrand(*seed, 48271);
            attachment[0] = (*seed as f64 + 1.0) / (RAND_MAX + 2.0);
            *seed = Rand::pmrand(*seed, 48271);
            attachment[1] = *seed as f64 / (RAND_MAX + 1.0);
            z = (2.0 * PI * attachment[1]).sin();
        } else {
            z = (2.0 * PI * attachment[1]).cos();
        }
        z *= (-2.0 * attachment[0].log(10.0)).sqrt();
        attachment[2] = 1.0 - attachment[2];
        z
    }

    fn marsaglia(seed: &mut i64, attachment: &mut Vec<f64>) -> f64 {
        // FIXME: value assigned to `x` is never read
        #[allow(unused_assignments)]
        let mut x = 0.0;
        if attachment.len() == 0 {
            attachment.push(0.0);
            attachment.push(0.0);
            attachment.push(0.0);
            attachment.push(0.0);
        }
        if attachment[3] == 0.0 {
            loop {
                *seed = Rand::pmrand(*seed, 48271);
                let u1 = *seed as f64 / RAND_MAX;
                *seed = Rand::pmrand(*seed, 48271);
                let u2 = *seed as f64 / RAND_MAX;
                attachment[0] = 2.0 * u1 - 1.0;
                attachment[1] = 2.0 * u2 - 1.0;
                attachment[2] = attachment[0] * attachment[0] + attachment[1] * attachment[1];
                if attachment[2] < 1.0 && attachment[2] != 0.0 {
                    break;
                }
            }
            x = attachment[0] * (-2.0 * attachment[2].log(10.0) / attachment[2]);
        } else {
            x = attachment[1] * (-2.0 * attachment[2].log(10.0) / attachment[2]);
        }
        attachment[3] = 1.0 - attachment[3];
        x
    }

    fn lazy(seed: i64) -> i64 {
        Rand::pmrand(seed, 16807)
    }

    fn crand(seed: &mut i64) -> i64 {
        *seed = *seed * 1103515245 + 12345;
        (*seed >> 16) & (RAND_MAX as i64)
    }
}

/// A macro that generates random numbers
///
/// #Example
///
/// ```Rust
/// #[macro_use]
/// extern crate xiangyun;
/// use xiangyun::{Rand, Style};
/// fn main() {
///     println!("Style::Lazy");
///     let foo = rand!(2);
///     println!("{}, {}", foo[0], foo[1]);
///     println!("Style::PMrand");
///     let foo = rand!(Style::PMrand, 2);
///     println!("{}, {}", foo[0], foo[1]);
///     println!("Style::Gauss");
///     let foo = rand!(Style::Gauss, 2);
///     println!("{}, {}", foo[0], foo[1]);
/// }
/// ```
#[macro_export]
macro_rules! rand {
    () => {{
        let mut foo = Rand::new(Style::Lazy);
        foo.lazy_srand();
        foo.get_rand()
    }};
    ($num: expr) => {{
        let mut foo = Rand::new(Style::Lazy);
        let mut bar: Vec<f64> = Vec::new();
        foo.lazy_srand();
        for _ in 0..$num {
            bar.push(foo.get_rand());
        }
        bar
    }};
    ($style: path) => {{
        let mut foo = Rand::new($style);
        foo.lazy_srand();
        foo.get_rand()
    }};
    ($style: path, $num: expr) => {{
        let mut foo = Rand::new($style);
        let mut bar: Vec<f64> = Vec::new();
        foo.lazy_srand();
        for _ in 0..$num {
            bar.push(foo.get_rand());
        }
        bar
    }};
}
<|endoftext|>


<commit_before>//! Parse hoon source into AST twig

use std::str;
use std::str::FromStr;
use num::bigint::BigUint;

use twig::{self, Twig, Rune, Odor};

pub type ParseResult<'a, T> = Result<(&'a [u8], T), &'a [u8]>;

/// Parse Hoon source code into a Twig AST.
///
/// Return trailing input after a successful parse along with the resulting
/// Twig. Return trailing input after the point of failed parse on error.
pub fn ream(mut input: &[u8]) -> ParseResult<Twig> {
    // Eat initial space
    loop {
        if let Ok((tail, _)) = space_or_comment(input) {
            input = tail;
        } else {
            break;
        }
    }
    twig(input)
}

fn twig(input: &[u8]) -> ParseResult<Twig> {
    use twig::Rune::*;

    if let Ok(x) = atom(input) { return Ok(x); }

    // Just crunch through the whole set of rune data and look for all the
    // ones that look like they can be parsed naively.
    for i in twig::RUNES.iter() {
        if i.rune.is_regular() && i.rune.glyph().is_some() {
            if let Ok(x) = rune(input, i.rune) { return Ok(x); }
        }
    }

    Err(input)
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum Form {
    Tall,
    Wide
}

fn rune<'a>(input: &'a[u8], rune: Rune) -> ParseResult<'a, Twig> {
    assert!(rune.is_regular(), "Can't use standard parser on this type of rune!");
    let glyph = rune.glyph().expect("Trying to parse an unprintable rune");
    let (input, form) = try!(rune_start(input, &glyph));
    let (input, args) = try!(rune_args(input, form, rune.arity()));
    Ok((input, Twig::Cell(box Twig::Rune(rune), box args)))
}

/// Parse the start of a rune with the given glyph and determine if the rune
/// is in wide form (.*(p q) or tall form (.*  p  q).
fn rune_start<'a>(input: &'a[u8], glyph: &str) -> ParseResult<'a, Form> {
    assert!(glyph.len() == 2, "Rune isn't 2 characters");
    let (mut tail, _) = try!(tag(input, glyph));

    if let Ok((tail, _)) = tag(tail, "(") {
        return Ok((tail, Form::Wide));
    }

    if let Ok((tail, _)) = gap(tail) {
        return Ok((tail, Form::Tall));
    }

    Err(input)
}

fn rune_args(input: &[u8], form: Form, n: usize) -> ParseResult<Twig> {
    assert!(n > 0);
    if n == 1 {
        let (input, p) = try!(twig(input));
        let (input, _) = try!(rune_end(input, form));
        Ok((input, p))
    } else {
        let (input, p) = try!(twig(input));
        let (input, _) = try!(rune_sep(input, form));
        let (input, ps) = try!(rune_args(input, form, n - 1));
        Ok((input, Twig::Cell(box p, box ps)))
    }
}

fn rune_sep(input: &[u8], form: Form) -> ParseResult<&[u8]> {
    match form {
        Form::Tall => gap(input),
        Form::Wide => tag(input, " ")
    }
}

fn rune_end(input: &[u8], form: Form) -> ParseResult<&[u8]> {
    match form {
        Form::Tall => Ok((input, &input[..0])),
        Form::Wide => tag(input, ")")
    }
}

fn atom(input: &[u8]) -> ParseResult<Twig> {
    if let Ok((tail, num)) = ud(input) {
        Ok((tail,
            Twig::Cell(
                box Twig::Rune(Rune::dtzy),
                box Twig::Atom(Odor::ud, num))))
    } else {
        Err(input)
    }
}

/// Unsigned decimal
fn ud(input: &[u8]) -> ParseResult<BigUint> {
    let mut idx = 0;
    let mut num = String::new();
    for c in input.iter() {
        if *c >= '0' as u8 && *c <= '9' as u8 {
            num.push(*c as char);
        }
        else if idx > 0 && *c == '.' as u8 {
            // Ignore separator dots.
            // We're lazy, so we let them show up in any pattern after the
            // initial digit instead of insisting that they group the digits
            // in sized groups.
        } else {
            if idx == 0 { return Err(input); }
            break;
        }
        idx += 1;
    }

    Ok((&input[idx..], FromStr::from_str(&num).unwrap()))
}

fn space_or_comment(input: &[u8]) -> ParseResult<()> {
    let mut tail = input;
    loop {
        if let Ok((t, _)) = comment(tail) {
            tail = t
        } else {
            if tail.len() == 0 {
                break;
            } else if is_whitespace(tail[0]) {
                tail = &tail[1..];
            } else {
                break;
            }
        }
    }
    if tail == input {
        Err(input)
    } else {
        Ok((tail, ()))
    }
}

/// At least one newline or at least two spaces.
///
/// Used to separate tall forms in Hoon.
fn gap(input: &[u8]) -> ParseResult<&[u8]> {
    let mut spaces = 0;
    let mut idx = 0;
    for i in input.iter() {
        if *i == '\n' as u8 {
            spaces += 2;
        } else if is_whitespace(*i) {
            spaces += 1;
        } else {
            break;
        }

        idx += 1;
    }

    if spaces < 2 {
        Err(input)
    } else {
        Ok((&input[idx..], &input[0..idx]))
    }
}

fn comment(input: &[u8]) -> ParseResult<&[u8]> {
    let (input, _) = try!(tag(input, "::"));
    // XXX: The initial bit with the "::" won't make it to the return value.
    split_after(input, '\n' as u8)
}

fn is_whitespace(c: u8) -> bool {
    // Physical tabs not included. A physical tab in the code is a syntax
    // error.
    c == 0x10 || c == 0x13 || c == ' ' as u8
}

fn is_lowercase(c: u8) -> bool {
    c >= 'a' as u8 && c <= 'z' as u8
}

fn tag<'a>(input: &'a[u8], prefix: &str) -> ParseResult<'a, &'a [u8]> {
    let prefix = prefix.as_bytes();
    if input.len() < prefix.len() {
        return Err(input);
    }

    for (x, y) in prefix.iter().zip(input.iter()) {
        if x != y { return Err(input); }
    }

    Ok((&input[prefix.len()..], &input[0..prefix.len()]))
}

fn split_after(input: &[u8], c: u8) -> ParseResult<&[u8]> {
    let mut idx = 1;
    for i in input.iter() {
        if *i == c {
            break;
        }
        idx += 1;
    }
    println!("Split at {}", idx);
    Ok((&input[idx..], &input[0..idx]))
}
<commit_msg>Wing parsing<commit_after>//! Parse hoon source into AST twig

use std::str;
use std::str::FromStr;
use num::bigint::BigUint;

use twig::{self, Twig, Rune, Odor};

pub type ParseResult<'a, T> = Result<(&'a [u8], T), &'a [u8]>;

/// Parse Hoon source code into a Twig AST.
///
/// Return trailing input after a successful parse along with the resulting
/// Twig. Return trailing input after the point of failed parse on error.
pub fn ream(mut input: &[u8]) -> ParseResult<Twig> {
    // Eat initial space
    loop {
        if let Ok((tail, _)) = space_or_comment(input) {
            input = tail;
        } else {
            break;
        }
    }
    twig(input)
}

fn twig(input: &[u8]) -> ParseResult<Twig> {
    use twig::Rune::*;

    if let Ok(x) = atom(input) { return Ok(x); }
    if let Ok(x) = wing(input) { return Ok(x); }

    // Just crunch through the whole set of rune data and look for all the
    // ones that look like they can be parsed naively.
    for i in twig::RUNES.iter() {
        if i.rune.is_regular() && i.rune.glyph().is_some() {
            if let Ok(x) = rune(input, i.rune) { return Ok(x); }
        }
    }

    Err(input)
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum Form {
    Tall,
    Wide
}

fn rune<'a>(input: &'a[u8], rune: Rune) -> ParseResult<'a, Twig> {
    assert!(rune.is_regular(), "Can't use standard parser on this type of rune!");
    let glyph = rune.glyph().expect("Trying to parse an unprintable rune");
    let (input, form) = try!(rune_start(input, &glyph));
    let (input, args) = try!(rune_args(input, form, rune.arity()));
    Ok((input, Twig::Cell(box Twig::Rune(rune), box args)))
}

/// Parse the start of a rune with the given glyph and determine if the rune
/// is in wide form (.*(p q) or tall form (.*  p  q).
fn rune_start<'a>(input: &'a[u8], glyph: &str) -> ParseResult<'a, Form> {
    assert!(glyph.len() == 2, "Rune isn't 2 characters");
    let (mut tail, _) = try!(tag(input, glyph));

    if let Ok((tail, _)) = tag(tail, "(") {
        return Ok((tail, Form::Wide));
    }

    if let Ok((tail, _)) = gap(tail) {
        return Ok((tail, Form::Tall));
    }

    Err(input)
}

fn rune_args(input: &[u8], form: Form, n: usize) -> ParseResult<Twig> {
    assert!(n > 0);
    if n == 1 {
        let (input, p) = try!(twig(input));
        let (input, _) = try!(rune_end(input, form));
        Ok((input, p))
    } else {
        let (input, p) = try!(twig(input));
        let (input, _) = try!(rune_sep(input, form));
        let (input, ps) = try!(rune_args(input, form, n - 1));
        Ok((input, Twig::Cell(box p, box ps)))
    }
}

fn rune_sep(input: &[u8], form: Form) -> ParseResult<&[u8]> {
    match form {
        Form::Tall => gap(input),
        Form::Wide => tag(input, " ")
    }
}

fn rune_end(input: &[u8], form: Form) -> ParseResult<&[u8]> {
    match form {
        Form::Tall => Ok((input, &input[..0])),
        Form::Wide => tag(input, ")")
    }
}

fn atom(input: &[u8]) -> ParseResult<Twig> {
    if let Ok((tail, num)) = ud(input) {
        Ok((tail,
            Twig::Cell(
                box Twig::Rune(Rune::dtzy),
                box Twig::Atom(Odor::ud, num))))
    } else {
        Err(input)
    }
}

/// Unsigned decimal
fn ud(input: &[u8]) -> ParseResult<BigUint> {
    let mut idx = 0;
    let mut num = String::new();
    for c in input.iter() {
        if *c >= '0' as u8 && *c <= '9' as u8 {
            num.push(*c as char);
        }
        else if idx > 0 && *c == '.' as u8 {
            // Ignore separator dots.
            // We're lazy, so we let them show up in any pattern after the
            // initial digit instead of insisting that they group the digits
            // in sized groups.
        } else {
            if idx == 0 { return Err(input); }
            break;
        }
        idx += 1;
    }

    Ok((&input[idx..], FromStr::from_str(&num).unwrap()))
}

fn wing(input: &[u8]) -> ParseResult<Twig> {
    // TODO: Dotted forms expanding to multi-term wings.
    let (input, term) = try!(term(input));
    let s = str::from_utf8(term).unwrap().to_string();
    Ok((input, Twig::Cell(box Twig::Rune(Rune::cnzz), box Twig::Wing(vec![s]))))
}

fn term(input: &[u8]) -> ParseResult<&[u8]> {
    let mut idx = 0;
    for i in input.iter() {
        if idx == 0 && *i == '$' as u8 {
            // Special $
            if input.len() > 1 && !is_ident_middle(input[1]) {
                // Can't have something like $foo.
                return Err(input);
            }
            idx += 1;
            break;
        }

        if idx == 0 && !is_ident_start(*i) { break; }

        if idx > 0 && !is_ident_middle(*i) { break; }

        idx += 1;
    }

    if idx == 0 {
        Err(input)
    } else {
        Ok((&input[idx..], &input[..idx]))
    }
}

fn space_or_comment(input: &[u8]) -> ParseResult<()> {
    let mut tail = input;
    loop {
        if let Ok((t, _)) = comment(tail) {
            tail = t
        } else {
            if tail.len() == 0 {
                break;
            } else if is_whitespace(tail[0]) {
                tail = &tail[1..];
            } else {
                break;
            }
        }
    }
    if tail == input {
        Err(input)
    } else {
        Ok((tail, ()))
    }
}

/// At least one newline or at least two spaces.
///
/// Used to separate tall forms in Hoon.
fn gap(input: &[u8]) -> ParseResult<&[u8]> {
    let mut spaces = 0;
    let mut idx = 0;
    for i in input.iter() {
        if *i == '\n' as u8 {
            spaces += 2;
        } else if is_whitespace(*i) {
            spaces += 1;
        } else {
            break;
        }

        idx += 1;
    }

    if spaces < 2 {
        Err(input)
    } else {
        Ok((&input[idx..], &input[0..idx]))
    }
}

fn comment(input: &[u8]) -> ParseResult<&[u8]> {
    let (input, _) = try!(tag(input, "::"));
    // XXX: The initial bit with the "::" won't make it to the return value.
    split_after(input, '\n' as u8)
}

fn is_whitespace(c: u8) -> bool {
    // Physical tabs not included. A physical tab in the code is a syntax
    // error.
    c == 0x10 || c == 0x13 || c == ' ' as u8
}

fn is_lowercase(c: u8) -> bool {
    c >= 'a' as u8 && c <= 'z' as u8
}

fn is_numeric(c: u8) -> bool {
    c >= '0' as u8 && c <= '9' as u8
}

fn is_ident_start(c: u8) -> bool { is_lowercase(c) }

fn is_ident_middle(c: u8) -> bool { is_lowercase(c) || is_numeric(c) || c == '-' as u8 }

fn tag<'a>(input: &'a[u8], prefix: &str) -> ParseResult<'a, &'a [u8]> {
    let prefix = prefix.as_bytes();
    if input.len() < prefix.len() {
        return Err(input);
    }

    for (x, y) in prefix.iter().zip(input.iter()) {
        if x != y { return Err(input); }
    }

    Ok((&input[prefix.len()..], &input[0..prefix.len()]))
}

fn split_after(input: &[u8], c: u8) -> ParseResult<&[u8]> {
    let mut idx = 1;
    for i in input.iter() {
        if *i == c {
            break;
        }
        idx += 1;
    }
    Ok((&input[idx..], &input[0..idx]))
}
<|endoftext|>


<commit_before>

use std::fmt::{self, Display, Formatter};
use std::collections::VecDeque;

use itertools::*;

use self::Form::*;

/// Lexical program representation: untyped s-expressions.
#[derive(Debug, PartialEq, Clone)]
pub enum Form {
    /// A token, such as an identifier, number, or anything that isn't a `List`.
    Atom(String),
    /// A list of `Form`s, usually delimited by parentheses.
    List(VecDeque<Form>),
}

impl Form {
    /// Construct an Atom containing a String
    pub fn atom(s: String) -> Self {
        Atom(s)
    }
    /// Construct a list of forms
    pub fn list<I>(src: I) -> Self
        where I: IntoIterator<Item = Form>
    {
        List(src.into_iter().collect())
    }
    /// Construct a List form containing nothing
    pub fn empty_list() -> Self {
        List(VecDeque::new())
    }

    pub fn add_to_list(&mut self, item: Form) {
        match *self {
            Atom(_) => panic!(),
            List(ref mut l) => l.push_back(item)
        }
    }
}

impl Display for Form {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let s = match *self {
            Atom(ref s) => s.clone(),
            List(ref list) => format!("({})", list.iter().join(" ")),
        };
        write!(f, "{}", s)
    }
}
<commit_msg>Begin Ast<commit_after>

use std::fmt::{self, Display, Formatter};
use std::collections::VecDeque;

use itertools::*;

use self::Form::*;

/// Lexical program representation: untyped s-expressions.
#[derive(Debug, PartialEq, Clone)]
pub enum Form {
    /// A token, such as an identifier, number, or anything that isn't a `List`.
    Atom(String),
    /// A list of `Form`s, usually delimited by parentheses.
    List(VecDeque<Form>),
}

impl Form {
    /// Construct an Atom containing a String
    pub fn atom(s: String) -> Self {
        Atom(s)
    }
    /// Construct a list of forms
    pub fn list<I>(src: I) -> Self
        where I: IntoIterator<Item = Form>
    {
        List(src.into_iter().collect())
    }
    /// Construct a List form containing nothing
    pub fn empty_list() -> Self {
        List(VecDeque::new())
    }

    pub fn add_to_list(&mut self, item: Form) {
        match *self {
            Atom(_) => panic!(),
            List(ref mut l) => l.push_back(item)
        }
    }
}

impl Display for Form {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let s = match *self {
            Atom(ref s) => s.clone(),
            List(ref list) => format!("({})", list.iter().join(" ")),
        };
        write!(f, "{}", s)
    }
}

// AST node types for each special form, right? see wiki diagram for AST
// some nodes contain type info (or at least slots for it)
// a Form -> AST fn
// do modules go in the AST?
enum Ast {
    // Special Forms
    Def,
    Quote,
    Fn,
    Macro,
    Cond,
    //? Let,

}

// constraint graph? each edge has a vector of contraints relating to the nodes it connects?
// might need to be a hypergraph...

// also Identifier vs Literal vs FnCall
// Literals map to FnCalls? (macros?) (compiler macros?)

// so what are the special forms?

/*

environment:
Reader env.
Analyzer env.

*/
<|endoftext|>