<commit_before>use std::sync::atomic::{self, AtomicUsize, Ordering};

/// Indexes used for triple buffer access
/// TODO: Switch to i8 / AtomicI8 once they are stable
type TripleBufferIndex = usize;
type AtomicTripleBufferIndex = AtomicUsize;

/// A triple buffer, suitable for continuously updating a shared data block
/// in a thread-safe and non-blocking fashion when there is only one producer
/// and one consumer of the data.
struct TripleBuffer<T: Clone> {
    /// Storage for triple-buffered data
    storage: [T; 3],

    /// Index of the write buffer (private to the writer)
    write_idx: TripleBufferIndex,

    /// Index of the back-buffer (shared between reader and writer)
    back_idx: AtomicTripleBufferIndex,

    /// Index of the read buffer (private to the reader)
    read_idx: TripleBufferIndex,

    /// Index of the most up-to-date buffer (written by writer, read by reader)
    last_idx: AtomicTripleBufferIndex,
}

// Implementation of the triple buffer
impl<T: Clone> TripleBuffer<T> {
    /// Create a new triple buffer with some initial data value
    fn new(initial: T) -> Self {
        TripleBuffer {
            storage: [initial.clone(), initial.clone(), initial.clone()],
            write_idx: 0,
            back_idx: AtomicTripleBufferIndex::new(1),
            read_idx: 2,
            last_idx: AtomicTripleBufferIndex::new(2),
        }
    }

    /// Write a new value into the triple buffer
    fn write(&mut self, value: T) {
        // Select a write buffer that we have exclusive access to
        let active_idx = self.write_idx;

        // Move the input value into the write buffer
        self.storage[active_idx] = value;

        // Swap the back buffer and the write buffer. This makes the new data
        // block available to the reader and gives us a new buffer to write to.
        self.write_idx = self.back_idx.swap(active_idx, Ordering::Relaxed);

        // Allow the reader to detect and synchronize with this update
        self.last_idx.store(active_idx, Ordering::Release);
    }

    /// Access the latest value from the triple buffer
    fn read(&mut self) -> &T {
        // Check which buffer was last written to
        let last_idx = self.last_idx.load(Ordering::Relaxed);

        // Update the read buffer if an update has occured since the last read
        if self.read_idx != last_idx {
            // Synchronize with the writer's updates
            atomic::fence(Ordering::Acquire);

            // Swap the back buffer and the read buffer. We get exclusive read
            // access to the data, and the writer gets a new back buffer.
            self.read_idx = self.back_idx.swap(self.read_idx, Ordering::Relaxed);
        }

        // Access data from the current read buffer
        &self.storage[self.read_idx]
    }
}

/// Unit tests for triple buffers
#[cfg(test)]
mod tests {
    /// Test that triple buffers are properly initialized
    #[test]
    fn test_init() {
        // Let's create a triple buffer
        let buf = ::TripleBuffer::new(42);

        // Cache atomic indices for convenience
        let back_idx = buf.back_idx.load(::Ordering::Relaxed);
        let last_idx = buf.last_idx.load(::Ordering::Relaxed);

        // Write, read and back-buffer indexes must be in range
        assert!(index_in_range(buf.read_idx));
        assert!(index_in_range(buf.write_idx));
        assert!(index_in_range(back_idx));

        // Write, read and back-buffer indexes must be distinct
        assert!(buf.read_idx != buf.write_idx);
        assert!(buf.read_idx != back_idx);
        assert!(buf.write_idx != back_idx);

        // Read buffer must be properly initialized
        assert!(buf.storage[buf.read_idx] == 42);

        // Last-written index must initially point to read buffer
        assert_eq!(last_idx, buf.read_idx);
    }

    /// Test that (sequentially) writing to a triple buffer works
    #[test]
    fn test_seq_write() {
        // Let's create a triple buffer
        let mut buf = ::TripleBuffer::new(false);

        // Back up initial state
        let init_storage = buf.storage.clone();
        let init_write_idx = buf.write_idx;
        let init_back_idx = buf.back_idx.load(::Ordering::Relaxed);
        let init_read_idx = buf.read_idx;

        // Perform a write
        buf.write(true);

        // Only the write buffer should have changed
        let mut expected_storage = init_storage.clone();
        expected_storage[init_write_idx] = true;
        assert_eq!(buf.storage, expected_storage);

        // Write index should point to the former back buffer
        assert_eq!(buf.write_idx, init_back_idx);

        // Back index should point to the former write buffer
        let new_back_idx = buf.back_idx.load(::Ordering::Relaxed);
        assert_eq!(new_back_idx, init_write_idx);

        // Read index should be unchanged
        assert_eq!(buf.read_idx, init_read_idx);

        // Last index should point to the newly written buffer
        let new_last_idx = buf.last_idx.load(::Ordering::Relaxed);
        assert_eq!(new_last_idx, init_write_idx);
    }

    // TODO: Check that (sequentially) reading from a triple buffer works
    // TODO: Check that concurrent reads and writes work

    /// Range check for triple buffer indexes
    #[allow(unused_comparisons)]
    fn index_in_range(idx: ::TripleBufferIndex) -> bool {
        (idx >= 0) & (idx <= 2)
    }
}

fn main() {
    println!("Hello, world!");

    let mut buf = TripleBuffer::new("Hello!");
    println!("Initial value is {}", buf.read());

    buf.write("World!");
    println!("New value is {}", buf.read())
}
<commit_msg>Added read test<commit_after>use std::sync::atomic::{self, AtomicUsize, Ordering};

/// Indexes used for triple buffer access
/// TODO: Switch to i8 / AtomicI8 once they are stable
type TripleBufferIndex = usize;
type AtomicTripleBufferIndex = AtomicUsize;

/// A triple buffer, suitable for continuously updating a shared data block
/// in a thread-safe and non-blocking fashion when there is only one producer
/// and one consumer of the data.
struct TripleBuffer<T: Clone> {
    /// Storage for triple-buffered data
    storage: [T; 3],

    /// Index of the write buffer (private to the writer)
    write_idx: TripleBufferIndex,

    /// Index of the back-buffer (shared between reader and writer)
    back_idx: AtomicTripleBufferIndex,

    /// Index of the read buffer (private to the reader)
    read_idx: TripleBufferIndex,

    /// Index of the most up-to-date buffer (written by writer, read by reader)
    last_idx: AtomicTripleBufferIndex,
}

// Implementation of the triple buffer
impl<T: Clone> TripleBuffer<T> {
    /// Create a new triple buffer with some initial data value
    fn new(initial: T) -> Self {
        TripleBuffer {
            storage: [initial.clone(), initial.clone(), initial.clone()],
            write_idx: 0,
            back_idx: AtomicTripleBufferIndex::new(1),
            read_idx: 2,
            last_idx: AtomicTripleBufferIndex::new(2),
        }
    }

    /// Write a new value into the triple buffer
    fn write(&mut self, value: T) {
        // Select a write buffer that we have exclusive access to
        let active_idx = self.write_idx;

        // Move the input value into the write buffer
        self.storage[active_idx] = value;

        // Swap the back buffer and the write buffer. This makes the new data
        // block available to the reader and gives us a new buffer to write to.
        self.write_idx = self.back_idx.swap(active_idx, Ordering::Relaxed);

        // Allow the reader to detect and synchronize with this update
        self.last_idx.store(active_idx, Ordering::Release);
    }

    /// Access the latest value from the triple buffer
    fn read(&mut self) -> &T {
        // Check which buffer was last written to
        let last_idx = self.last_idx.load(Ordering::Relaxed);

        // Update the read buffer if an update has occured since the last read
        if self.read_idx != last_idx {
            // Synchronize with the writer's updates
            atomic::fence(Ordering::Acquire);

            // Swap the back buffer and the read buffer. We get exclusive read
            // access to the data, and the writer gets a new back buffer.
            self.read_idx = self.back_idx.swap(self.read_idx, Ordering::Relaxed);
        }

        // Access data from the current read buffer
        &self.storage[self.read_idx]
    }
}

/// Unit tests for triple buffers
#[cfg(test)]
mod tests {
    /// Test that triple buffers are properly initialized
    #[test]
    fn test_init() {
        // Let's create a triple buffer
        let buf = ::TripleBuffer::new(42);

        // Cache atomic indices for convenience
        let back_idx = buf.back_idx.load(::Ordering::Relaxed);
        let last_idx = buf.last_idx.load(::Ordering::Relaxed);

        // Write, read and back-buffer indexes must be in range
        assert!(index_in_range(buf.read_idx));
        assert!(index_in_range(buf.write_idx));
        assert!(index_in_range(back_idx));

        // Write, read and back-buffer indexes must be distinct
        assert!(buf.read_idx != buf.write_idx);
        assert!(buf.read_idx != back_idx);
        assert!(buf.write_idx != back_idx);

        // Read buffer must be properly initialized
        assert!(buf.storage[buf.read_idx] == 42);

        // Last-written index must initially point to read buffer
        assert_eq!(last_idx, buf.read_idx);
    }

    /// Test that (sequentially) writing to a triple buffer works
    #[test]
    fn test_seq_write() {
        // Let's create a triple buffer
        let mut buf = ::TripleBuffer::new(false);

        // Back up initial state
        let init_storage = buf.storage.clone();
        let init_write_idx = buf.write_idx;
        let init_back_idx = buf.back_idx.load(::Ordering::Relaxed);
        let init_read_idx = buf.read_idx;

        // Perform a write
        buf.write(true);

        // Only the write buffer should have changed
        let mut expected_storage = init_storage.clone();
        expected_storage[init_write_idx] = true;
        assert_eq!(buf.storage, expected_storage);

        // Write index should point to the former back buffer
        assert_eq!(buf.write_idx, init_back_idx);

        // Back index should point to the former write buffer
        let new_back_idx = buf.back_idx.load(::Ordering::Relaxed);
        assert_eq!(new_back_idx, init_write_idx);

        // Read index should not change
        assert_eq!(buf.read_idx, init_read_idx);

        // Last index should point to the newly written buffer
        let new_last_idx = buf.last_idx.load(::Ordering::Relaxed);
        assert_eq!(new_last_idx, init_write_idx);
    }

    /// Check that (sequentially) reading from a triple buffer works
    #[test]
    fn test_seq_read() {
        // Let's create a triple buffer and write into it
        let mut buf = ::TripleBuffer::new(1.0);
        buf.write(4.2);

        // Test readout from dirty (freshly written) triple buffer
        {
            // Back up initial state
            let init_storage = buf.storage.clone();
            let init_write_idx = buf.write_idx;
            let init_read_idx = buf.read_idx;
            let init_last_idx = buf.last_idx.load(::Ordering::Relaxed);

            // Read from the buffer
            let result = *buf.read();

            // Output value should be correct
            assert_eq!(result, 4.2);

            // Storage should not change
            assert_eq!(buf.storage, init_storage);

            // Write index should not change
            assert_eq!(buf.write_idx, init_write_idx);

            // Back index should point to the former read buffer
            let new_back_idx = buf.back_idx.load(::Ordering::Relaxed);
            assert_eq!(new_back_idx, init_read_idx);

            // Read index should point to the last written index
            assert_eq!(buf.read_idx, init_last_idx);

            // Last index should not change
            let new_last_idx = buf.last_idx.load(::Ordering::Relaxed);
            assert_eq!(new_last_idx, init_last_idx);
        }

        // Test readout from clean (unchanged) triple buffer
        {
            // Back up initial state
            let init_storage = buf.storage.clone();
            let init_write_idx = buf.write_idx;
            let init_back_idx = buf.back_idx.load(::Ordering::Relaxed);
            let init_read_idx = buf.read_idx;
            let init_last_idx = buf.last_idx.load(::Ordering::Relaxed);

            // Read from the buffer
            let result = *buf.read();

            // Output value should be correct
            assert_eq!(result, 4.2);

            // Storage should not change
            assert_eq!(buf.storage, init_storage);

            // Write index should not change
            assert_eq!(buf.write_idx, init_write_idx);

            // Back index should not change
            let new_back_idx = buf.back_idx.load(::Ordering::Relaxed);
            assert_eq!(new_back_idx, init_back_idx);

            // Read index should not change
            assert_eq!(buf.read_idx, init_read_idx);

            // Last index should not change
            let new_last_idx = buf.last_idx.load(::Ordering::Relaxed);
            assert_eq!(new_last_idx, init_last_idx);
        }
    }

    // TODO: Check that concurrent reads and writes work

    /// Range check for triple buffer indexes
    #[allow(unused_comparisons)]
    fn index_in_range(idx: ::TripleBufferIndex) -> bool {
        (idx >= 0) & (idx <= 2)
    }
}

fn main() {
    println!("Hello, world!");

    let mut buf = TripleBuffer::new("Hello!");
    println!("Initial value is {}", buf.read());

    buf.write("World!");
    println!("New value is {}", buf.read())
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate docopt;
extern crate gitrev;

use docopt::Docopt;

const USAGE: &'static str = "
GITREV is a utility program that is meant to serve as a replacement for
SubWCRev.exe.

Usage:
    gitrev.exe <src-version-file> <dst-version-file>
    gitrev.exe (-h | --help)
    gitrev.exe --version

Options:
    -h --help   Prints this message.
    --version   Prints version.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_src_version_file: String,
    arg_dst_version_file: String,
}

fn main() {
    // Parse command line arguments
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
    let curr_rev = gitrev::git_describe().unwrap_or_else(|e| {
        println!("{}", e);
        ::std::process::exit(1);
    });
    let curr_branch = gitrev::git_branch().unwrap_or_else(|e| {
        println!("{}", e);
        ::std::process::exit(1);
    });
    let remote_url = gitrev::git_remote_url().unwrap_or_else(|e| {
        println!("{}", e);
        ::std::process::exit(1);
    });
    let build_time = gitrev::build_time().unwrap_or_else(|e| {
        println!("{}", e);
        ::std::process::exit(1);
    });
    println!("Current revision: {}", curr_rev);
    println!("Build time: {}", build_time);
    println!("Current branch: {}", curr_branch);
    println!("Remote url: {}", remote_url);
}
<commit_msg>Read in contents of the source file<commit_after>extern crate rustc_serialize;
extern crate docopt;
extern crate gitrev;

use docopt::Docopt;
use std::io::Read;
use std::fs::File;

const USAGE: &'static str = "
GITREV is a utility program that is meant to serve as a replacement for
SubWCRev.exe.

Usage:
    gitrev.exe <src-version-file> <dst-version-file>
    gitrev.exe (-h | --help)
    gitrev.exe --version

Options:
    -h --help   Prints this message.
    --version   Prints version.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_src_version_file: String,
    arg_dst_version_file: String,
}

fn main() {
    // Parse command line arguments
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
    let curr_rev = gitrev::git_describe().unwrap_or_else(|e| {
        println!("{}", e);
        ::std::process::exit(1);
    });
    let curr_branch = gitrev::git_branch().unwrap_or_else(|e| {
        println!("{}", e);
        ::std::process::exit(1);
    });
    let remote_url = gitrev::git_remote_url().unwrap_or_else(|e| {
        println!("{}", e);
        ::std::process::exit(1);
    });
    let build_time = gitrev::build_time().unwrap_or_else(|e| {
        println!("{}", e);
        ::std::process::exit(1);
    });
    println!("Current revision: {}", curr_rev);
    println!("Build time: {}", build_time);
    println!("Current branch: {}", curr_branch);
    println!("Remote url: {}", remote_url);

    let mut f = File::open(&args.arg_src_version_file).unwrap();
    let mut contents = String::new();
    f.read_to_string(&mut contents).unwrap();
    println!("Template contents:\n{}", contents);
}
<|endoftext|>


<commit_before>extern crate log;
extern crate env_logger;
#[macro_use]
extern crate structopt;
extern crate failure;
extern crate mdblog;

use std::env;
use std::path::{Path, PathBuf};
use structopt::StructOpt;
use mdblog::{Mdblog, Result, log_error};

#[derive(StructOpt, Debug)]
#[structopt(name = "mdblog")]
/// static site generator from markdown files
enum Opt {
    #[structopt(name = "init")]
    /// Initialize the blog directory layout
    Init {
        /// the blog directory name
        name: String,
    },
     #[structopt(name = "new")]
    /// Create a blog post
    New {
        #[structopt(short = "t", long = "tag", default_value = "blog")]
        /// Post tags
        tags: Vec<String>,
        #[structopt(parse(from_os_str))]
        /// Post path relative to blog `posts` directory
        path: PathBuf,
    },
    #[structopt(name = "build")]
    /// Build the blog static files
    Build,
    #[structopt(name = "serve")]
    /// Serve the blog, rebuild on change
    Serve {
        #[structopt(short = "p", long = "port", default_value = "5000")]
        /// Serve the blog at http://127.0.0.1:<port>
        port: u16,
    },
    #[structopt(name = "theme")]
    /// Blog theme operations
    Theme(SubCommandTheme),
}

#[derive(StructOpt, Debug)]
enum SubCommandTheme {
    #[structopt(name = "list")]
    /// list blog themes
    List,
    #[structopt(name = "new")]
    /// Create a new theme
    New {
        /// theme name
        name: String,
    },
     #[structopt(name = "delete")]
    /// Delete a theme
    Delete {
        /// theme name
        name: String,
    },
    #[structopt(name = "set")]
    /// Set blog use the theme
    Set {
        /// theme name
        name: String,
    },
}

fn main() {
    env_logger::Builder::new()
        .filter(None, log::LevelFilter::Info)
        .init();

    let opt = Opt::from_args();
    let res = match opt {
        Opt::Init {ref name} => init(name),
        Opt::New {ref tags, ref path} => new(path, tags),
        Opt::Build => build(),
        Opt::Serve { port } => serve(port),
        Opt::Theme(ref subcmd) => theme(subcmd),
    };

    if let Err(ref e) = res {
        log_error(e);
        std::process::exit(1);
    }
}

fn init(name: &str) -> Result<()> {
    let root_dir = env::current_dir()?.join(name);
    let mut mb = Mdblog::new(root_dir)?;
    mb.init()?;
    Ok(())
}

fn new(path: &Path, tags: &Vec<String>) -> Result<()> {
    let root_dir = env::current_dir()?;
    let mut mb = Mdblog::new(&root_dir)?;
    mb.load_customize_settings()?;
    mb.create_post(path, tags)?;
    Ok(())
}

fn build() -> Result<()> {
    let root_dir = env::current_dir()?;
    let mut mb = Mdblog::new(&root_dir)?;
    mb.load_customize_settings()?;
    mb.build()?;
    Ok(())
}

fn serve(port: u16) -> Result<()> {
    let root_dir = env::current_dir()?;
    let mut mb = Mdblog::new(&root_dir)?;
    mb.load_customize_settings()?;
    mb.serve(port)?;
    Ok(())
}

fn theme(cmd: &SubCommandTheme) -> Result<()> {
    let root_dir = env::current_dir()?;
    let mut mb = Mdblog::new(&root_dir)?;
    mb.load_customize_settings()?;

    match cmd {
        &SubCommandTheme::List => mb.list_blog_theme()?,
        &SubCommandTheme::New { ref name } => mb.create_blog_theme(name)?,
        &SubCommandTheme::Delete { ref name } => mb.delete_blog_theme(name)?,
        &SubCommandTheme::Set { ref name } => mb.set_blog_theme(name)?,
    }
    Ok(())
}
<commit_msg>change new subcommand tags flag default value to null string<commit_after>extern crate log;
extern crate env_logger;
#[macro_use]
extern crate structopt;
extern crate failure;
extern crate mdblog;

use std::env;
use std::path::{Path, PathBuf};
use structopt::StructOpt;
use mdblog::{Mdblog, Result, log_error};

#[derive(StructOpt, Debug)]
#[structopt(name = "mdblog")]
/// static site generator from markdown files
enum Opt {
    #[structopt(name = "init")]
    /// Initialize the blog directory layout
    Init {
        /// the blog directory name
        name: String,
    },
     #[structopt(name = "new")]
    /// Create a blog post
    New {
        #[structopt(short = "t", long = "tag", default_value = "")]
        /// Post tags
        tags: Vec<String>,
        #[structopt(parse(from_os_str))]
        /// Post path relative to blog `posts` directory
        path: PathBuf,
    },
    #[structopt(name = "build")]
    /// Build the blog static files
    Build,
    #[structopt(name = "serve")]
    /// Serve the blog, rebuild on change
    Serve {
        #[structopt(short = "p", long = "port", default_value = "5000")]
        /// Serve the blog at http://127.0.0.1:<port>
        port: u16,
    },
    #[structopt(name = "theme")]
    /// Blog theme operations
    Theme(SubCommandTheme),
}

#[derive(StructOpt, Debug)]
enum SubCommandTheme {
    #[structopt(name = "list")]
    /// list blog themes
    List,
    #[structopt(name = "new")]
    /// Create a new theme
    New {
        /// theme name
        name: String,
    },
     #[structopt(name = "delete")]
    /// Delete a theme
    Delete {
        /// theme name
        name: String,
    },
    #[structopt(name = "set")]
    /// Set blog use the theme
    Set {
        /// theme name
        name: String,
    },
}

fn main() {
    env_logger::Builder::new()
        .filter(None, log::LevelFilter::Info)
        .init();

    let opt = Opt::from_args();
    let res = match opt {
        Opt::Init {ref name} => init(name),
        Opt::New {ref tags, ref path} => new(path, tags),
        Opt::Build => build(),
        Opt::Serve { port } => serve(port),
        Opt::Theme(ref subcmd) => theme(subcmd),
    };

    if let Err(ref e) = res {
        log_error(e);
        std::process::exit(1);
    }
}

fn init(name: &str) -> Result<()> {
    let root_dir = env::current_dir()?.join(name);
    let mut mb = Mdblog::new(root_dir)?;
    mb.init()?;
    Ok(())
}

fn new(path: &Path, tags: &Vec<String>) -> Result<()> {
    let root_dir = env::current_dir()?;
    let mut mb = Mdblog::new(&root_dir)?;
    mb.load_customize_settings()?;
    mb.create_post(path, tags)?;
    Ok(())
}

fn build() -> Result<()> {
    let root_dir = env::current_dir()?;
    let mut mb = Mdblog::new(&root_dir)?;
    mb.load_customize_settings()?;
    mb.build()?;
    Ok(())
}

fn serve(port: u16) -> Result<()> {
    let root_dir = env::current_dir()?;
    let mut mb = Mdblog::new(&root_dir)?;
    mb.load_customize_settings()?;
    mb.serve(port)?;
    Ok(())
}

fn theme(cmd: &SubCommandTheme) -> Result<()> {
    let root_dir = env::current_dir()?;
    let mut mb = Mdblog::new(&root_dir)?;
    mb.load_customize_settings()?;

    match cmd {
        &SubCommandTheme::List => mb.list_blog_theme()?,
        &SubCommandTheme::New { ref name } => mb.create_blog_theme(name)?,
        &SubCommandTheme::Delete { ref name } => mb.delete_blog_theme(name)?,
        &SubCommandTheme::Set { ref name } => mb.set_blog_theme(name)?,
    }
    Ok(())
}
<|endoftext|>


<commit_before>extern crate fontconfig;
extern crate freetype;
extern crate libc;
extern crate glutin;
extern crate gl;
extern crate cgmath;
extern crate euclid;

mod list_fonts;
mod text;

use std::ffi::CString;
use std::mem::size_of;
use std::ptr;

use euclid::{Rect, Size2D, Point2D};

use libc::c_void;

use gl::types::*;

use cgmath::Matrix;

use text::RasterizedGlyph;

static TEXT_SHADER_V: &'static str = include_str!("../res/text.v.glsl");
static TEXT_SHADER_F: &'static str = include_str!("../res/text.f.glsl");

fn main() {
    let window = glutin::Window::new().unwrap();
    let (width, height) = window.get_inner_size_pixels().unwrap();
    unsafe {
        window.make_current()
    };

    unsafe {
        gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
        gl::Viewport(0, 0, width as i32, height as i32);
    }

    let rasterizer = text::Rasterizer::new();
    let glyph_j = rasterizer.get_glyph(180., 'J');

    let tex = AlphaTexture::new(
        glyph_j.width as i32,
        glyph_j.height as i32,
        glyph_j.buf.as_ptr() as *const _
    );

    unsafe {
        gl::Enable(gl::BLEND);
        gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
    }

    let mut vao: GLuint = 0;
    let mut vbo: GLuint = 0;
    let mut ebo: GLuint = 0;
    unsafe {
        gl::GenVertexArrays(1, &mut vao);
        gl::GenBuffers(1, &mut vbo);
        gl::GenBuffers(1, &mut ebo);
        gl::BindVertexArray(vao);

        gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
        gl::BufferData(
            gl::ARRAY_BUFFER,
            (size_of::<f32>() * 4 * 4) as GLsizeiptr,
            ptr::null(),
            gl::DYNAMIC_DRAW
        );

        let indices: [u32; 6] = [0, 1, 3,
                                 1, 2, 3];

        gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo);
        gl::BufferData(gl::ELEMENT_ARRAY_BUFFER,
                       6 * size_of::<u32>() as isize,
                       indices.as_ptr() as *const _,
                       gl::STATIC_DRAW);

        gl::EnableVertexAttribArray(0);
        gl::VertexAttribPointer(0, 4, gl::FLOAT, gl::FALSE, 4 * size_of::<f32>() as i32,
                                ptr::null());

        gl::BindBuffer(gl::ARRAY_BUFFER, 0);
        gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
        gl::BindVertexArray(0);
    }

    let program = ShaderProgram::new(width, height);

    for event in window.wait_events() {
        unsafe {
            gl::ClearColor(0.08, 0.08, 0.08, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
        }

        render(&program, &glyph_j, &tex, vbo, vao, ebo);

        window.swap_buffers();

        match event {
            glutin::Event::Closed => break,
            _ => ()
        }
    }
}

fn get_rect(glyph: &RasterizedGlyph, x: f32, y: f32) -> Rect<f32> {
    Rect::new(
        Point2D::new(x, y),
        Size2D::new(glyph.width as f32, glyph.height as f32)
    )
}

/// Render a character
fn render(program: &ShaderProgram, glyph: &RasterizedGlyph, tex: &AlphaTexture, vbo: GLuint,
          vao: GLuint, ebo: GLuint)
{
    program.activate();
    unsafe {
        // set color
        gl::Uniform3f(program.u_color, 1., 1., 0.5);
    }

    let rect = get_rect(glyph, 10.0, 10.0);

    // top right of character
    let vertices: [[f32; 4]; 4] = [
        [rect.max_x(), rect.max_y(), 1., 0.], // top-right
        [rect.max_x(), rect.min_y(), 1., 1.], // bottom-right
        [rect.min_x(), rect.min_y(), 0., 1.], // bottom-left
        [rect.min_x(), rect.max_y(), 0., 0.], // top-left
    ];

    unsafe {
        bind_mask_texture(tex.id);
        gl::BindVertexArray(vao);

        gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
        gl::BufferSubData(
            gl::ARRAY_BUFFER,
            0,
            (4 * 4 * size_of::<f32>()) as isize,
            vertices.as_ptr() as *const _
        );
        gl::BindBuffer(gl::ARRAY_BUFFER, 0);
        gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo);

        gl::DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_INT, ptr::null());
        gl::BindVertexArray(0);
        gl::BindTexture(gl::TEXTURE_2D, 0);
    }

    program.deactivate();
}

fn bind_mask_texture(id: u32) {
    unsafe {
        gl::ActiveTexture(gl::TEXTURE0);
        gl::BindTexture(gl::TEXTURE_2D, id);
    }
}

pub struct ShaderProgram {
    id: GLuint,
    /// projection matrix uniform
    u_projection: GLint,
    /// color uniform
    u_color: GLint,
}

impl ShaderProgram {
    pub fn activate(&self) {
        unsafe {
            gl::UseProgram(self.id);
        }
    }

    pub fn deactivate(&self) {
        unsafe {
            gl::UseProgram(0);
        }
    }

    pub fn new(width: u32, height: u32) -> ShaderProgram {
        let vertex_shader = ShaderProgram::create_vertex_shader();
        let fragment_shader = ShaderProgram::create_fragment_shader();
        let program = ShaderProgram::create_program(vertex_shader, fragment_shader);

        unsafe {
            gl::DeleteShader(vertex_shader);
            gl::DeleteShader(fragment_shader);
        }

        // get uniform locations
        let projection_str = CString::new("projection").unwrap();
        let color_str = CString::new("textColor").unwrap();

        let (projection, color) = unsafe {
            (
                gl::GetUniformLocation(program, projection_str.as_ptr()),
                gl::GetUniformLocation(program, color_str.as_ptr())
            )
        };

        assert!(projection != gl::INVALID_VALUE as i32);
        assert!(projection != gl::INVALID_OPERATION as i32);
        assert!(color != gl::INVALID_VALUE as i32);
        assert!(color != gl::INVALID_OPERATION as i32);

        let shader = ShaderProgram {
            id: program,
            u_projection: projection,
            u_color: color,
        };

        // set projection uniform
        let ortho = cgmath::ortho(0., width as f32, 0., height as f32, -1., 1.);
        let projection: [[f32; 4]; 4] = ortho.into();

        println!("width: {}, height: {}", width, height);

        shader.activate();
        unsafe {
            gl::UniformMatrix4fv(shader.u_projection,
                                 1, gl::FALSE, projection.as_ptr() as *const _);
        }
        shader.deactivate();

        shader
    }

    fn create_program(vertex: GLuint, fragment: GLuint) -> GLuint {

        unsafe {
            let program = gl::CreateProgram();
            gl::AttachShader(program, vertex);
            gl::AttachShader(program, fragment);
            gl::LinkProgram(program);

            let mut success: GLint = 0;
            gl::GetProgramiv(program, gl::LINK_STATUS, &mut success);

            if success != (gl::TRUE as GLint) {
                panic!("failed to link shader program");
            }
            program
        }
    }

    fn create_fragment_shader() -> GLuint {
        unsafe {
            let fragment_shader = gl::CreateShader(gl::FRAGMENT_SHADER);
            let fragment_source = CString::new(TEXT_SHADER_F).unwrap();
            gl::ShaderSource(fragment_shader, 1, &fragment_source.as_ptr(), ptr::null());
            gl::CompileShader(fragment_shader);

            let mut success: GLint = 0;
            gl::GetShaderiv(fragment_shader, gl::COMPILE_STATUS, &mut success);

            if success != (gl::TRUE as GLint) {
                panic!("failed to compiler fragment shader");
            }
            fragment_shader
        }
    }

    fn create_vertex_shader() -> GLuint {
        unsafe {
            let vertex_shader = gl::CreateShader(gl::VERTEX_SHADER);
            let vertex_source = CString::new(TEXT_SHADER_V).unwrap();
            gl::ShaderSource(vertex_shader, 1, &vertex_source.as_ptr(), ptr::null());
            gl::CompileShader(vertex_shader);

            let mut success: GLint = 0;
            gl::GetShaderiv(vertex_shader, gl::COMPILE_STATUS, &mut success);

            if success != (gl::TRUE as GLint) {
                panic!("failed to compiler vertex shader");
            }
            vertex_shader
        }
    }
}

struct AlphaTexture {
    pub id: GLuint,
    pub width: i32,
    pub height: i32,
}

impl AlphaTexture {
    pub fn new(width: i32, height: i32, bytes: *const ::std::os::raw::c_void) -> AlphaTexture {
        let mut id: GLuint = 0;
        unsafe {
            gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);
            gl::GenTextures(1, &mut id);
            gl::BindTexture(gl::TEXTURE_2D, id);
            gl::TexImage2D(
                gl::TEXTURE_2D,
                0,
                gl::RED as i32,
                width as i32,
                height as i32,
                0,
                gl::RED,
                gl::UNSIGNED_BYTE,
                bytes
            );

            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32);
            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32);
            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);

            gl::BindTexture(gl::TEXTURE_2D, 0);
        }

        AlphaTexture {
            id: id,
            width: width,
            height: height,
        }
    }
}
<commit_msg>Abstract glyph rendering, poorly<commit_after>extern crate fontconfig;
extern crate freetype;
extern crate libc;
extern crate glutin;
extern crate gl;
extern crate cgmath;
extern crate euclid;

mod list_fonts;
mod text;

use std::ffi::CString;
use std::mem::size_of;
use std::ptr;

use euclid::{Rect, Size2D, Point2D};

use libc::c_void;

use gl::types::*;

use cgmath::Matrix;

use text::RasterizedGlyph;

static TEXT_SHADER_V: &'static str = include_str!("../res/text.v.glsl");
static TEXT_SHADER_F: &'static str = include_str!("../res/text.f.glsl");

fn main() {
    let window = glutin::Window::new().unwrap();
    let (width, height) = window.get_inner_size_pixels().unwrap();
    unsafe {
        window.make_current()
    };

    unsafe {
        gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
        gl::Viewport(0, 0, width as i32, height as i32);
    }

    let rasterizer = text::Rasterizer::new();
    let glyph_R = Glyph::new(&rasterizer.get_glyph(180., 'R'));
    let glyph_u = Glyph::new(&rasterizer.get_glyph(180., 'u'));
    let glyph_s = Glyph::new(&rasterizer.get_glyph(180., 's'));
    let glyph_t = Glyph::new(&rasterizer.get_glyph(180., 't'));

    unsafe {
        gl::Enable(gl::BLEND);
        gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
        gl::Enable(gl::MULTISAMPLE);
    }

    let renderer = QuadRenderer::new(width, height);

    for event in window.wait_events() {
        unsafe {
            gl::ClearColor(0.08, 0.08, 0.08, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
        }

        renderer.render(&glyph_R, 10.0, 10.0);
        renderer.render(&glyph_u, 130.0, 10.0);
        renderer.render(&glyph_s, 250.0, 10.0);
        renderer.render(&glyph_t, 370.0, 10.0);

        window.swap_buffers();

        match event {
            glutin::Event::Closed => break,
            _ => ()
        }
    }
}

struct QuadRenderer {
    program: ShaderProgram,
    vao: GLuint,
    vbo: GLuint,
    ebo: GLuint,
}

impl QuadRenderer {
    // TODO should probably hand this a transform instead of width/height
    pub fn new(width: u32, height: u32) -> QuadRenderer {
        let program = ShaderProgram::new(width, height);

        let mut vao: GLuint = 0;
        let mut vbo: GLuint = 0;
        let mut ebo: GLuint = 0;

        unsafe {
            gl::GenVertexArrays(1, &mut vao);
            gl::GenBuffers(1, &mut vbo);
            gl::GenBuffers(1, &mut ebo);
            gl::BindVertexArray(vao);

            gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
            gl::BufferData(
                gl::ARRAY_BUFFER,
                (size_of::<f32>() * 4 * 4) as GLsizeiptr,
                ptr::null(),
                gl::DYNAMIC_DRAW
            );

            let indices: [u32; 6] = [0, 1, 3,
                                     1, 2, 3];

            gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo);
            gl::BufferData(gl::ELEMENT_ARRAY_BUFFER,
                           6 * size_of::<u32>() as isize,
                           indices.as_ptr() as *const _,
                           gl::STATIC_DRAW);

            gl::EnableVertexAttribArray(0);
            gl::VertexAttribPointer(0, 4, gl::FLOAT, gl::FALSE, 4 * size_of::<f32>() as i32,
                                    ptr::null());

            gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
            gl::BindBuffer(gl::ARRAY_BUFFER, 0);
            gl::BindVertexArray(0);
        }

        QuadRenderer {
            program: program,
            vao: vao,
            vbo: vbo,
            ebo: ebo,
        }
    }

    pub fn render(&self, glyph: &Glyph, x: f32, y: f32) {
        self.program.activate();
        unsafe {
            // set color
            gl::Uniform3f(self.program.u_color, 1., 1., 0.5);
        }

        let rect = get_rect(glyph, x, y);

        // top right of character
        let vertices: [[f32; 4]; 4] = [
            [rect.max_x(), rect.max_y(), 1., 0.], // top-right
            [rect.max_x(), rect.min_y(), 1., 1.], // bottom-right
            [rect.min_x(), rect.min_y(), 0., 1.], // bottom-left
            [rect.min_x(), rect.max_y(), 0., 0.], // top-left
        ];

        unsafe {
            bind_mask_texture(glyph.tex_id);
            gl::BindVertexArray(self.vao);

            gl::BindBuffer(gl::ARRAY_BUFFER, self.vbo);
            gl::BufferSubData(
                gl::ARRAY_BUFFER,
                0,
                (4 * 4 * size_of::<f32>()) as isize,
                vertices.as_ptr() as *const _
            );
            gl::BindBuffer(gl::ARRAY_BUFFER, 0);
            gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.ebo);

            gl::DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_INT, ptr::null());
            gl::BindVertexArray(0);
            gl::BindTexture(gl::TEXTURE_2D, 0);
        }

        self.program.deactivate();
    }
}

fn get_rect(glyph: &Glyph, x: f32, y: f32) -> Rect<f32> {
    Rect::new(
        Point2D::new(x, y),
        Size2D::new(glyph.width as f32, glyph.height as f32)
    )
}

fn bind_mask_texture(id: u32) {
    unsafe {
        gl::ActiveTexture(gl::TEXTURE0);
        gl::BindTexture(gl::TEXTURE_2D, id);
    }
}

pub struct ShaderProgram {
    id: GLuint,
    /// projection matrix uniform
    u_projection: GLint,
    /// color uniform
    u_color: GLint,
}

impl ShaderProgram {
    pub fn activate(&self) {
        unsafe {
            gl::UseProgram(self.id);
        }
    }

    pub fn deactivate(&self) {
        unsafe {
            gl::UseProgram(0);
        }
    }

    pub fn new(width: u32, height: u32) -> ShaderProgram {
        let vertex_shader = ShaderProgram::create_vertex_shader();
        let fragment_shader = ShaderProgram::create_fragment_shader();
        let program = ShaderProgram::create_program(vertex_shader, fragment_shader);

        unsafe {
            gl::DeleteShader(vertex_shader);
            gl::DeleteShader(fragment_shader);
        }

        // get uniform locations
        let projection_str = CString::new("projection").unwrap();
        let color_str = CString::new("textColor").unwrap();

        let (projection, color) = unsafe {
            (
                gl::GetUniformLocation(program, projection_str.as_ptr()),
                gl::GetUniformLocation(program, color_str.as_ptr())
            )
        };

        assert!(projection != gl::INVALID_VALUE as i32);
        assert!(projection != gl::INVALID_OPERATION as i32);
        assert!(color != gl::INVALID_VALUE as i32);
        assert!(color != gl::INVALID_OPERATION as i32);

        let shader = ShaderProgram {
            id: program,
            u_projection: projection,
            u_color: color,
        };

        // set projection uniform
        let ortho = cgmath::ortho(0., width as f32, 0., height as f32, -1., 1.);
        let projection: [[f32; 4]; 4] = ortho.into();

        println!("width: {}, height: {}", width, height);

        shader.activate();
        unsafe {
            gl::UniformMatrix4fv(shader.u_projection,
                                 1, gl::FALSE, projection.as_ptr() as *const _);
        }
        shader.deactivate();

        shader
    }

    fn create_program(vertex: GLuint, fragment: GLuint) -> GLuint {

        unsafe {
            let program = gl::CreateProgram();
            gl::AttachShader(program, vertex);
            gl::AttachShader(program, fragment);
            gl::LinkProgram(program);

            let mut success: GLint = 0;
            gl::GetProgramiv(program, gl::LINK_STATUS, &mut success);

            if success != (gl::TRUE as GLint) {
                panic!("failed to link shader program");
            }
            program
        }
    }

    fn create_fragment_shader() -> GLuint {
        unsafe {
            let fragment_shader = gl::CreateShader(gl::FRAGMENT_SHADER);
            let fragment_source = CString::new(TEXT_SHADER_F).unwrap();
            gl::ShaderSource(fragment_shader, 1, &fragment_source.as_ptr(), ptr::null());
            gl::CompileShader(fragment_shader);

            let mut success: GLint = 0;
            gl::GetShaderiv(fragment_shader, gl::COMPILE_STATUS, &mut success);

            if success != (gl::TRUE as GLint) {
                panic!("failed to compiler fragment shader");
            }
            fragment_shader
        }
    }

    fn create_vertex_shader() -> GLuint {
        unsafe {
            let vertex_shader = gl::CreateShader(gl::VERTEX_SHADER);
            let vertex_source = CString::new(TEXT_SHADER_V).unwrap();
            gl::ShaderSource(vertex_shader, 1, &vertex_source.as_ptr(), ptr::null());
            gl::CompileShader(vertex_shader);

            let mut success: GLint = 0;
            gl::GetShaderiv(vertex_shader, gl::COMPILE_STATUS, &mut success);

            if success != (gl::TRUE as GLint) {
                panic!("failed to compiler vertex shader");
            }
            vertex_shader
        }
    }
}

struct Glyph {
    tex_id: GLuint,
    top: i32,
    left: i32,
    width: i32,
    height: i32,
}

impl Glyph {
    pub fn new(rasterized: &RasterizedGlyph) -> Glyph {
        let mut id: GLuint = 0;
        unsafe {
            gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);
            gl::GenTextures(1, &mut id);
            gl::BindTexture(gl::TEXTURE_2D, id);
            gl::TexImage2D(
                gl::TEXTURE_2D,
                0,
                gl::RED as i32,
                rasterized.width as i32,
                rasterized.height as i32,
                0,
                gl::RED,
                gl::UNSIGNED_BYTE,
                rasterized.buf.as_ptr() as *const _
            );

            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32);
            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32);
            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);

            gl::BindTexture(gl::TEXTURE_2D, 0);
        }

        Glyph {
            tex_id: id,
            top: rasterized.top as i32,
            width: rasterized.width as i32,
            height: rasterized.height as i32,
            left: rasterized.left as i32,
        }
    }
}
<|endoftext|>


<commit_before>
extern crate modbus;
use modbus::Modbus;

pub fn main() {

    let addr = "127.0.0.1:12345".parse().unwrap();
    let mut m = Modbus::new_tcp(&addr);

}
<commit_msg>remove unneeded main.rs<commit_after><|endoftext|>


<commit_before>use std::io::fs::rename;
use std::io::fs::PathExtensions;
use std::collections::HashMap;
use std::os;
use std::io;
use std::vec::Vec;
use std::str::StrSlice;

mod util;
mod server;

fn main() {

    let args = os::args();

    if args.len() == 2 && args[1] == "--server".to_string() {
        serve();
        return;
    }

    if args.len() == 2 && args[1] == "--start-server".to_string() {
        server::start_server();
        return;
    }

    let use_external_process = args.contains(&String::from_str("--use-external-process"));

    if args.len() < 3 {
        println!("Usage: {} <original-directory> <new-directory>", args[0]);
        return;
    }

    let remote_source = args[1].as_slice().contains(":");
    let dry_run = args.contains(&"--dry-run".to_string());
    let mut ssh_port = 22i;
    let host: String;
    let source_path: String;
    let verbose = args.contains(&"--verbose".to_string());

    if args.contains(&"--ssh-port".to_string()) {
        let index = args.iter().position(|a| a == &"--ssh-port".to_string()).unwrap();
        ssh_port = from_str(args.get(index + 1).as_slice()).unwrap();
    }

    if remote_source {
        let components: Vec<&str> = args[1].as_slice().split(':').collect();
        host = components[0].to_string();
        source_path = components[1].to_string();
    }
    else {
        source_path = args[1].clone();
        host = "".to_string();
    }

    let src_directory = Path::new(source_path);
    let dst_directory = Path::new(args[2].clone());

    if remote_source || use_external_process {
        let mut server = server::StdServer::new(host, ssh_port);
        let mut dest_server = server::InMemoryServer::new();
        sync_renames(verbose, dry_run, &mut server, &mut dest_server, &src_directory, &dst_directory);
    }
    else {
        let mut server = server::InMemoryServer::new();
        let mut dest_server = server::InMemoryServer::new();
        sync_renames(verbose, dry_run, &mut server, &mut dest_server, &src_directory, &dst_directory);
    }
}

fn sync_renames(verbose: bool, dry_run: bool, source_server: &mut server::Server, dest_server: &mut server::Server, src_directory: &Path, dst_directory: &Path) {

    if verbose {
        println!("Getting source metadata...");
    }
    let src_map = source_server.get_metadata(src_directory);
    if verbose {
        println!("Getting destination metadata...");
    }
    let new_map = dest_server.get_metadata(dst_directory);

    for (&(size, mod_date), paths) in new_map.iter() {

        let mut matching_paths = 0i;

        for (i, value) in paths.iter().enumerate() {

            let new_path = Path::new(value.clone());
            let src_path :Path;

            match find_matching_file(verbose, &new_path, size, mod_date, &src_map, source_server, dest_server) {
                Some(p) => src_path = p,
                None => continue
            }

            let mut file_path = dst_directory.clone();
            file_path.push(src_path.path_relative_from(src_directory).unwrap());

            let src_relative_path = src_path.path_relative_from(src_directory).unwrap();
            let dst_relative_path = new_path.path_relative_from(dst_directory).unwrap();

            // No point in comparing a file with itself
            if src_relative_path == dst_relative_path {
                continue;
            }

            matching_paths += 1;

            if matching_paths > 1 && file_path.exists() && source_server.get_checksum(&src_path) == dest_server.get_checksum(&file_path) {
                println!("{} was copied to {}", dst_relative_path.display(), src_relative_path.display());

            } else {
                println!("{} was renamed to {}", dst_relative_path.display(), src_relative_path.display());
                if !dry_run {
                    rename(
                        &dst_directory.join(dst_relative_path),
                        &dst_directory.join(src_relative_path)).unwrap();
                }
            }
        }
    }
}

fn find_matching_file(verbose: bool, file: &Path, size: u64, modification_date: u64, master_metadata: &HashMap<(u64, u64), Vec<String>>, src_server: &mut server::Server, dest_server: &mut server::Server) -> Option<Path> {

    // Check whether there are any files in master with the same
    // size and modification date of the sought file
    match master_metadata.find(&(size, modification_date)) {

        Some(matches) => {

            // Compare the file contents until we find a match, or return None if
            // we don't find one
            for potential_match in matches.iter() {
                let path = Path::new(potential_match.clone());
                if verbose {
                    println!("Getting checksum for source file '{}'...", path.as_str());
                }
                let src_checksum = src_server.get_checksum(&path);
                if verbose {
                    println!("Getting checksum for destination file '{}'...", path.as_str());
                }
                let dest_checksum = dest_server.get_checksum(file);
                if src_checksum == dest_checksum {
                    return Some(path);
                }
            }

            return None

        }

        None => return None
    }

}

fn serve() {

    for line in io::stdin().lines() {
        let unwrapped_line = line.unwrap();
        let line_slice = unwrapped_line.as_slice().trim_right_chars('\n');
        if line_slice.starts_with("checksum ") {
           let file_name = line_slice.slice_from(9);
           println!("{}", util::get_file_checksum(&Path::new(file_name)));
           println!("\0");
        }

        if line_slice.starts_with("metadata ") {
            let path = line_slice.slice_from(9);
            for metadata in util::MetadataReader::new(&Path::new(path)) {
                println!("{}", metadata.path);
                println!("{}", metadata.size);
                println!("{}", metadata.modified);
            }
            println!("\0");

        }

    }
}
<commit_msg>Add an option to skip checksums<commit_after>use std::io::fs::rename;
use std::io::fs::PathExtensions;
use std::collections::HashMap;
use std::os;
use std::io;
use std::vec::Vec;
use std::str::StrSlice;

mod util;
mod server;

fn main() {

    let args = os::args();

    if args.len() == 2 && args[1] == "--server".to_string() {
        serve();
        return;
    }

    if args.len() == 2 && args[1] == "--start-server".to_string() {
        server::start_server();
        return;
    }

    let use_external_process = args.contains(&String::from_str("--use-external-process"));

    if args.len() < 3 {
        println!("Usage: {} <original-directory> <new-directory>", args[0]);
        return;
    }

    let remote_source = args[1].as_slice().contains(":");
    let dry_run = args.contains(&"--dry-run".to_string());
    let mut ssh_port = 22i;
    let host: String;
    let source_path: String;
    let verbose = args.contains(&"--verbose".to_string());
    let checksums = !args.contains(&"--no-checksums".to_string());

    if args.contains(&"--ssh-port".to_string()) {
        let index = args.iter().position(|a| a == &"--ssh-port".to_string()).unwrap();
        ssh_port = from_str(args.get(index + 1).as_slice()).unwrap();
    }

    if remote_source {
        let components: Vec<&str> = args[1].as_slice().split(':').collect();
        host = components[0].to_string();
        source_path = components[1].to_string();
    }
    else {
        source_path = args[1].clone();
        host = "".to_string();
    }

    let src_directory = Path::new(source_path);
    let dst_directory = Path::new(args[2].clone());

    if remote_source || use_external_process {
        let mut server = server::StdServer::new(host, ssh_port);
        let mut dest_server = server::InMemoryServer::new();
        sync_renames(checksums, verbose, dry_run, &mut server, &mut dest_server, &src_directory, &dst_directory);
    }
    else {
        let mut server = server::InMemoryServer::new();
        let mut dest_server = server::InMemoryServer::new();
        sync_renames(checksums, verbose, dry_run, &mut server, &mut dest_server, &src_directory, &dst_directory);
    }
}

fn sync_renames(checksums:bool, verbose: bool, dry_run: bool, source_server: &mut server::Server, dest_server: &mut server::Server, src_directory: &Path, dst_directory: &Path) {

    let mut renames: Vec<(Path, Path)> = Vec::new();

    if verbose {
        println!("Getting source metadata...");
    }
    let src_map = source_server.get_metadata(src_directory);
    if verbose {
        println!("Getting destination metadata...");
    }
    let new_map = dest_server.get_metadata(dst_directory);

    for (&(size, mod_date), paths) in new_map.iter() {

        let mut matching_paths = 0i;

        for (i, value) in paths.iter().enumerate() {

            let new_path = Path::new(value.clone());
            let src_path :Path;

            match find_matching_file(src_directory, dst_directory, checksums, verbose, &new_path, size, mod_date, &src_map, source_server, dest_server) {
                Some(p) => src_path = p,
                None => continue
            }

            let mut file_path = dst_directory.clone();
            file_path.push(src_path.path_relative_from(src_directory).unwrap());

            let src_relative_path = src_path.path_relative_from(src_directory).unwrap();
            let dst_relative_path = new_path.path_relative_from(dst_directory).unwrap();

            matching_paths += 1;

            if matching_paths > 1 && file_path.exists() && source_server.get_checksum(&src_path) == dest_server.get_checksum(&file_path) {
                println!("{} was copied to {}", dst_relative_path.display(), src_relative_path.display());

            } else {
                println!("{} was renamed to {}", dst_relative_path.display(), src_relative_path.display());
                renames.push(
                    (dst_directory.join(dst_relative_path),
                    dst_directory.join(src_relative_path)));
            }
        }
    }

    if !dry_run {
        for &(ref old, ref new) in renames.iter() {
            rename(old, new).unwrap();
        }
    }
}

fn find_matching_file(src_directory: &Path, dst_directory: &Path, checksums: bool, verbose: bool, file: &Path, size: u64, modification_date: u64, master_metadata: &HashMap<(u64, u64), Vec<String>>, src_server: &mut server::Server, dest_server: &mut server::Server) -> Option<Path> {

    // Check whether there are any files in master with the same
    // size and modification date of the sought file
    match master_metadata.find(&(size, modification_date)) {

        Some(matches) => {

            // Compare the file contents until we find a match, or return None if
            // we don't find one
            for potential_match in matches.iter() {

                let path = Path::new(potential_match.clone());

                let src_relative_path = path.path_relative_from(src_directory).unwrap();
                let dst_relative_path = file.path_relative_from(dst_directory).unwrap();

                // No point in comparing a file with itself
                if src_relative_path == dst_relative_path {
                    continue;
                }

                if !checksums {
                    return Some(path);
                }

                if verbose {
                    println!("Getting checksum for source file '{}'...", path.as_str());
                }
                let src_checksum = src_server.get_checksum(&path);
                if verbose {
                    println!("Getting checksum for destination file '{}'...", file.as_str());
                }
                let dest_checksum = dest_server.get_checksum(file);
                if src_checksum == dest_checksum {
                    return Some(path);
                }
            }

            return None

        }

        None => return None
    }

}

fn serve() {

    for line in io::stdin().lines() {
        let unwrapped_line = line.unwrap();
        let line_slice = unwrapped_line.as_slice().trim_right_chars('\n');
        if line_slice.starts_with("checksum ") {
           let file_name = line_slice.slice_from(9);
           println!("{}", util::get_file_checksum(&Path::new(file_name)));
           println!("\0");
        }

        if line_slice.starts_with("metadata ") {
            let path = line_slice.slice_from(9);
            for metadata in util::MetadataReader::new(&Path::new(path)) {
                println!("{}", metadata.path);
                println!("{}", metadata.size);
                println!("{}", metadata.modified);
            }
            println!("\0");

        }

    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate websocat;

extern crate futures;
extern crate tokio_core;
extern crate tokio_stdin_stdout;

extern crate env_logger;

#[cfg(feature="openssl-probe")]
extern crate openssl_probe;

#[macro_use]
extern crate structopt;

use structopt::StructOpt;

use tokio_core::reactor::Core;

use websocat::{spec, Options, SpecifierClass, WebsocatConfiguration};

type Result<T> = std::result::Result<T, Box<std::error::Error>>;

#[derive(StructOpt, Debug)]
#[structopt(
    after_help = "
Basic examples:
  Connect stdin/stdout to a websocket:
    websocat - ws://echo.websocket.org/

  Listen websocket and redirect it to a TCP port:
    websocat ws-l:127.0.0.1:8080 tcp:127.0.0.1:5678

  See more examples with the --long-help option

Short list of specifiers (see --long-help):
  ws:// wss:// - inetd: ws-listen: inetd-ws: tcp: tcp-l: ws-c:
  autoreconnect: reuse: mirror: threadedstdio: clogged:
  literal: literalreply: assert: udp-connect: open-async:
  readfile: writefile: open-fd: unix-connect: unix-listen:
  unix-dgram: abstract-connect: abstract-listen:
  exec: sh-c:
"
)]
struct Opt {
    /// First, listening/connecting specifier. See --long-help for info about specifiers.
    s1: String,
    /// Second, connecting specifier
    s2: String,

    #[structopt(
        short = "u",
        long = "unidirectional",
        help = "Inhibit copying data from right specifier to left"
    )]
    unidirectional: bool,
    #[structopt(
        short = "U",
        long = "unidirectional-reverse",
        help = "Inhibit copying data from left specifier to right"
    )]
    unidirectional_reverse: bool,

    #[structopt(
        long = "exit-on-eof",
        short = "E",
        help = "Close a data transfer direction if the other one reached EOF"
    )]
    exit_on_eof: bool,

    #[structopt(
        short = "t", long = "text", help = "Send text WebSocket messages instead of binary"
    )]
    websocket_text_mode: bool,

    #[structopt(long = "oneshot", help = "Serve only once. Not to be confused with -1 (--one-message)")]
    oneshot: bool,

    #[structopt(long = "long-help", help = "Show full help aboput specifiers and examples")]
    longhelp: bool,

    #[structopt(
        long = "dump-spec",
        help = "Instead of running, dump the specifiers representation to stdout"
    )]
    dumpspec: bool,

    #[structopt(long = "protocol", help = "Specify Sec-WebSocket-Protocol: header")]
    websocket_protocol: Option<String>,

    #[structopt(long = "udp-oneshot", help = "udp-listen: replies only one packet per client")]
    udp_oneshot_mode: bool,

    #[structopt(long = "unlink", help = "Unlink listening UNIX socket before binding to it")]
    unlink_unix_socket: bool,

    #[structopt(
        long = "exec-args",
        raw(allow_hyphen_values = r#"true"#),
        help = "Arguments for the `exec:` specifier. Must be the last option, everything after it gets into the exec args list."
    )]
    exec_args: Vec<String>,

    #[structopt(
        long = "ws-c-uri", help = "URI to use for ws-c: specifier", default_value = "ws://0.0.0.0/"
    )]
    ws_c_uri: String,

    #[structopt(
        long = "linemode-retain-newlines",
        help = "In --line mode, don't chop off trailing \\n from messages"
    )]
    linemode_retain_newlines: bool,

    #[structopt(
        short = "-l", long = "--line", help = "Make each WebSocket message correspond to one line"
    )]
    linemode: bool,

    #[structopt(long="origin",help="Add Origin HTTP header to websocket client request")]
    origin: Option<String>,

    #[structopt(
        long="header",
        short="H",
        help="Add custom HTTP header to websocket client request. Separate header name and value with a colon and optionally a single space. Can be used multiple times.",
        parse(try_from_str="interpret_custom_header"),
    )]
    custom_headers: Vec<(String,Vec<u8>)>,

    #[structopt(long="websocket-version", help="Override the Sec-WebSocket-Version value")]
    websocket_version: Option<String>,

    #[structopt(long="no-close", short="n", help="Don't send Close message to websocket on EOF")]
    websocket_dont_close: bool,

    #[structopt(
        short="1",
        long="one-message",
        help="Send and/or receive only one message. Use with --no-close and/or -u/-U.",
    )]
    one_message : bool,

    // TODO: -v --quiet
}

// TODO: make it byte-oriented/OsStr?
fn interpret_custom_header(x:&str) -> Result<(String,Vec<u8>)> {
    let colon = x.find(':');
    let colon = if let Some(colon) = colon { colon } else {
        Err("Argument to --header must contain `:` character")?
    };
    let hn = &x[0..colon];
    let mut hv = &x[colon+1..];
    if hv.chars().next() == Some(' ') {
        hv = &x[colon+2..];
    }
    Ok((hn.to_owned(), hv.as_bytes().to_vec()))
}

fn longhelp() {
    println!(
        r#"(see also the usual --help message)

Positional arguments to websocat are generally called specifiers.
Specifiers are ways to obtain a connection from some string representation (i.e. address).

Specifiers may be argumentless (like `mirror:`), can accept an argument (which
may be some path or socket address, like `tcp:`), or can accept a subspecifier
(like `reuse:` or `autoreconnect:`).

Here is the full list of specifier classes in this WebSocat build:

"#
    );

    fn help1(sc: &SpecifierClass) {
        let n = sc.get_name().replace("Class", "");
        let prefixes = sc
            .get_prefixes()
            .iter()
            .map(|x| format!("`{}`", x))
            .collect::<Vec<_>>()
            .join(", ");
        println!("### {}\n\n* {}", n, prefixes);

        let help =
            sc
            .help()
            //.lines()
            //.map(|x|format!("    {}",x))
            //.collect::<Vec<_>>()
            //.join("\n")
            ;
        println!("{}\n", help);
    }

    macro_rules! my {
        ($x:expr) => {
            help1(&$x);
        };
    }

    list_of_all_specifier_classes!(my);

    println!(
        r#"

TODO:
  sctp:
  ssl:

Final example just for fun: wacky mode

    websocat ws-c:ws-l:ws-c:- tcp:127.0.0.1:5678

Connect to a websocket using stdin/stdout as a transport,
then accept a websocket connection over the previous websocket used as a transport,
then connect to a websocket using previous step as a transport,
then forward resulting connection to the TCP port.

(Excercise to the reader: manage to make it actually connect to 5678).
"#
    );
}

fn run() -> Result<()> {
    if std::env::args().nth(1).unwrap_or_default() == "--long-help" {
        longhelp();
        return Ok(());
    }

    let cmd = Opt::from_args();

    if cmd.longhelp {
        longhelp();
        return Ok(());
    }

    if false
    //    || cmd.oneshot
    {
        Err("This mode is not implemented")?
    }

    #[cfg(feature="openssl-probe")] {
        openssl_probe::init_ssl_cert_env_vars();
    }

    let opts = {
        macro_rules! opts {
            ($($o:ident)*) => {
                Options {
                    $($o : cmd.$o,)*
                }
            };
        }
        opts!(
            websocket_text_mode
            websocket_protocol
            udp_oneshot_mode
            unidirectional
            unidirectional_reverse
            exit_on_eof
            oneshot
            unlink_unix_socket
            exec_args
            ws_c_uri
            linemode_retain_newlines
            origin
            custom_headers
            websocket_version
            websocket_dont_close
            one_message
        )
    };

    let s1 = spec(&cmd.s1)?;
    let s2 = spec(&cmd.s2)?;

    let mut websocat = WebsocatConfiguration { opts, s1, s2 };

    if cmd.linemode {
        use websocat::lints::AutoInstallLinemodeConcern::*;
        websocat = match websocat.auto_install_linemode() {
            Ok(x) => x,
            Err((NoWebsocket,_)) => Err("No websocket usage is specified. Use line2msg: and msg2line: specifiers manually if needed.")?,
            Err((MultipleWebsocket,_)) => Err("Multiple websocket usages are specified. Use line2msg: and msg2line: specifiers manually if needed.")?,
            Err((AlreadyLine,_)) => Err("Can't auto-insert msg2line:/line2msg: if you have already manually specified some of them")?,
        }
    }

    while let Some(concern) = websocat.get_concern() {
        use websocat::lints::ConfigurationConcern::*;
        if concern == StdinToStdout {
            if cmd.dumpspec {
                println!("cat mode");
                return Ok(());
            }

            // Degenerate mode: just copy stdin to stdout and call it a day
            ::std::io::copy(&mut ::std::io::stdin(), &mut ::std::io::stdout())?;
            return Ok(());
        }

        if concern == DegenerateMode {
            if cmd.dumpspec {
                println!("noop");
            }
            return Ok(());
        }

        if concern == StdioConflict {
            Err("Too many usages of stdin/stdout")?;
        }

        if concern == NeedsStdioReuser {
            eprintln!("Warning: replies on stdio get directed at random connected client");
            websocat = websocat.auto_install_reuser();
            continue;
        }

        if concern == NeedsStdioReuser2 {
            websocat = websocat.auto_install_reuser();
            continue;
        }

        if concern == MultipleReusers {
            eprintln!("Specifier dump: {:?} {:?}", websocat.s1, websocat.s2);
            Err("Multiple reusers is not allowed")?;
        }
        break;
    }

    if cmd.dumpspec {
        println!("{:?}", websocat.s1);
        println!("{:?}", websocat.s2);
        println!("{:?}", websocat.opts);
        return Ok(());
    }

    let mut core = Core::new()?;

    let prog = websocat.serve(
        core.handle(),
        std::rc::Rc::new(|e| {
            eprintln!("websocat: {}", e);
        }),
    );
    core.run(prog).map_err(|()| "error running".to_string())?;
    Ok(())
}

fn main() {
    env_logger::init();
    let r = run();

    if let Err(e) = r {
        eprintln!("websocat: {}", e);
        ::std::process::exit(1);
    }
}
<commit_msg>Single-argument mode<commit_after>#[macro_use]
extern crate websocat;

extern crate futures;
extern crate tokio_core;
extern crate tokio_stdin_stdout;

extern crate env_logger;

#[cfg(feature="openssl-probe")]
extern crate openssl_probe;

#[macro_use]
extern crate structopt;

use structopt::StructOpt;

use tokio_core::reactor::Core;

use websocat::{spec, Options, SpecifierClass, WebsocatConfiguration};

type Result<T> = std::result::Result<T, Box<std::error::Error>>;

#[derive(StructOpt, Debug)]
#[structopt(
    after_help = "
Basic examples:
  Command-line websocket client:
    websocat ws://echo.websocket.org/

  Listen websocket and redirect it to a TCP port:
    websocat ws-l:127.0.0.1:8080 tcp:127.0.0.1:5678

  See more examples with the --long-help option

Short list of specifiers (see --long-help):
  ws:// wss:// - inetd: ws-listen: inetd-ws: tcp: tcp-l: ws-c:
  autoreconnect: reuse: mirror: threadedstdio: clogged:
  literal: literalreply: assert: udp-connect: open-async:
  readfile: writefile: open-fd: unix-connect: unix-listen:
  unix-dgram: abstract-connect: abstract-listen:
  exec: sh-c:
", usage="websocat [FLAGS] [OPTIONS] <s1> [s2]"
)]
struct Opt {
    /// First, listening/connecting specifier. See --long-help for info about specifiers.
    s1: String,
    /// Second, connecting specifier
    s2: Option<String>,

    #[structopt(
        short = "u",
        long = "unidirectional",
        help = "Inhibit copying data from right specifier to left"
    )]
    unidirectional: bool,
    #[structopt(
        short = "U",
        long = "unidirectional-reverse",
        help = "Inhibit copying data from left specifier to right"
    )]
    unidirectional_reverse: bool,

    #[structopt(
        long = "exit-on-eof",
        short = "E",
        help = "Close a data transfer direction if the other one reached EOF"
    )]
    exit_on_eof: bool,

    #[structopt(
        short = "t", long = "text", help = "Send text WebSocket messages instead of binary"
    )]
    websocket_text_mode: bool,

    #[structopt(long = "oneshot", help = "Serve only once. Not to be confused with -1 (--one-message)")]
    oneshot: bool,

    #[structopt(long = "long-help", help = "Show full help aboput specifiers and examples")]
    longhelp: bool,

    #[structopt(
        long = "dump-spec",
        help = "Instead of running, dump the specifiers representation to stdout"
    )]
    dumpspec: bool,

    #[structopt(long = "protocol", help = "Specify Sec-WebSocket-Protocol: header")]
    websocket_protocol: Option<String>,

    #[structopt(long = "udp-oneshot", help = "udp-listen: replies only one packet per client")]
    udp_oneshot_mode: bool,

    #[structopt(long = "unlink", help = "Unlink listening UNIX socket before binding to it")]
    unlink_unix_socket: bool,

    #[structopt(
        long = "exec-args",
        raw(allow_hyphen_values = r#"true"#),
        help = "Arguments for the `exec:` specifier. Must be the last option, everything after it gets into the exec args list."
    )]
    exec_args: Vec<String>,

    #[structopt(
        long = "ws-c-uri", help = "URI to use for ws-c: specifier", default_value = "ws://0.0.0.0/"
    )]
    ws_c_uri: String,

    #[structopt(
        long = "linemode-retain-newlines",
        help = "In --line mode, don't chop off trailing \\n from messages"
    )]
    linemode_retain_newlines: bool,

    #[structopt(
        short = "-l", long = "--line", help = "Make each WebSocket message correspond to one line"
    )]
    linemode: bool,

    #[structopt(long="origin",help="Add Origin HTTP header to websocket client request")]
    origin: Option<String>,

    #[structopt(
        long="header",
        short="H",
        help="Add custom HTTP header to websocket client request. Separate header name and value with a colon and optionally a single space. Can be used multiple times.",
        parse(try_from_str="interpret_custom_header"),
    )]
    custom_headers: Vec<(String,Vec<u8>)>,

    #[structopt(long="websocket-version", help="Override the Sec-WebSocket-Version value")]
    websocket_version: Option<String>,

    #[structopt(long="no-close", short="n", help="Don't send Close message to websocket on EOF")]
    websocket_dont_close: bool,

    #[structopt(
        short="1",
        long="one-message",
        help="Send and/or receive only one message. Use with --no-close and/or -u/-U.",
    )]
    one_message : bool,

    // TODO: -v --quiet
}

// TODO: make it byte-oriented/OsStr?
fn interpret_custom_header(x:&str) -> Result<(String,Vec<u8>)> {
    let colon = x.find(':');
    let colon = if let Some(colon) = colon { colon } else {
        Err("Argument to --header must contain `:` character")?
    };
    let hn = &x[0..colon];
    let mut hv = &x[colon+1..];
    if hv.chars().next() == Some(' ') {
        hv = &x[colon+2..];
    }
    Ok((hn.to_owned(), hv.as_bytes().to_vec()))
}

fn longhelp() {
    println!(
        r#"(see also the usual --help message)

Positional arguments to websocat are generally called specifiers.
Specifiers are ways to obtain a connection from some string representation (i.e. address).

Specifiers may be argumentless (like `mirror:`), can accept an argument (which
may be some path or socket address, like `tcp:`), or can accept a subspecifier
(like `reuse:` or `autoreconnect:`).

Here is the full list of specifier classes in this WebSocat build:

"#
    );

    fn help1(sc: &SpecifierClass) {
        let n = sc.get_name().replace("Class", "");
        let prefixes = sc
            .get_prefixes()
            .iter()
            .map(|x| format!("`{}`", x))
            .collect::<Vec<_>>()
            .join(", ");
        println!("### {}\n\n* {}", n, prefixes);

        let help =
            sc
            .help()
            //.lines()
            //.map(|x|format!("    {}",x))
            //.collect::<Vec<_>>()
            //.join("\n")
            ;
        println!("{}\n", help);
    }

    macro_rules! my {
        ($x:expr) => {
            help1(&$x);
        };
    }

    list_of_all_specifier_classes!(my);

    println!(
        r#"

TODO:
  sctp:
  ssl:

Final example just for fun: wacky mode

    websocat ws-c:ws-l:ws-c:- tcp:127.0.0.1:5678

Connect to a websocket using stdin/stdout as a transport,
then accept a websocket connection over the previous websocket used as a transport,
then connect to a websocket using previous step as a transport,
then forward resulting connection to the TCP port.

(Excercise to the reader: manage to make it actually connect to 5678).
"#
    );
}

fn run() -> Result<()> {
    if std::env::args().nth(1).unwrap_or_default() == "--long-help" {
        longhelp();
        return Ok(());
    }

    let mut cmd = Opt::from_args();

    if cmd.longhelp {
        longhelp();
        return Ok(());
    }

    if false
    //    || cmd.oneshot
    {
        Err("This mode is not implemented")?
    }

    #[cfg(feature="openssl-probe")] {
        openssl_probe::init_ssl_cert_env_vars();
    }

    let mut opts = {
        macro_rules! opts {
            ($($o:ident)*) => {
                Options {
                    $($o : cmd.$o,)*
                }
            };
        }
        opts!(
            websocket_text_mode
            websocket_protocol
            udp_oneshot_mode
            unidirectional
            unidirectional_reverse
            exit_on_eof
            oneshot
            unlink_unix_socket
            exec_args
            ws_c_uri
            linemode_retain_newlines
            origin
            custom_headers
            websocket_version
            websocket_dont_close
            one_message
        )
    };

    let (s1, s2) = if let Some(ref cmds2) = cmd.s2 {
        (spec(&cmd.s1)?, spec(cmds2)?)
    } else {
        if ! (cmd.s1.starts_with("ws://") || cmd.s1.starts_with("wss://")) {
            Err("Simple one-argument mode is only for connecting to websockets. Use explicit two-argument websocat invocation for advanced features.")?;
        }
        // Easy mode
        cmd.linemode = true;
        opts.websocket_text_mode = true;
        if opts.websocket_protocol == None {
            opts.websocket_protocol = Some("tcp".to_owned());
        }
        (spec("-")?, spec(&cmd.s1)?)
    };

    let mut websocat = WebsocatConfiguration { opts, s1, s2 };

    if cmd.linemode {
        use websocat::lints::AutoInstallLinemodeConcern::*;
        websocat = match websocat.auto_install_linemode() {
            Ok(x) => x,
            Err((NoWebsocket,_)) => Err("No websocket usage is specified. Use line2msg: and msg2line: specifiers manually if needed.")?,
            Err((MultipleWebsocket,_)) => Err("Multiple websocket usages are specified. Use line2msg: and msg2line: specifiers manually if needed.")?,
            Err((AlreadyLine,_)) => Err("Can't auto-insert msg2line:/line2msg: if you have already manually specified some of them")?,
        }
    }

    while let Some(concern) = websocat.get_concern() {
        use websocat::lints::ConfigurationConcern::*;
        if concern == StdinToStdout {
            if cmd.dumpspec {
                println!("cat mode");
                return Ok(());
            }

            // Degenerate mode: just copy stdin to stdout and call it a day
            ::std::io::copy(&mut ::std::io::stdin(), &mut ::std::io::stdout())?;
            return Ok(());
        }

        if concern == DegenerateMode {
            if cmd.dumpspec {
                println!("noop");
            }
            return Ok(());
        }

        if concern == StdioConflict {
            Err("Too many usages of stdin/stdout")?;
        }

        if concern == NeedsStdioReuser {
            eprintln!("Warning: replies on stdio get directed at random connected client");
            websocat = websocat.auto_install_reuser();
            continue;
        }

        if concern == NeedsStdioReuser2 {
            websocat = websocat.auto_install_reuser();
            continue;
        }

        if concern == MultipleReusers {
            eprintln!("Specifier dump: {:?} {:?}", websocat.s1, websocat.s2);
            Err("Multiple reusers is not allowed")?;
        }
        break;
    }

    if cmd.dumpspec {
        println!("{:?}", websocat.s1);
        println!("{:?}", websocat.s2);
        println!("{:?}", websocat.opts);
        return Ok(());
    }

    let mut core = Core::new()?;

    let prog = websocat.serve(
        core.handle(),
        std::rc::Rc::new(|e| {
            eprintln!("websocat: {}", e);
        }),
    );
    core.run(prog).map_err(|()| "error running".to_string())?;
    Ok(())
}

fn main() {
    env_logger::init();
    let r = run();

    if let Err(e) = r {
        eprintln!("websocat: {}", e);
        ::std::process::exit(1);
    }
}
<|endoftext|>


<commit_before>
mod tables;

static SRGB: ColorSpace = ColorSpace {
    r: ColorXyy {
        x: 0.6400,
        y: 0.3300,
        Y: 0.2126,
    },
    g: ColorXyy {
        x: 0.3000,
        y: 0.6000,
        Y: 0.7152,
    },
    b: ColorXyy {
        x: 0.1500,
        y: 0.0600,
        Y: 0.0722,
    },
    w: ColorXyy {
        x: 0.3127,
        y: 0.3290,
        Y: 1.0000,
    },
};

#[deriving(Show)]
struct ColorSpace {
    r: ColorXyy,
    g: ColorXyy,
    b: ColorXyy,
    w: ColorXyy,
}

#[deriving(Show)]
struct Color3<T, U>(T, T, T);
#[deriving(Show)]
struct Color4<T, U>(T, T, T, T);

#[deriving(Show)]
struct ColorXyz {
    x: f64,
    y: f64,
    z: f64,
}

impl ColorXyz {
    fn from_wavelength(wavelength: uint) -> ColorXyz {
        use self::tables::CIE_COLOR_MATCH;
        match CIE_COLOR_MATCH.get(wavelength - 390) {
            Some(c) => ColorXyz {
                x: c[0],
                y: c[1],
                z: c[2],
            },
            None => ColorXyz {
                x: 0.0,
                y: 0.0,
                z: 0.0,
            },
        }
    }
    fn to_rgb(&self, cs: &ColorSpace) -> ColorRgbF64 {
        let (xc, yc, zc) = (self.x, self.y, self.z);
        let (xr, yr, zr) = (cs.r.x, cs.r.y, 1. - (cs.r.x + cs.r.y));
        let (xg, yg, zg) = (cs.g.x, cs.g.y, 1. - (cs.g.x + cs.g.y));
        let (xb, yb, zb) = (cs.b.x, cs.b.y, 1. - (cs.b.x + cs.b.y));
        let (xw, yw, zw) = (cs.w.x, cs.w.y, 1. - (cs.w.x + cs.w.y));
        let (rx, ry, rz) = (yg * zb - yb * zg, xb * zg - xg * zb, xg * yb - xb * yg);
        let (gx, gy, gz) = (yb * zr - yr * zb, xr * zb - xb * zr, xb * yr - xr * yb);
        let (bx, by, bz) = (yr * zg - yg * zr, xg * zr - xr * zg, xr * yg - xg * yr);
        let rw = (rx * xw + ry * yw + rz * zw) / yw;
        let gw = (gx * xw + gy * yw + gz * zw) / yw;
        let bw = (bx * xw + by * yw + bz * zw) / yw;
        let (rx, ry, rz) = (rx / rw, ry / rw, rz / rw);
        let (gx, gy, gz) = (gx / gw, gy / gw, gz / gw);
        let (bx, by, bz) = (bx / bw, by / bw, bz / bw);
        ColorRgbF64 {
            r: rx * xc + ry * yc + rz * zc,
            g: gx * xc + gy * yc + gz * zc,
            b: bx * xc + by * yc + bz * zc,
        }
    }
    fn normalize(&self) -> ColorXyz {
        let m = self.x.max(self.y).max(self.z);
        ColorXyz {
            x: self.x.div(&m),
            y: self.y.div(&m),
            z: self.z.div(&m),
        }
    }
}

#[allow(uppercase_variables)]
#[deriving(Show)]
struct ColorXyy {
    x: f64,
    y: f64,
    Y: f64,
}

#[deriving(Show)]
struct ColorRgbU8 {
    r: u8,
    g: u8,
    b: u8,
}

impl ColorRgbU8 {
    fn to_float(&self) -> ColorRgbF64 {
        ColorRgbF64 {
            r: self.r as f64 / 255.,
            g: self.g as f64 / 255.,
            b: self.b as f64 / 255.,
        }
    }
}

#[deriving(Show)]
struct ColorRgbF64 {
    r: f64,
    g: f64,
    b: f64,
}

impl ColorRgbF64 {
    fn to_int(&self) -> ColorRgbU8 {
        ColorRgbU8 {
            r: (self.r.min(1.).max(0.) * 255.).round() as u8,
            g: (self.g.min(1.).max(0.) * 255.).round() as u8,
            b: (self.b.min(1.).max(0.) * 255.).round() as u8,
        }
    }
    fn luminance(&self, cs: &ColorSpace) -> f64 {
        self.r * cs.r.Y + self.g * cs.g.Y + self.b * cs.b.Y
    }
    fn normalize(&self) -> ColorRgbF64 {
        let m = self.r.max(self.g).max(self.b);
        ColorRgbF64 {
            r: self.r.div(&m),
            g: self.g.div(&m),
            b: self.b.div(&m),
        }
    }
    fn constrain(&self) -> ColorRgbF64 {
        let w = 0f64.min(self.r).min(self.g).min(self.b);
        ColorRgbF64 {
            r: self.r - w,
            g: self.g - w,
            b: self.b - w,
        }
    }
    fn encode_srgb(&self) -> ColorRgbF64 {
        fn encode(x: f64) -> f64 {
            if x <= 0.0031308 {
                x * 12.92
            } else {
                x.powf(2.4f64.recip()) * (1. + 0.055) - 0.055
            }
        }
        ColorRgbF64 {
            r: encode(self.r),
            g: encode(self.g),
            b: encode(self.b),
        }
    }
    fn decode_srgb(&self) -> ColorRgbF64 {
        fn decode(x: f64) -> f64 {
            if x <= 0.04045 {
                x / 12.92
            } else {
                ((x + 0.055) / (1. + 0.055)).powf(2.4)
            }
        }
        ColorRgbF64 {
            r: decode(self.r),
            g: decode(self.g),
            b: decode(self.b),
        }
    }
    fn from_hue(hue: f64) -> ColorRgbF64 {
        let x = 1. - (hue % 2. - 1.).abs();
        match hue {
            h if h >= 0. && h < 1. => ColorRgbF64 { r: 1., g: x, b: 0. },
            h if h >= 1. && h < 2. => ColorRgbF64 { r: x, g: 1., b: 0. },
            h if h >= 2. && h < 3. => ColorRgbF64 { r: 0., g: 1., b: x },
            h if h >= 3. && h < 4. => ColorRgbF64 { r: 0., g: x, b: 1. },
            h if h >= 4. && h < 5. => ColorRgbF64 { r: x, g: 0., b: 1. },
            h if h >= 5. && h < 6. => ColorRgbF64 { r: 1., g: 0., b: x },
            _ => unreachable!(),
        }
    }
    fn target_luminance(&self, lum: f64, cs: &ColorSpace) -> ColorRgbF64 {
        let l = self.luminance(cs);
        if l < lum {
            let d = (lum - 1.) / (l - 1.);
            self * d + ColorRgbF64::white() * (1. - d)
        } else {
            self * (lum / l)
        }
    }
    fn white() -> ColorRgbF64 {
        ColorRgbF64 {
            r: 1.,
            g: 1.,
            b: 1.,
        }
    }
}

impl Add<ColorRgbF64, ColorRgbF64> for ColorRgbF64 {
    fn add(&self, o: &ColorRgbF64) -> ColorRgbF64 {
        ColorRgbF64 {
            r: self.r.add(&o.r),
            g: self.g.add(&o.g),
            b: self.b.add(&o.b),
        }
    }
}

impl Mul<f64, ColorRgbF64> for ColorRgbF64 {
    fn mul(&self, o: &f64) -> ColorRgbF64 {
        ColorRgbF64 {
            r: self.r.mul(o),
            g: self.g.mul(o),
            b: self.b.mul(o),
        }
    }
}

impl Div<f64, ColorRgbF64> for ColorRgbF64 {
    fn div(&self, o: &f64) -> ColorRgbF64 {
        ColorRgbF64 {
            r: self.r.div(o),
            g: self.g.div(o),
            b: self.b.div(o),
        }
    }
}

fn rainbow_username() {
    let s = "ABCDEFGHI";
    let len = s.len();
    let num = len - 1;
    let lo = 400;
    let hi = 650;
    let colors = range(0, len).map(|i| {
        let xyz = ColorXyz::from_wavelength(lo + (num - i) * (hi - lo) / num);
        (xyz.to_rgb(&SRGB).constrain().normalize() + ColorRgbF64::white() * 0.1).normalize()
    }).collect::<Vec<ColorRgbF64>>();
    let minlum = colors.iter().fold(1f64, |s, c| {
        s.min(c.luminance(&SRGB))
    });
    for c in colors.iter().map(|c| {
        (c * minlum / c.luminance(&SRGB)).encode_srgb().to_int()
    }) {
        println!("{:02X}{:02X}{:02X}", c.r, c.g, c.b);
    }
}
fn irc_nick_colors() {
    let num = 9u;
    for c in range(0, num).map(|i| {
        let hue = i as f64 * (6. / num as f64);
        ColorRgbF64::from_hue(hue).target_luminance(0.5, &SRGB).encode_srgb().to_int()
    }) {
        println!("{:02X}{:02X}{:02X}", c.r, c.g, c.b);
    }
}
fn main() {
    irc_nick_colors()
}
<commit_msg>Stuff<commit_after>
use std::iter::{AdditiveIterator};
use std::iter::range_step;
use std::num::{Zero};

use std::io::net::tcp::TcpStream;
use std::io::{IoResult, BufferedWriter};

mod tables;

static SRGB: ColorSpace = ColorSpace {
    r: ColorXyy {
        x: 0.6400,
        y: 0.3300,
        Y: 0.2126,
    },
    g: ColorXyy {
        x: 0.3000,
        y: 0.6000,
        Y: 0.7152,
    },
    b: ColorXyy {
        x: 0.1500,
        y: 0.0600,
        Y: 0.0722,
    },
    w: ColorXyy {
        x: 0.3127,
        y: 0.3290,
        Y: 1.0000,
    },
};

#[deriving(Show)]
struct ColorSpace {
    r: ColorXyy,
    g: ColorXyy,
    b: ColorXyy,
    w: ColorXyy,
}

#[deriving(Show)]
struct Color3<T, U>(T, T, T);
#[deriving(Show)]
struct Color4<T, U>(T, T, T, T);

#[deriving(Show)]
struct ColorXyz {
    x: f64,
    y: f64,
    z: f64,
}

impl ColorXyz {
    fn from_array(arr: &[f64, ..3]) -> ColorXyz {
        ColorXyz {
            x: arr[0],
            y: arr[1],
            z: arr[2],
        }
    }
    fn from_wavelength(wavelength: uint) -> ColorXyz {
        use self::tables::CIE_COLOR_MATCH;
        match CIE_COLOR_MATCH.get(wavelength - 390) {
            Some(c) => ColorXyz::from_array(c),
            None => Zero::zero(),
        }
    }
    fn to_rgb(&self, cs: &ColorSpace) -> ColorRgbF64 {
        let (xc, yc, zc) = (self.x, self.y, self.z);
        let (xr, yr, zr) = (cs.r.x, cs.r.y, 1. - (cs.r.x + cs.r.y));
        let (xg, yg, zg) = (cs.g.x, cs.g.y, 1. - (cs.g.x + cs.g.y));
        let (xb, yb, zb) = (cs.b.x, cs.b.y, 1. - (cs.b.x + cs.b.y));
        let (xw, yw, zw) = (cs.w.x, cs.w.y, 1. - (cs.w.x + cs.w.y));
        let (rx, ry, rz) = (yg * zb - yb * zg, xb * zg - xg * zb, xg * yb - xb * yg);
        let (gx, gy, gz) = (yb * zr - yr * zb, xr * zb - xb * zr, xb * yr - xr * yb);
        let (bx, by, bz) = (yr * zg - yg * zr, xg * zr - xr * zg, xr * yg - xg * yr);
        let rw = (rx * xw + ry * yw + rz * zw) / yw;
        let gw = (gx * xw + gy * yw + gz * zw) / yw;
        let bw = (bx * xw + by * yw + bz * zw) / yw;
        let (rx, ry, rz) = (rx / rw, ry / rw, rz / rw);
        let (gx, gy, gz) = (gx / gw, gy / gw, gz / gw);
        let (bx, by, bz) = (bx / bw, by / bw, bz / bw);
        ColorRgbF64 {
            r: rx * xc + ry * yc + rz * zc,
            g: gx * xc + gy * yc + gz * zc,
            b: bx * xc + by * yc + bz * zc,
        }
    }
    fn normalize(&self) -> ColorXyz {
        let m = self.x.max(self.y).max(self.z);
        ColorXyz {
            x: self.x.div(&m),
            y: self.y.div(&m),
            z: self.z.div(&m),
        }
    }
}

impl Zero for ColorXyz {
    fn zero() -> ColorXyz {
        ColorXyz {
            x: 0.,
            y: 0.,
            z: 0.,
        }
    }
    fn is_zero(&self) -> bool {
        self.x == 0. && self.y == 0. && self.z == 0.
    }
}

impl Add<ColorXyz, ColorXyz> for ColorXyz {
    fn add(&self, o: &ColorXyz) -> ColorXyz {
        ColorXyz {
            x: self.x + o.x,
            y: self.y + o.y,
            z: self.z + o.z,
        }
    }
}
impl Mul<f64, ColorXyz> for ColorXyz {
    fn mul(&self, o: &f64) -> ColorXyz {
        ColorXyz {
            x: self.x.mul(o),
            y: self.y.mul(o),
            z: self.z.mul(o),
        }
    }
}

#[allow(uppercase_variables)]
#[deriving(Show)]
struct ColorXyy {
    x: f64,
    y: f64,
    Y: f64,
}

#[deriving(Show)]
struct ColorRgbU8 {
    r: u8,
    g: u8,
    b: u8,
}

impl ColorRgbU8 {
    fn to_float(&self) -> ColorRgbF64 {
        ColorRgbF64 {
            r: self.r as f64 / 255.,
            g: self.g as f64 / 255.,
            b: self.b as f64 / 255.,
        }
    }
}

#[deriving(Show)]
struct ColorRgbF64 {
    r: f64,
    g: f64,
    b: f64,
}

impl ColorRgbF64 {
    fn to_int(&self) -> ColorRgbU8 {
        ColorRgbU8 {
            r: (self.r.min(1.).max(0.) * 255.).round() as u8,
            g: (self.g.min(1.).max(0.) * 255.).round() as u8,
            b: (self.b.min(1.).max(0.) * 255.).round() as u8,
        }
    }
    fn luminance(&self, cs: &ColorSpace) -> f64 {
        self.r * cs.r.Y + self.g * cs.g.Y + self.b * cs.b.Y
    }
    fn normalize(&self) -> ColorRgbF64 {
        let m = self.r.max(self.g).max(self.b);
        ColorRgbF64 {
            r: self.r.div(&m),
            g: self.g.div(&m),
            b: self.b.div(&m),
        }
    }
    fn constrain(&self) -> ColorRgbF64 {
        let w = 0f64.min(self.r).min(self.g).min(self.b);
        ColorRgbF64 {
            r: self.r - w,
            g: self.g - w,
            b: self.b - w,
        }
    }
    fn encode_srgb(&self) -> ColorRgbF64 {
        fn encode(x: f64) -> f64 {
            if x <= 0.0031308 {
                x * 12.92
            } else {
                x.powf(2.4f64.recip()) * (1. + 0.055) - 0.055
            }
        }
        ColorRgbF64 {
            r: encode(self.r),
            g: encode(self.g),
            b: encode(self.b),
        }
    }
    fn decode_srgb(&self) -> ColorRgbF64 {
        fn decode(x: f64) -> f64 {
            if x <= 0.04045 {
                x / 12.92
            } else {
                ((x + 0.055) / (1. + 0.055)).powf(2.4)
            }
        }
        ColorRgbF64 {
            r: decode(self.r),
            g: decode(self.g),
            b: decode(self.b),
        }
    }
    fn from_hue(hue: f64) -> ColorRgbF64 {
        let x = 1. - (hue % 2. - 1.).abs();
        match hue {
            h if h >= 0. && h < 1. => ColorRgbF64 { r: 1., g: x, b: 0. },
            h if h >= 1. && h < 2. => ColorRgbF64 { r: x, g: 1., b: 0. },
            h if h >= 2. && h < 3. => ColorRgbF64 { r: 0., g: 1., b: x },
            h if h >= 3. && h < 4. => ColorRgbF64 { r: 0., g: x, b: 1. },
            h if h >= 4. && h < 5. => ColorRgbF64 { r: x, g: 0., b: 1. },
            h if h >= 5. && h < 6. => ColorRgbF64 { r: 1., g: 0., b: x },
            _ => unreachable!(),
        }
    }
    fn target_luminance(&self, lum: f64, cs: &ColorSpace) -> ColorRgbF64 {
        let l = self.luminance(cs);
        if l < lum {
            let d = (lum - 1.) / (l - 1.);
            self * d + ColorRgbF64::white() * (1. - d)
        } else {
            self * (lum / l)
        }
    }
    fn white() -> ColorRgbF64 {
        ColorRgbF64 {
            r: 1.,
            g: 1.,
            b: 1.,
        }
    }
}

impl Add<ColorRgbF64, ColorRgbF64> for ColorRgbF64 {
    fn add(&self, o: &ColorRgbF64) -> ColorRgbF64 {
        ColorRgbF64 {
            r: self.r.add(&o.r),
            g: self.g.add(&o.g),
            b: self.b.add(&o.b),
        }
    }
}

impl Mul<f64, ColorRgbF64> for ColorRgbF64 {
    fn mul(&self, o: &f64) -> ColorRgbF64 {
        ColorRgbF64 {
            r: self.r.mul(o),
            g: self.g.mul(o),
            b: self.b.mul(o),
        }
    }
}

impl Div<f64, ColorRgbF64> for ColorRgbF64 {
    fn div(&self, o: &f64) -> ColorRgbF64 {
        ColorRgbF64 {
            r: self.r.div(o),
            g: self.g.div(o),
            b: self.b.div(o),
        }
    }
}

fn rainbow_username() {
    let s = "ABCDEFGHI";
    let len = s.len();
    let num = len - 1;
    let lo = 400;
    let hi = 650;
    let colors = range(0, len).map(|i| {
        let xyz = ColorXyz::from_wavelength(lo + (num - i) * (hi - lo) / num);
        (xyz.to_rgb(&SRGB).constrain().normalize() + ColorRgbF64::white() * 0.1).normalize()
    }).collect::<Vec<ColorRgbF64>>();
    let minlum = colors.iter().fold(1f64, |s, c| {
        s.min(c.luminance(&SRGB))
    });
    for c in colors.iter().map(|c| {
        (c * minlum / c.luminance(&SRGB)).encode_srgb().to_int()
    }) {
        println!("{:02X}{:02X}{:02X}", c.r, c.g, c.b);
    }
}

fn irc_nick_colors() {
    let num = 9u;
    for c in range(0, num).map(|i| {
        let hue = i as f64 * (6. / num as f64);
        ColorRgbF64::from_hue(hue).target_luminance(0.5, &SRGB).encode_srgb().to_int()
    }) {
        println!("{:02X}{:02X}{:02X}", c.r, c.g, c.b);
    }
}

fn sample(w: f64, t: f64) -> f64 {
    let h = 6.62606957E-34;
    let c = 299792458.;
    let k = 1.3806488E-23;
    let v = c / w;
    (2. * h * v.powi(3)) / (c.powi(2) * (((h * v) / (k * t)).exp() - 1.))
}

fn black_body(temp: f64) -> ColorXyz {
    tables::CIE_COLOR_MATCH.iter().enumerate().map(|(wave, col)| {
        let energy = sample((wave as f64 + 390.) * 1E-9, temp);
        ColorXyz::from_array(col) * energy
    }).sum()
}

fn stuff() {
    for i in range(0i, 14) {
        let i = i as f64 * 100. + 1000.;
        let c = black_body(i).to_rgb(&SRGB).constrain().normalize().encode_srgb().to_int();
        println!("{:02X}{:02X}{:02X}", c.r, c.g, c.b);
    }
}

fn main() {
    stuff()
}
<|endoftext|>