<commit_before>// By compiling this file we check that all the intrinsics we care about continue to be provided by
// the `compiler_builtins` crate regardless of the changes we make to it. If we, by mistake, stop
// compiling a C implementation and forget to implement that intrinsic in Rust, this file will fail
// to link due to the missing intrinsic (symbol).

#![allow(unused_features)]
#![cfg_attr(thumb, no_main)]
#![deny(dead_code)]
#![feature(asm)]
#![feature(compiler_builtins_lib)]
#![feature(lang_items)]
#![feature(start)]
#![feature(allocator_api)]
#![no_std]

extern crate panic_handler;

#[cfg(all(not(thumb), not(windows)))]
#[link(name = "c")]
extern "C" {}

// Every function in this module maps will be lowered to an intrinsic by LLVM, if the platform
// doesn't have native support for the operation used in the function. ARM has a naming convention
// convention for its intrinsics that's different from other architectures; that's why some function
// have an additional comment: the function name is the ARM name for the intrinsic and the comment
// in the non-ARM name for the intrinsic.
mod intrinsics {
    // trunccdfsf2
    pub fn aeabi_d2f(x: f64) -> f32 {
        // This is only implemented in C currently, so only test it there.
        #[cfg(feature = "c")]
        return x as f32;
        #[cfg(not(feature = "c"))]
        {
            drop(x);
            0.0
        }
    }

    // fixdfsi
    pub fn aeabi_d2i(x: f64) -> i32 {
        x as i32
    }

    // fixdfdi
    pub fn aeabi_d2l(x: f64) -> i64 {
        x as i64
    }

    // fixunsdfsi
    pub fn aeabi_d2uiz(x: f64) -> u32 {
        x as u32
    }

    // fixunsdfdi
    pub fn aeabi_d2ulz(x: f64) -> u64 {
        x as u64
    }

    // adddf3
    pub fn aeabi_dadd(a: f64, b: f64) -> f64 {
        a + b
    }

    // eqdf2
    pub fn aeabi_dcmpeq(a: f64, b: f64) -> bool {
        a == b
    }

    // gtdf2
    pub fn aeabi_dcmpgt(a: f64, b: f64) -> bool {
        a > b
    }

    // ltdf2
    pub fn aeabi_dcmplt(a: f64, b: f64) -> bool {
        a < b
    }

    // divdf3
    pub fn aeabi_ddiv(a: f64, b: f64) -> f64 {
        a / b
    }

    // muldf3
    pub fn aeabi_dmul(a: f64, b: f64) -> f64 {
        a * b
    }

    // subdf3
    pub fn aeabi_dsub(a: f64, b: f64) -> f64 {
        a - b
    }

    // extendsfdf2
    pub fn aeabi_f2d(x: f32) -> f64 {
        x as f64
    }

    // fixsfsi
    pub fn aeabi_f2iz(x: f32) -> i32 {
        x as i32
    }

    // fixsfdi
    pub fn aeabi_f2lz(x: f32) -> i64 {
        x as i64
    }

    // fixunssfsi
    pub fn aeabi_f2uiz(x: f32) -> u32 {
        x as u32
    }

    // fixunssfdi
    pub fn aeabi_f2ulz(x: f32) -> u64 {
        x as u64
    }

    // addsf3
    pub fn aeabi_fadd(a: f32, b: f32) -> f32 {
        a + b
    }

    // eqsf2
    pub fn aeabi_fcmpeq(a: f32, b: f32) -> bool {
        a == b
    }

    // gtsf2
    pub fn aeabi_fcmpgt(a: f32, b: f32) -> bool {
        a > b
    }

    // ltsf2
    pub fn aeabi_fcmplt(a: f32, b: f32) -> bool {
        a < b
    }

    // divsf3
    pub fn aeabi_fdiv(a: f32, b: f32) -> f32 {
        a / b
    }

    // mulsf3
    pub fn aeabi_fmul(a: f32, b: f32) -> f32 {
        a * b
    }

    // subsf3
    pub fn aeabi_fsub(a: f32, b: f32) -> f32 {
        a - b
    }

    // floatsidf
    pub fn aeabi_i2d(x: i32) -> f64 {
        x as f64
    }

    // floatsisf
    pub fn aeabi_i2f(x: i32) -> f32 {
        x as f32
    }

    pub fn aeabi_idiv(a: i32, b: i32) -> i32 {
        a.wrapping_div(b)
    }

    pub fn aeabi_idivmod(a: i32, b: i32) -> i32 {
        a % b
    }

    // floatdidf
    pub fn aeabi_l2d(x: i64) -> f64 {
        x as f64
    }

    // floatdisf
    pub fn aeabi_l2f(x: i64) -> f32 {
        x as f32
    }

    // divdi3
    pub fn aeabi_ldivmod(a: i64, b: i64) -> i64 {
        a / b
    }

    // muldi3
    pub fn aeabi_lmul(a: i64, b: i64) -> i64 {
        a.wrapping_mul(b)
    }

    // floatunsidf
    pub fn aeabi_ui2d(x: u32) -> f64 {
        x as f64
    }

    // floatunsisf
    pub fn aeabi_ui2f(x: u32) -> f32 {
        x as f32
    }

    pub fn aeabi_uidiv(a: u32, b: u32) -> u32 {
        a / b
    }

    pub fn aeabi_uidivmod(a: u32, b: u32) -> u32 {
        a % b
    }

    // floatundidf
    pub fn aeabi_ul2d(x: u64) -> f64 {
        x as f64
    }

    // floatundisf
    pub fn aeabi_ul2f(x: u64) -> f32 {
        x as f32
    }

    // udivdi3
    pub fn aeabi_uldivmod(a: u64, b: u64) -> u64 {
        a * b
    }

    pub fn moddi3(a: i64, b: i64) -> i64 {
        a % b
    }

    pub fn mulodi4(a: i64, b: i64) -> i64 {
        a * b
    }

    pub fn umoddi3(a: u64, b: u64) -> u64 {
        a % b
    }

    pub fn muloti4(a: u128, b: u128) -> Option<u128> {
        a.checked_mul(b)
    }

    pub fn multi3(a: u128, b: u128) -> u128 {
        a.wrapping_mul(b)
    }

    pub fn ashlti3(a: u128, b: usize) -> u128 {
        a >> b
    }

    pub fn ashrti3(a: u128, b: usize) -> u128 {
        a << b
    }

    pub fn lshrti3(a: i128, b: usize) -> i128 {
        a >> b
    }

    pub fn udivti3(a: u128, b: u128) -> u128 {
        a / b
    }

    pub fn umodti3(a: u128, b: u128) -> u128 {
        a % b
    }

    pub fn divti3(a: i128, b: i128) -> i128 {
        a / b
    }

    pub fn modti3(a: i128, b: i128) -> i128 {
        a % b
    }

    pub fn udivsi3(a: u32, b: u32) -> u32 {
        a / b
    }
}

fn run() {
    use intrinsics::*;

    // A copy of "test::black_box". Used to prevent LLVM from optimizing away the intrinsics during LTO
    fn bb<T>(dummy: T) -> T {
        unsafe { asm!("" : : "r"(&dummy)) }
        dummy
    }

    bb(aeabi_d2f(bb(2.)));
    bb(aeabi_d2i(bb(2.)));
    bb(aeabi_d2l(bb(2.)));
    bb(aeabi_d2uiz(bb(2.)));
    bb(aeabi_d2ulz(bb(2.)));
    bb(aeabi_dadd(bb(2.), bb(3.)));
    bb(aeabi_dcmpeq(bb(2.), bb(3.)));
    bb(aeabi_dcmpgt(bb(2.), bb(3.)));
    bb(aeabi_dcmplt(bb(2.), bb(3.)));
    bb(aeabi_ddiv(bb(2.), bb(3.)));
    bb(aeabi_dmul(bb(2.), bb(3.)));
    bb(aeabi_dsub(bb(2.), bb(3.)));
    bb(aeabi_f2d(bb(2.)));
    bb(aeabi_f2iz(bb(2.)));
    bb(aeabi_f2lz(bb(2.)));
    bb(aeabi_f2uiz(bb(2.)));
    bb(aeabi_f2ulz(bb(2.)));
    bb(aeabi_fadd(bb(2.), bb(3.)));
    bb(aeabi_fcmpeq(bb(2.), bb(3.)));
    bb(aeabi_fcmpgt(bb(2.), bb(3.)));
    bb(aeabi_fcmplt(bb(2.), bb(3.)));
    bb(aeabi_fdiv(bb(2.), bb(3.)));
    bb(aeabi_fmul(bb(2.), bb(3.)));
    bb(aeabi_fsub(bb(2.), bb(3.)));
    bb(aeabi_i2d(bb(2)));
    bb(aeabi_i2f(bb(2)));
    bb(aeabi_idiv(bb(2), bb(3)));
    bb(aeabi_idivmod(bb(2), bb(3)));
    bb(aeabi_l2d(bb(2)));
    bb(aeabi_l2f(bb(2)));
    bb(aeabi_ldivmod(bb(2), bb(3)));
    bb(aeabi_lmul(bb(2), bb(3)));
    bb(aeabi_ui2d(bb(2)));
    bb(aeabi_ui2f(bb(2)));
    bb(aeabi_uidiv(bb(2), bb(3)));
    bb(aeabi_uidivmod(bb(2), bb(3)));
    bb(aeabi_ul2d(bb(2)));
    bb(aeabi_ul2f(bb(2)));
    bb(aeabi_uldivmod(bb(2), bb(3)));
    bb(moddi3(bb(2), bb(3)));
    bb(mulodi4(bb(2), bb(3)));
    bb(umoddi3(bb(2), bb(3)));
    bb(muloti4(bb(2), bb(2)));
    bb(multi3(bb(2), bb(2)));
    bb(ashlti3(bb(2), bb(2)));
    bb(ashrti3(bb(2), bb(2)));
    bb(lshrti3(bb(2), bb(2)));
    bb(udivti3(bb(2), bb(2)));
    bb(umodti3(bb(2), bb(2)));
    bb(divti3(bb(2), bb(2)));
    bb(modti3(bb(2), bb(2)));
    bb(udivsi3(bb(2), bb(2)));

    something_with_a_dtor(&|| assert_eq!(bb(1), 1));

    extern "C" {
        fn rust_begin_unwind();
    }
    // if bb(false) {
    unsafe {
        rust_begin_unwind();
    }
    // }
}

fn something_with_a_dtor(f: &Fn()) {
    struct A<'a>(&'a (Fn() + 'a));

    impl<'a> Drop for A<'a> {
        fn drop(&mut self) {
            (self.0)();
        }
    }
    let _a = A(f);
    f();
}

#[cfg(not(thumb))]
#[start]
fn main(_: isize, _: *const *const u8) -> isize {
    run();
    0
}

#[cfg(thumb)]
#[no_mangle]
pub fn _start() -> ! {
    run();
    loop {}
}

#[cfg(windows)]
#[link(name = "kernel32")]
#[link(name = "msvcrt")]
extern "C" {}

// ARM targets need these symbols
#[no_mangle]
pub fn __aeabi_unwind_cpp_pr0() {}

#[no_mangle]
pub fn __aeabi_unwind_cpp_pr1() {}

#[cfg(not(windows))]
#[allow(non_snake_case)]
#[no_mangle]
pub fn _Unwind_Resume() {}

#[cfg(not(windows))]
#[lang = "eh_personality"]
#[no_mangle]
pub extern "C" fn eh_personality() {}

#[cfg(all(windows, target_env = "gnu"))]
mod mingw_unwidning {
    #[no_mangle]
    pub fn rust_eh_personality() {}
    #[no_mangle]
    pub fn rust_eh_unwind_resume() {}
    #[no_mangle]
    pub fn rust_eh_register_frames() {}
    #[no_mangle]
    pub fn rust_eh_unregister_frames() {}
}
<commit_msg>Fix typo: mingw_unwinding<commit_after>// By compiling this file we check that all the intrinsics we care about continue to be provided by
// the `compiler_builtins` crate regardless of the changes we make to it. If we, by mistake, stop
// compiling a C implementation and forget to implement that intrinsic in Rust, this file will fail
// to link due to the missing intrinsic (symbol).

#![allow(unused_features)]
#![cfg_attr(thumb, no_main)]
#![deny(dead_code)]
#![feature(asm)]
#![feature(compiler_builtins_lib)]
#![feature(lang_items)]
#![feature(start)]
#![feature(allocator_api)]
#![no_std]

extern crate panic_handler;

#[cfg(all(not(thumb), not(windows)))]
#[link(name = "c")]
extern "C" {}

// Every function in this module maps will be lowered to an intrinsic by LLVM, if the platform
// doesn't have native support for the operation used in the function. ARM has a naming convention
// convention for its intrinsics that's different from other architectures; that's why some function
// have an additional comment: the function name is the ARM name for the intrinsic and the comment
// in the non-ARM name for the intrinsic.
mod intrinsics {
    // trunccdfsf2
    pub fn aeabi_d2f(x: f64) -> f32 {
        // This is only implemented in C currently, so only test it there.
        #[cfg(feature = "c")]
        return x as f32;
        #[cfg(not(feature = "c"))]
        {
            drop(x);
            0.0
        }
    }

    // fixdfsi
    pub fn aeabi_d2i(x: f64) -> i32 {
        x as i32
    }

    // fixdfdi
    pub fn aeabi_d2l(x: f64) -> i64 {
        x as i64
    }

    // fixunsdfsi
    pub fn aeabi_d2uiz(x: f64) -> u32 {
        x as u32
    }

    // fixunsdfdi
    pub fn aeabi_d2ulz(x: f64) -> u64 {
        x as u64
    }

    // adddf3
    pub fn aeabi_dadd(a: f64, b: f64) -> f64 {
        a + b
    }

    // eqdf2
    pub fn aeabi_dcmpeq(a: f64, b: f64) -> bool {
        a == b
    }

    // gtdf2
    pub fn aeabi_dcmpgt(a: f64, b: f64) -> bool {
        a > b
    }

    // ltdf2
    pub fn aeabi_dcmplt(a: f64, b: f64) -> bool {
        a < b
    }

    // divdf3
    pub fn aeabi_ddiv(a: f64, b: f64) -> f64 {
        a / b
    }

    // muldf3
    pub fn aeabi_dmul(a: f64, b: f64) -> f64 {
        a * b
    }

    // subdf3
    pub fn aeabi_dsub(a: f64, b: f64) -> f64 {
        a - b
    }

    // extendsfdf2
    pub fn aeabi_f2d(x: f32) -> f64 {
        x as f64
    }

    // fixsfsi
    pub fn aeabi_f2iz(x: f32) -> i32 {
        x as i32
    }

    // fixsfdi
    pub fn aeabi_f2lz(x: f32) -> i64 {
        x as i64
    }

    // fixunssfsi
    pub fn aeabi_f2uiz(x: f32) -> u32 {
        x as u32
    }

    // fixunssfdi
    pub fn aeabi_f2ulz(x: f32) -> u64 {
        x as u64
    }

    // addsf3
    pub fn aeabi_fadd(a: f32, b: f32) -> f32 {
        a + b
    }

    // eqsf2
    pub fn aeabi_fcmpeq(a: f32, b: f32) -> bool {
        a == b
    }

    // gtsf2
    pub fn aeabi_fcmpgt(a: f32, b: f32) -> bool {
        a > b
    }

    // ltsf2
    pub fn aeabi_fcmplt(a: f32, b: f32) -> bool {
        a < b
    }

    // divsf3
    pub fn aeabi_fdiv(a: f32, b: f32) -> f32 {
        a / b
    }

    // mulsf3
    pub fn aeabi_fmul(a: f32, b: f32) -> f32 {
        a * b
    }

    // subsf3
    pub fn aeabi_fsub(a: f32, b: f32) -> f32 {
        a - b
    }

    // floatsidf
    pub fn aeabi_i2d(x: i32) -> f64 {
        x as f64
    }

    // floatsisf
    pub fn aeabi_i2f(x: i32) -> f32 {
        x as f32
    }

    pub fn aeabi_idiv(a: i32, b: i32) -> i32 {
        a.wrapping_div(b)
    }

    pub fn aeabi_idivmod(a: i32, b: i32) -> i32 {
        a % b
    }

    // floatdidf
    pub fn aeabi_l2d(x: i64) -> f64 {
        x as f64
    }

    // floatdisf
    pub fn aeabi_l2f(x: i64) -> f32 {
        x as f32
    }

    // divdi3
    pub fn aeabi_ldivmod(a: i64, b: i64) -> i64 {
        a / b
    }

    // muldi3
    pub fn aeabi_lmul(a: i64, b: i64) -> i64 {
        a.wrapping_mul(b)
    }

    // floatunsidf
    pub fn aeabi_ui2d(x: u32) -> f64 {
        x as f64
    }

    // floatunsisf
    pub fn aeabi_ui2f(x: u32) -> f32 {
        x as f32
    }

    pub fn aeabi_uidiv(a: u32, b: u32) -> u32 {
        a / b
    }

    pub fn aeabi_uidivmod(a: u32, b: u32) -> u32 {
        a % b
    }

    // floatundidf
    pub fn aeabi_ul2d(x: u64) -> f64 {
        x as f64
    }

    // floatundisf
    pub fn aeabi_ul2f(x: u64) -> f32 {
        x as f32
    }

    // udivdi3
    pub fn aeabi_uldivmod(a: u64, b: u64) -> u64 {
        a * b
    }

    pub fn moddi3(a: i64, b: i64) -> i64 {
        a % b
    }

    pub fn mulodi4(a: i64, b: i64) -> i64 {
        a * b
    }

    pub fn umoddi3(a: u64, b: u64) -> u64 {
        a % b
    }

    pub fn muloti4(a: u128, b: u128) -> Option<u128> {
        a.checked_mul(b)
    }

    pub fn multi3(a: u128, b: u128) -> u128 {
        a.wrapping_mul(b)
    }

    pub fn ashlti3(a: u128, b: usize) -> u128 {
        a >> b
    }

    pub fn ashrti3(a: u128, b: usize) -> u128 {
        a << b
    }

    pub fn lshrti3(a: i128, b: usize) -> i128 {
        a >> b
    }

    pub fn udivti3(a: u128, b: u128) -> u128 {
        a / b
    }

    pub fn umodti3(a: u128, b: u128) -> u128 {
        a % b
    }

    pub fn divti3(a: i128, b: i128) -> i128 {
        a / b
    }

    pub fn modti3(a: i128, b: i128) -> i128 {
        a % b
    }

    pub fn udivsi3(a: u32, b: u32) -> u32 {
        a / b
    }
}

fn run() {
    use intrinsics::*;

    // A copy of "test::black_box". Used to prevent LLVM from optimizing away the intrinsics during LTO
    fn bb<T>(dummy: T) -> T {
        unsafe { asm!("" : : "r"(&dummy)) }
        dummy
    }

    bb(aeabi_d2f(bb(2.)));
    bb(aeabi_d2i(bb(2.)));
    bb(aeabi_d2l(bb(2.)));
    bb(aeabi_d2uiz(bb(2.)));
    bb(aeabi_d2ulz(bb(2.)));
    bb(aeabi_dadd(bb(2.), bb(3.)));
    bb(aeabi_dcmpeq(bb(2.), bb(3.)));
    bb(aeabi_dcmpgt(bb(2.), bb(3.)));
    bb(aeabi_dcmplt(bb(2.), bb(3.)));
    bb(aeabi_ddiv(bb(2.), bb(3.)));
    bb(aeabi_dmul(bb(2.), bb(3.)));
    bb(aeabi_dsub(bb(2.), bb(3.)));
    bb(aeabi_f2d(bb(2.)));
    bb(aeabi_f2iz(bb(2.)));
    bb(aeabi_f2lz(bb(2.)));
    bb(aeabi_f2uiz(bb(2.)));
    bb(aeabi_f2ulz(bb(2.)));
    bb(aeabi_fadd(bb(2.), bb(3.)));
    bb(aeabi_fcmpeq(bb(2.), bb(3.)));
    bb(aeabi_fcmpgt(bb(2.), bb(3.)));
    bb(aeabi_fcmplt(bb(2.), bb(3.)));
    bb(aeabi_fdiv(bb(2.), bb(3.)));
    bb(aeabi_fmul(bb(2.), bb(3.)));
    bb(aeabi_fsub(bb(2.), bb(3.)));
    bb(aeabi_i2d(bb(2)));
    bb(aeabi_i2f(bb(2)));
    bb(aeabi_idiv(bb(2), bb(3)));
    bb(aeabi_idivmod(bb(2), bb(3)));
    bb(aeabi_l2d(bb(2)));
    bb(aeabi_l2f(bb(2)));
    bb(aeabi_ldivmod(bb(2), bb(3)));
    bb(aeabi_lmul(bb(2), bb(3)));
    bb(aeabi_ui2d(bb(2)));
    bb(aeabi_ui2f(bb(2)));
    bb(aeabi_uidiv(bb(2), bb(3)));
    bb(aeabi_uidivmod(bb(2), bb(3)));
    bb(aeabi_ul2d(bb(2)));
    bb(aeabi_ul2f(bb(2)));
    bb(aeabi_uldivmod(bb(2), bb(3)));
    bb(moddi3(bb(2), bb(3)));
    bb(mulodi4(bb(2), bb(3)));
    bb(umoddi3(bb(2), bb(3)));
    bb(muloti4(bb(2), bb(2)));
    bb(multi3(bb(2), bb(2)));
    bb(ashlti3(bb(2), bb(2)));
    bb(ashrti3(bb(2), bb(2)));
    bb(lshrti3(bb(2), bb(2)));
    bb(udivti3(bb(2), bb(2)));
    bb(umodti3(bb(2), bb(2)));
    bb(divti3(bb(2), bb(2)));
    bb(modti3(bb(2), bb(2)));
    bb(udivsi3(bb(2), bb(2)));

    something_with_a_dtor(&|| assert_eq!(bb(1), 1));

    extern "C" {
        fn rust_begin_unwind();
    }
    // if bb(false) {
    unsafe {
        rust_begin_unwind();
    }
    // }
}

fn something_with_a_dtor(f: &Fn()) {
    struct A<'a>(&'a (Fn() + 'a));

    impl<'a> Drop for A<'a> {
        fn drop(&mut self) {
            (self.0)();
        }
    }
    let _a = A(f);
    f();
}

#[cfg(not(thumb))]
#[start]
fn main(_: isize, _: *const *const u8) -> isize {
    run();
    0
}

#[cfg(thumb)]
#[no_mangle]
pub fn _start() -> ! {
    run();
    loop {}
}

#[cfg(windows)]
#[link(name = "kernel32")]
#[link(name = "msvcrt")]
extern "C" {}

// ARM targets need these symbols
#[no_mangle]
pub fn __aeabi_unwind_cpp_pr0() {}

#[no_mangle]
pub fn __aeabi_unwind_cpp_pr1() {}

#[cfg(not(windows))]
#[allow(non_snake_case)]
#[no_mangle]
pub fn _Unwind_Resume() {}

#[cfg(not(windows))]
#[lang = "eh_personality"]
#[no_mangle]
pub extern "C" fn eh_personality() {}

#[cfg(all(windows, target_env = "gnu"))]
mod mingw_unwinding {
    #[no_mangle]
    pub fn rust_eh_personality() {}
    #[no_mangle]
    pub fn rust_eh_unwind_resume() {}
    #[no_mangle]
    pub fn rust_eh_register_frames() {}
    #[no_mangle]
    pub fn rust_eh_unregister_frames() {}
}
<|endoftext|>


<commit_before>extern crate mqtt;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate clap;
extern crate uuid;

use std::net::TcpStream;
use std::io::{self, Write};

use clap::{App, Arg};

use uuid::Uuid;

use mqtt::{Encodable, Decodable, QualityOfService};
use mqtt::packet::*;
use mqtt::control::variable_header::ConnectReturnCode;
use mqtt::TopicFilter;
use mqtt::control::variable_header::TopicName;

fn generate_client_id() -> String {
    format!("/MQTT/rust/{}", Uuid::new_v4().to_simple_string())
}

fn main() {
    env_logger::init().unwrap();

    let matches = App::new("sub-client")
                    .author("Y. T. Chung <zonyitoo@gmail.com>")
                    .arg(Arg::with_name("HOST").short("h").long("host").takes_value(true).required(true)
                            .help("MQTT host"))
                    .arg(Arg::with_name("SUBSCRIBE").short("s").long("subscribe").takes_value(true)
                            .multiple(true).required(true).help("Channel filter to subscribe"))
                    .arg(Arg::with_name("USER_NAME").short("u").long("username").takes_value(true)
                            .help("Login user name"))
                    .arg(Arg::with_name("PASSWORD").short("p").long("password").takes_value(true)
                            .help("Password"))
                    .arg(Arg::with_name("CLIENT_ID").short("i").long("client-identifier").takes_value(true)
                            .help("Client identifier"))
                    .get_matches();

    let server_addr = matches.value_of("HOST").unwrap();
    let client_id = matches.value_of("CLIENT_ID")
        .map(|x| x.to_owned())
        .unwrap_or_else(generate_client_id);
    let channel_filters: Vec<(TopicFilter, QualityOfService)>
        = matches.values_of("SUBSCRIBE").unwrap()
                 .iter()
                 .map(|c| (TopicFilter::new_checked(c.to_string()).unwrap(), QualityOfService::Level0))
                 .collect();

    print!("Connecting to {:?} ... ", server_addr);
    let mut stream = TcpStream::connect(server_addr).unwrap();
    println!("Connected!");

    println!("Client identifier {:?}", client_id);
    let mut conn = ConnectPacket::new(client_id.to_owned());
    conn.set_clean_session(true);
    let mut buf = Vec::new();
    conn.encode(&mut buf).unwrap();
    stream.write_all(&buf[..]).unwrap();

    let connack = ConnackPacket::decode(&mut stream).unwrap();
    trace!("CONNACK {:?}", connack);

    if connack.connect_return_code() != ConnectReturnCode::ConnectionAccepted {
        panic!("Failed to connect to server, return code {:?}", connack.connect_return_code());
    }

    println!("Applying channel filters {:?} ...", channel_filters);
    let sub = SubscribePacket::new(10, channel_filters);
    let mut buf = Vec::new();
    sub.encode(&mut buf).unwrap();
    stream.write_all(&buf[..]).unwrap();

    let channels: Vec<TopicName> = matches.values_of("SUBSCRIBE").unwrap()
                                          .iter().map(|c| TopicName::new(c.to_string()).unwrap())
                                          .collect();

    let user_name = matches.value_of("USER_NAME").unwrap_or("<anonym>");

    let mut stdin = io::stdin();
    loop {
        print!("{}: ", user_name);
        io::stdout().flush().unwrap();

        let mut line = String::new();
        stdin.read_line(&mut line).unwrap();

        match line.trim() {
            "" => continue,
            _ => {},
        }

        let message = format!("{}: {}", user_name, line.trim());

        for chan in channels.iter() {
            let publish_packet = PublishPacket::new(chan.clone(), QoSWithPacketIdentifier::Level0,
                                                    message.as_bytes().to_vec());
            let mut buf = Vec::new();
            publish_packet.encode(&mut buf).unwrap();
            stream.write_all(&buf[..]).unwrap();
        }
    }
}
<commit_msg>just trim right<commit_after>extern crate mqtt;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate clap;
extern crate uuid;

use std::net::TcpStream;
use std::io::{self, Write};

use clap::{App, Arg};

use uuid::Uuid;

use mqtt::{Encodable, Decodable, QualityOfService};
use mqtt::packet::*;
use mqtt::control::variable_header::ConnectReturnCode;
use mqtt::TopicFilter;
use mqtt::control::variable_header::TopicName;

fn generate_client_id() -> String {
    format!("/MQTT/rust/{}", Uuid::new_v4().to_simple_string())
}

fn main() {
    env_logger::init().unwrap();

    let matches = App::new("sub-client")
                    .author("Y. T. Chung <zonyitoo@gmail.com>")
                    .arg(Arg::with_name("HOST").short("h").long("host").takes_value(true).required(true)
                            .help("MQTT host"))
                    .arg(Arg::with_name("SUBSCRIBE").short("s").long("subscribe").takes_value(true)
                            .multiple(true).required(true).help("Channel filter to subscribe"))
                    .arg(Arg::with_name("USER_NAME").short("u").long("username").takes_value(true)
                            .help("Login user name"))
                    .arg(Arg::with_name("PASSWORD").short("p").long("password").takes_value(true)
                            .help("Password"))
                    .arg(Arg::with_name("CLIENT_ID").short("i").long("client-identifier").takes_value(true)
                            .help("Client identifier"))
                    .get_matches();

    let server_addr = matches.value_of("HOST").unwrap();
    let client_id = matches.value_of("CLIENT_ID")
        .map(|x| x.to_owned())
        .unwrap_or_else(generate_client_id);
    let channel_filters: Vec<(TopicFilter, QualityOfService)>
        = matches.values_of("SUBSCRIBE").unwrap()
                 .iter()
                 .map(|c| (TopicFilter::new_checked(c.to_string()).unwrap(), QualityOfService::Level0))
                 .collect();

    print!("Connecting to {:?} ... ", server_addr);
    let mut stream = TcpStream::connect(server_addr).unwrap();
    println!("Connected!");

    println!("Client identifier {:?}", client_id);
    let mut conn = ConnectPacket::new(client_id.to_owned());
    conn.set_clean_session(true);
    let mut buf = Vec::new();
    conn.encode(&mut buf).unwrap();
    stream.write_all(&buf[..]).unwrap();

    let connack = ConnackPacket::decode(&mut stream).unwrap();
    trace!("CONNACK {:?}", connack);

    if connack.connect_return_code() != ConnectReturnCode::ConnectionAccepted {
        panic!("Failed to connect to server, return code {:?}", connack.connect_return_code());
    }

    println!("Applying channel filters {:?} ...", channel_filters);
    let sub = SubscribePacket::new(10, channel_filters);
    let mut buf = Vec::new();
    sub.encode(&mut buf).unwrap();
    stream.write_all(&buf[..]).unwrap();

    let channels: Vec<TopicName> = matches.values_of("SUBSCRIBE").unwrap()
                                          .iter().map(|c| TopicName::new(c.to_string()).unwrap())
                                          .collect();

    let user_name = matches.value_of("USER_NAME").unwrap_or("<anonym>");

    let mut stdin = io::stdin();
    loop {
        print!("{}: ", user_name);
        io::stdout().flush().unwrap();

        let mut line = String::new();
        stdin.read_line(&mut line).unwrap();

        match line.trim_right() {
            "" => continue,
            _ => {},
        }

        let message = format!("{}: {}", user_name, line.trim_right());

        for chan in channels.iter() {
            let publish_packet = PublishPacket::new(chan.clone(), QoSWithPacketIdentifier::Level0,
                                                    message.as_bytes().to_vec());
            let mut buf = Vec::new();
            publish_packet.encode(&mut buf).unwrap();
            stream.write_all(&buf[..]).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>use super::candidate_pow_receipt_root_record::CandidatePoWReceiptRootRecord;
use super::crosslink_record::CrosslinkRecord;
use super::fork_data::ForkData;
use super::pending_attestation_record::PendingAttestationRecord;
use super::shard_committee::ShardCommittee;
use super::shard_reassignment_record::ShardReassignmentRecord;
use super::validator_record::ValidatorRecord;
use super::Hash256;

#[derive(Debug, PartialEq, Clone)]
pub struct BeaconState {
    // Misc
    pub slot: u64,
    pub genesis_time: u64,
    pub fork_data: ForkData,

    // Validator registry
    pub validator_registry: Vec<ValidatorRecord>,
    pub validator_registry_latest_change_slot: u64,
    pub validator_registry_exit_count: u64,
    pub validator_registry_delta_chain_tip: Hash256,

    // Randomness and committees
    pub randao_mix: Hash256,
    pub next_seed: Hash256,
    pub shard_committees_at_slots: Vec<Vec<ShardCommittee>>,
    pub persistent_committees: Vec<Vec<u32>>,
    pub persistent_committee_reassignments: Vec<ShardReassignmentRecord>,

    // Finality
    pub previous_justified_slot: u64,
    pub justified_slot: u64,
    pub justification_bitfield: u64,
    pub finalized_slot: u64,

    // Recent state
    pub latest_crosslinks: Vec<CrosslinkRecord>,
    pub latest_block_roots: Vec<Hash256>,
    pub latest_penalized_exit_balances: Vec<u64>,
    pub latest_attestations: Vec<PendingAttestationRecord>,

    // PoW receipt root
    pub processed_pow_receipt_root: Hash256,
    pub candidate_pow_receipt_roots: Vec<CandidatePoWReceiptRootRecord>,
}
<commit_msg>Add canonical_hash method to `BeaconState`<commit_after>use super::candidate_pow_receipt_root_record::CandidatePoWReceiptRootRecord;
use super::crosslink_record::CrosslinkRecord;
use super::fork_data::ForkData;
use super::pending_attestation_record::PendingAttestationRecord;
use super::shard_committee::ShardCommittee;
use super::shard_reassignment_record::ShardReassignmentRecord;
use super::validator_record::ValidatorRecord;
use super::Hash256;

#[derive(Debug, PartialEq, Clone)]
pub struct BeaconState {
    // Misc
    pub slot: u64,
    pub genesis_time: u64,
    pub fork_data: ForkData,

    // Validator registry
    pub validator_registry: Vec<ValidatorRecord>,
    pub validator_registry_latest_change_slot: u64,
    pub validator_registry_exit_count: u64,
    pub validator_registry_delta_chain_tip: Hash256,

    // Randomness and committees
    pub randao_mix: Hash256,
    pub next_seed: Hash256,
    pub shard_committees_at_slots: Vec<Vec<ShardCommittee>>,
    pub persistent_committees: Vec<Vec<u32>>,
    pub persistent_committee_reassignments: Vec<ShardReassignmentRecord>,

    // Finality
    pub previous_justified_slot: u64,
    pub justified_slot: u64,
    pub justification_bitfield: u64,
    pub finalized_slot: u64,

    // Recent state
    pub latest_crosslinks: Vec<CrosslinkRecord>,
    pub latest_block_roots: Vec<Hash256>,
    pub latest_penalized_exit_balances: Vec<u64>,
    pub latest_attestations: Vec<PendingAttestationRecord>,

    // PoW receipt root
    pub processed_pow_receipt_root: Hash256,
    pub candidate_pow_receipt_roots: Vec<CandidatePoWReceiptRootRecord>,
}

impl BeaconState {
    pub fn canonical_root(&self) -> Hash256 {
        // TODO: implement tree hashing.
        // https://github.com/sigp/lighthouse/issues/70
        Hash256::zero()
    }
}
<|endoftext|>


<commit_before>//! `StructureTerminal` data description.
use super::super::resources::ResourceType;
use super::super::resources::Store;
use crate::data::RoomName;

with_base_fields_and_update_struct! {
    /// A terminal structure - a structure that has a medium capacity for storing multiple resources,
    /// and can spend energy to send any resources to another room with a terminal instantly.
    // Note: there's a field "send" which seems to always be null. It will be non-existent on a
    // terminal which has never sent any resources, and then will be updated to "null" on the first send.
    #[derive(Clone, Debug, PartialEq)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureTerminal {
        /// The current number of hit-points this structure has.
        #[serde(default)]
        pub hits: i32,
        /// The maximum number of hit-points this structure has.
        #[serde(default)]
        pub hits_max: i32,
        /// The user ID of the owner of this structure.
        pub user: Option<String>,
        /// Whether or not this structure is non-functional due to a degraded controller.
        #[serde(default, rename = "off")]
        pub disabled: bool,
        /// Total capacity for this structure.
        #[serde(rename = "storeCapacity")]
        pub capacity: i32,
        /// The game time at which this terminal will next be able to send minerals.
        #[serde(default)]
        pub cooldown_time: u32,
        /// Whether or not an attack on this structure will send an email to the owner automatically.
        pub notify_when_attacked: Option<bool>,
        /// The resources and amounts of each resource some game object holds.
        pub store: Store,
    }

    /// The update structure for an extension structure.
    #[derive(Clone, Debug)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureTerminalUpdate {
        - hits: i32,
        - hits_max: i32,
        - user: Option<String>,
        #[serde(rename = "off")]
        - disabled: bool,
        #[serde(rename = "energyCapacity")]
        - capacity: i32,
        - cooldown_time: u32,
        - notify_when_attacked: Option<bool>,
        - store: Store,
    }
}

impl StructureTerminal {
    /// Iterates over this structure's resources.
    pub fn resources(&self) -> impl Iterator<Item = (ResourceType, i32)> + '_ {
        self.store.iter()
    }
}

#[cfg(test)]
mod test {
    use serde::Deserialize;

    use super::StructureTerminal;

    #[test]
    fn parse_terminal() {
        let json = json!({
            "_id": "59a5cc4f4733bb4c785ec4e7",
            "cooldownTime": 38432852,
            "hits": 3000,
            "hitsMax": 3000,
            "notifyWhenAttacked": true,
            "room": "W39N49",
            "send": null,
            "store": {
                "X": 50189,
                "XGH2O": 0,
                "energy": 25000
            },
            "storeCapacity": 300000,
            "type": "terminal",
            "user": "5788389e3fd9069e6b546e2d",
            "x": 4,
            "y": 9
        });

        let obj = StructureTerminal::deserialize(json).unwrap();

        match obj {
            StructureTerminal {
                capacity: 300000,
                hits: 3000,
                hits_max: 3000,
                notify_when_attacked: Some(true),
                cooldown_time: 38432852,
                disabled: false,
                x: 4,
                y: 9,
                ref user,
                ref id,
                ref store,
                ..
            } if *user == Some("5788389e3fd9069e6b546e2d".to_string())
                && id == "59a5cc4f4733bb4c785ec4e7"
                && *store == store! {Energy: 25000, Catalyst: 50189} =>
            {
                ()
            }

            other => panic!(
                "expected pre-set StructureTerminal to match, found {:#?}",
                other
            ),
        }
    }

    #[test]
    fn parse_with_null_cooldown() {
        // note: not actual server data, reconstructed from two instances
        //  - it's hard to find a null terminal cooldown.
        let json = json!({
            "_id": "59a5cc4f4733bb4c785ec4e7",
            "hits": 3000,
            "hitsMax": 3000,
            "notifyWhenAttacked": true,
            "room": "W39N49",
            "send": null,
            "store": {},
            "storeCapacity": 300000,
            "type": "terminal",
            "user": "5788389e3fd9069e6b546e2d",
            "x": 4,
            "y": 9
        });

        let obj = StructureTerminal::deserialize(json).unwrap();

        assert_eq!(obj.cooldown_time, 0);
    }

    #[test]
    fn parse_npc_terminal_with_null_store() {
        let json = json!({
            "_id": "57cd3a30c0551957424a1f0b",
            "room": "E40N40",
            "store": {
                "H": null,
                "K": null,
                "L": null,
                "O": null,
                "U": null,
                "X": null,
                "Z": null,
                "energy": 0,
                "power": null
            },
            "storeCapacity": 0,
            "type": "terminal",
            "x": 35,
            "y": 45
        });
        let obj = StructureTerminal::deserialize(json).unwrap();
        assert_eq!(obj.store, store!());
    }
}
<commit_msg>Improved fix for parse_npc_terminal_... test<commit_after>//! `StructureTerminal` data description.
use super::super::resources::ResourceType;
use super::super::resources::Store;
use crate::data::RoomName;

with_base_fields_and_update_struct! {
    /// A terminal structure - a structure that has a medium capacity for storing multiple resources,
    /// and can spend energy to send any resources to another room with a terminal instantly.
    // Note: there's a field "send" which seems to always be null. It will be non-existent on a
    // terminal which has never sent any resources, and then will be updated to "null" on the first send.
    #[derive(Clone, Debug, PartialEq)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureTerminal {
        /// The current number of hit-points this structure has.
        #[serde(default)]
        pub hits: i32,
        /// The maximum number of hit-points this structure has.
        #[serde(default)]
        pub hits_max: i32,
        /// The user ID of the owner of this structure.
        pub user: Option<String>,
        /// Whether or not this structure is non-functional due to a degraded controller.
        #[serde(default, rename = "off")]
        pub disabled: bool,
        /// Total capacity for this structure.
        #[serde(rename = "storeCapacity")]
        pub capacity: i32,
        /// The game time at which this terminal will next be able to send minerals.
        #[serde(default)]
        pub cooldown_time: u32,
        /// Whether or not an attack on this structure will send an email to the owner automatically.
        #[serde(default)]
        pub notify_when_attacked: bool,
        /// The resources and amounts of each resource some game object holds.
        pub store: Store,
    }

    /// The update structure for an extension structure.
    #[derive(Clone, Debug)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureTerminalUpdate {
        - hits: i32,
        - hits_max: i32,
        - user: Option<String>,
        #[serde(rename = "off")]
        - disabled: bool,
        #[serde(rename = "energyCapacity")]
        - capacity: i32,
        - cooldown_time: u32,
        - notify_when_attacked: bool,
        - store: Store,
    }
}

impl StructureTerminal {
    /// Iterates over this structure's resources.
    pub fn resources(&self) -> impl Iterator<Item = (ResourceType, i32)> + '_ {
        self.store.iter()
    }
}

#[cfg(test)]
mod test {
    use serde::Deserialize;

    use super::StructureTerminal;

    #[test]
    fn parse_terminal() {
        let json = json!({
            "_id": "59a5cc4f4733bb4c785ec4e7",
            "cooldownTime": 38432852,
            "hits": 3000,
            "hitsMax": 3000,
            "notifyWhenAttacked": true,
            "room": "W39N49",
            "send": null,
            "store": {
                "X": 50189,
                "XGH2O": 0,
                "energy": 25000
            },
            "storeCapacity": 300000,
            "type": "terminal",
            "user": "5788389e3fd9069e6b546e2d",
            "x": 4,
            "y": 9
        });

        let obj = StructureTerminal::deserialize(json).unwrap();

        match obj {
            StructureTerminal {
                capacity: 300000,
                hits: 3000,
                hits_max: 3000,
                notify_when_attacked: true,
                cooldown_time: 38432852,
                disabled: false,
                x: 4,
                y: 9,
                ref user,
                ref id,
                ref store,
                ..
            } if *user == Some("5788389e3fd9069e6b546e2d".to_string())
                && id == "59a5cc4f4733bb4c785ec4e7"
                && *store == store! {Energy: 25000, Catalyst: 50189} =>
            {
                ()
            }

            other => panic!(
                "expected pre-set StructureTerminal to match, found {:#?}",
                other
            ),
        }
    }

    #[test]
    fn parse_with_null_cooldown() {
        // note: not actual server data, reconstructed from two instances
        //  - it's hard to find a null terminal cooldown.
        let json = json!({
            "_id": "59a5cc4f4733bb4c785ec4e7",
            "hits": 3000,
            "hitsMax": 3000,
            "notifyWhenAttacked": true,
            "room": "W39N49",
            "send": null,
            "store": {},
            "storeCapacity": 300000,
            "type": "terminal",
            "user": "5788389e3fd9069e6b546e2d",
            "x": 4,
            "y": 9
        });

        let obj = StructureTerminal::deserialize(json).unwrap();

        assert_eq!(obj.cooldown_time, 0);
    }

    #[test]
    fn parse_npc_terminal_with_null_store() {
        let json = json!({
            "_id": "57cd3a30c0551957424a1f0b",
            "room": "E40N40",
            "store": {
                "H": null,
                "K": null,
                "L": null,
                "O": null,
                "U": null,
                "X": null,
                "Z": null,
                "energy": 0,
                "power": null
            },
            "storeCapacity": 0,
            "type": "terminal",
            "x": 35,
            "y": 45
        });
        let obj = StructureTerminal::deserialize(json).unwrap();
        assert_eq!(obj.store, store!());
        assert_eq!(obj.notify_when_attacked, false);
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use xi_rope::tree::Cursor;
use elapsed::ElapsedDuration;

use file;
use fall_tree::{Node, WHITESPACE, TextUnit, File, Language};
use fall_tree::search::{find_leaf_at_offset, ancestors};
use lang_fall::{LANG_FALL, highlight};

use ediproto::{ViewStateReply, Line, StyledText};
use model::{Direction, Amount, State, Editor, InputEvent, CowStr};

mod utils;

use self::utils::{move_cursor_by, cursor_offset};

#[derive(Default)]
pub struct EditorImpl {
    state: State,
}

impl Editor for EditorImpl {
    fn apply(&mut self, event: InputEvent) {
        let mut text_changed = false;
        match event {
            InputEvent::Ready => {}
            InputEvent::MoveCursor(d, a) => do_move_cursor(&mut self.state, d, a),
            InputEvent::InsertText(text) => {
                text_changed = true;
                if text == "\x08" {
                    do_backspace(&mut self.state);
                } else {
                    do_insert(&mut self.state, text);
                }
            }
            InputEvent::OpenFile(path) => {
                text_changed = true;
                do_open_file(&mut self.state, path);
            }
            InputEvent::SaveFile => do_save_file(&mut self.state),
        }
        let text: String = self.state.text.clone().into();
        if text_changed || self.state.file.is_none() {
            let file = LANG_FALL.parse(text.clone());
            self.state.file = Some(file);
        }

        modify_state(&mut self.state,
                     |state| {
                         let file = state.file.as_ref().unwrap();
                         highlight(file)
                     },
                     |state, spans| state.spans = spans
        );

        modify_state(&mut self.state,
                     |state| {
                         let mut off = cursor_offset(state);
                         let mut cursor = Cursor::new(&state.text, off);
                         while let Some(c) = cursor.next_codepoint() {
                             if !(c == ' ' || c == '\n') {
                                 break
                             }
                             off += c.len_utf8()
                         }
                         let file = state.file.as_ref().unwrap();
                         context(&file, off)
                     },
                     |state, syntax_tree| state.syntax_tree = syntax_tree
        );
    }

    fn render(&self) -> ViewStateReply {
        let mut result = ViewStateReply::new();
        render_lines(&mut result, self.state.text.lines_raw(0, self.state.text.len()), &self.state.spans);
        result.cursorX = self.state.cursor.x as i32;
        result.cursorY = self.state.cursor.y as i32;
        result.syntax_tree = self.state.syntax_tree.clone();
        if let Some(ref file) = self.state.file {
            result.lexing_time_nanos = ElapsedDuration::new(file.stats().lexing_time).nanos() as i64;
            result.parsing_time_nanos = ElapsedDuration::new(file.stats().parsing_time).nanos() as i64;
            result.reparse_len = file.stats().reparsed_region.len().as_u32() as i32;
        }
        if let Some(ref path) = self.state.file_path {
            result.file = path.display().to_string();
        }
        result.dirty = self.state.dirty;
        result
    }
}

fn render_lines<'a, L: Iterator<Item=CowStr<'a>>>(reply: &mut ViewStateReply, mut lines: L, spans: &[(u32, u32, &'static str)]) {
    let mut curr_global_offset = 0;

    let mut line_off;
    let mut curr_line: CowStr;
    macro_rules! next_line {
        () => {
            if let Some(line) = lines.next() {
                curr_line = line;
                line_off = 0;
                let _ = line_off;
            } else {
                return
            }
        }
    }
    next_line!();

    let mut line_sink = Line::new();
    macro_rules! push_line {
        () => {
            let mut line_done = Line::new();
            ::std::mem::swap(&mut line_done, &mut line_sink);
            reply.mut_lines().push(line_done);
         }
    }

    let mut events = Vec::new();
    for (i, span) in spans.iter().enumerate() {
        events.push((span.0 as usize, i as i32, false, span.2));
        events.push((span.1 as usize, -(i as i32), true, span.2));
    }
    events.sort();
    let mut events = events.into_iter();

    let mut color_stack = vec!["text"];
    macro_rules! push_range {
        ($chunk:expr) => {
            let range = {
                let mut range = StyledText::new();
                range.style = (*color_stack.last().unwrap()).to_owned();
                range.text = $chunk.to_owned();
                range
            };
            line_sink.mut_ranges().push(range);
         }
    }

    while let Some((off, _, is_close, color)) = events.next() {
        let mut l = off - curr_global_offset;
        while l > 0 {
            let effective_l = ::std::cmp::min(l, curr_line.len() - line_off);
            l -= effective_l;
            push_range!(&curr_line[line_off .. line_off + effective_l]);
            line_off += effective_l;
            if line_off == curr_line.len() {
                push_line!();
                next_line!();
            }
        }
        if is_close {
            color_stack.pop().unwrap();
        } else {
            color_stack.push(color);
        }
        curr_global_offset = off;
    }

    loop {
        push_range!(curr_line.as_ref());
        push_line!();
        next_line!();
    }
}

fn do_move_cursor(state: &mut State, direction: Direction, amount: Amount) {
    let (am_vert, am_hor): (i32, i32) = match amount {
        Amount::CHAR => (1, 1),
        Amount::PAGE => (10, ::std::i32::MAX / 2),
    };

    let (dx, dy) = match direction {
        Direction::UP => (0i32, -1 * am_vert),
        Direction::LEFT => (-1 * am_hor, 0),
        Direction::DOWN => (0, 1 * am_vert),
        Direction::RIGHT => (1 * am_hor, 0),
    };

    move_cursor_by(state, dx, dy)
}

fn do_backspace(state: &mut State) {
    let off = cursor_offset(state);
    if off == 0 { return }
    state.text.edit_str(off - 1, off, "");
    state.dirty = true;
    move_cursor_by(state, -1, 0);
}

fn do_insert(state: &mut State, text: String) {
    let dx = text.len();
    let off = cursor_offset(state);
    state.text.edit_str(off, off, &text);
    state.dirty = true;
    move_cursor_by(state, dx as i32, 0);
}

fn do_open_file(state: &mut State, path: PathBuf) {
    let text = file::get_text(&path).unwrap();
    state.text = From::from(text);
    state.dirty = false;
    state.file_path = Some(path)
}

fn do_save_file(state: &mut State) {
    if !state.dirty {
        return
    }
    if let Some(ref path) = state.file_path {
        file::put_text(path, String::from(state.text.clone()))
            .unwrap();
        state.dirty = false
    }
}

fn context(file: &File, offset: usize) -> String {

    fn go(lang: &Language, path: &[Node], level: usize, buff: &mut String) {
        assert!(path.len() > 0);
        if path.len() == 1 {
            return
        }
        let node = path[0];
        let next = path[1];
        for child in node.children() {
            if child.ty() == WHITESPACE {
                continue
            }

            let name = lang.node_type_info(child.ty()).name;
            for _ in 0..level {
                buff.push_str("  ");
            }
            if child == next {
                buff.push_str(">");
            } else {
                buff.push_str(" ");
            }
            buff.push_str(name);

            buff.push_str("\n");

            if child == next {
                go(lang, &path[1..], level + 1, buff);
            }
        }
    }
    let root = file.root();
    let mut result = String::new();
    let offset = TextUnit::from_usize(offset);
    let leaf = if let Some(leaf) = find_leaf_at_offset(root, offset).right_biased() {
        leaf
    } else {
        return String::new()
    };
    let mut path: Vec<Node> = ancestors(leaf).collect();
    path.reverse();
    go(&file.language(), &path, 0, &mut result);
    result
}

fn modify_state<R, F, C>(state: &mut State, f: F, commit: C)
    where F: FnOnce(&State) -> R + ::std::panic::UnwindSafe,
          C: FnOnce(&mut State, R) {
    let changes = {
        let s: &State = &*state;
        let s = ::std::panic::AssertUnwindSafe(s);
        match ::std::panic::catch_unwind(move || f(*s)) {
            Ok(changes) => changes,
            Err(_) => return
        }
    };
    commit(state, changes)
}
<commit_msg>Incremental reparse<commit_after>use std::path::PathBuf;
use xi_rope::tree::Cursor;
use elapsed::ElapsedDuration;

use file;
use fall_tree::{Node, WHITESPACE, TextUnit, File, Language, Edit, TextRange};
use fall_tree::search::{find_leaf_at_offset, ancestors};
use lang_fall::{LANG_FALL, highlight};

use ediproto::{ViewStateReply, Line, StyledText};
use model::{Direction, Amount, State, Editor, InputEvent, CowStr};

mod utils;

use self::utils::{move_cursor_by, cursor_offset};

#[derive(Default)]
pub struct EditorImpl {
    state: State,
}

impl Editor for EditorImpl {
    fn apply(&mut self, event: InputEvent) {
        let mut text_changed = None;
        match event {
            InputEvent::Ready => {}
            InputEvent::MoveCursor(d, a) => do_move_cursor(&mut self.state, d, a),
            InputEvent::InsertText(text) => {
                text_changed = if text == "\x08" {
                    do_backspace(&mut self.state)
                } else {
                    Some(do_insert(&mut self.state, text))
                };
            }
            InputEvent::OpenFile(path) => {
                do_open_file(&mut self.state, path);
                let text: String = self.state.text.clone().into();
                let file = LANG_FALL.parse(text.clone());
                self.state.file = Some(file);
            }
            InputEvent::SaveFile => do_save_file(&mut self.state),
        }
        let text: String = self.state.text.clone().into();
        let new_file = if let Some(ref file) = self.state.file {
            if let Some(edit) = text_changed {
                Some(file.edit(&edit))
            } else {
                None
            }
        } else {
            let file = LANG_FALL.parse(text.clone());
            Some(file)
        };

        if let Some(file) = new_file {
            self.state.file = Some(file)
        }

        modify_state(&mut self.state,
                     |state| {
                         let file = state.file.as_ref().unwrap();
                         highlight(file)
                     },
                     |state, spans| state.spans = spans
        );

        modify_state(&mut self.state,
                     |state| {
                         let mut off = cursor_offset(state);
                         let mut cursor = Cursor::new(&state.text, off);
                         while let Some(c) = cursor.next_codepoint() {
                             if !(c == ' ' || c == '\n') {
                                 break
                             }
                             off += c.len_utf8()
                         }
                         let file = state.file.as_ref().unwrap();
                         context(&file, off)
                     },
                     |state, syntax_tree| state.syntax_tree = syntax_tree
        );
    }

    fn render(&self) -> ViewStateReply {
        let mut result = ViewStateReply::new();
        render_lines(&mut result, self.state.text.lines_raw(0, self.state.text.len()), &self.state.spans);
        result.cursorX = self.state.cursor.x as i32;
        result.cursorY = self.state.cursor.y as i32;
        result.syntax_tree = self.state.syntax_tree.clone();
        if let Some(ref file) = self.state.file {
            result.lexing_time_nanos = ElapsedDuration::new(file.stats().lexing_time).nanos() as i64;
            result.parsing_time_nanos = ElapsedDuration::new(file.stats().parsing_time).nanos() as i64;
            result.reparse_len = file.stats().reparsed_region.len().as_u32() as i32;
        }
        if let Some(ref path) = self.state.file_path {
            result.file = path.display().to_string();
        }
        result.dirty = self.state.dirty;
        result
    }
}

fn render_lines<'a, L: Iterator<Item=CowStr<'a>>>(reply: &mut ViewStateReply, mut lines: L, spans: &[(u32, u32, &'static str)]) {
    let mut curr_global_offset = 0;

    let mut line_off;
    let mut curr_line: CowStr;
    macro_rules! next_line {
        () => {
            if let Some(line) = lines.next() {
                curr_line = line;
                line_off = 0;
                let _ = line_off;
            } else {
                return
            }
        }
    }
    next_line!();

    let mut line_sink = Line::new();
    macro_rules! push_line {
        () => {
            let mut line_done = Line::new();
            ::std::mem::swap(&mut line_done, &mut line_sink);
            reply.mut_lines().push(line_done);
         }
    }

    let mut events = Vec::new();
    for (i, span) in spans.iter().enumerate() {
        events.push((span.0 as usize, i as i32, false, span.2));
        events.push((span.1 as usize, -(i as i32), true, span.2));
    }
    events.sort();
    let mut events = events.into_iter();

    let mut color_stack = vec!["text"];
    macro_rules! push_range {
        ($chunk:expr) => {
            let range = {
                let mut range = StyledText::new();
                range.style = (*color_stack.last().unwrap()).to_owned();
                range.text = $chunk.to_owned();
                range
            };
            line_sink.mut_ranges().push(range);
         }
    }

    while let Some((off, _, is_close, color)) = events.next() {
        let mut l = off - curr_global_offset;
        while l > 0 {
            let effective_l = ::std::cmp::min(l, curr_line.len() - line_off);
            l -= effective_l;
            push_range!(&curr_line[line_off .. line_off + effective_l]);
            line_off += effective_l;
            if line_off == curr_line.len() {
                push_line!();
                next_line!();
            }
        }
        if is_close {
            color_stack.pop().unwrap();
        } else {
            color_stack.push(color);
        }
        curr_global_offset = off;
    }

    loop {
        push_range!(curr_line.as_ref());
        push_line!();
        next_line!();
    }
}

fn do_move_cursor(state: &mut State, direction: Direction, amount: Amount) {
    let (am_vert, am_hor): (i32, i32) = match amount {
        Amount::CHAR => (1, 1),
        Amount::PAGE => (10, ::std::i32::MAX / 2),
    };

    let (dx, dy) = match direction {
        Direction::UP => (0i32, -1 * am_vert),
        Direction::LEFT => (-1 * am_hor, 0),
        Direction::DOWN => (0, 1 * am_vert),
        Direction::RIGHT => (1 * am_hor, 0),
    };

    move_cursor_by(state, dx, dy)
}

fn do_backspace(state: &mut State) -> Option<Edit> {
    let off = cursor_offset(state);
    if off == 0 { return None }
    state.text.edit_str(off - 1, off, "");
    state.dirty = true;
    move_cursor_by(state, -1, 0);
    Some(Edit {
        delete: TextRange::from_len(TextUnit::from_usize(off - 1), TextUnit::from_usize(1)),
        insert: "".to_string(),
    })
}

fn do_insert(state: &mut State, text: String) -> Edit {
    let dx = text.len();
    let off = cursor_offset(state);
    state.text.edit_str(off, off, &text);
    state.dirty = true;
    move_cursor_by(state, dx as i32, 0);
    Edit {
        delete: TextRange::from_len(TextUnit::from_usize(off), TextUnit::zero()),
        insert: text,
    }
}

fn do_open_file(state: &mut State, path: PathBuf) {
    let text = file::get_text(&path).unwrap();
    state.text = From::from(text);
    state.dirty = false;
    state.file_path = Some(path)
}

fn do_save_file(state: &mut State) {
    if !state.dirty {
        return
    }
    if let Some(ref path) = state.file_path {
        file::put_text(path, String::from(state.text.clone()))
            .unwrap();
        state.dirty = false
    }
}

fn context(file: &File, offset: usize) -> String {
    fn go(lang: &Language, path: &[Node], level: usize, buff: &mut String) {
        assert!(path.len() > 0);
        if path.len() == 1 {
            return
        }
        let node = path[0];
        let next = path[1];
        for child in node.children() {
            if child.ty() == WHITESPACE {
                continue
            }

            let name = lang.node_type_info(child.ty()).name;
            for _ in 0..level {
                buff.push_str("  ");
            }
            if child == next {
                buff.push_str(">");
            } else {
                buff.push_str(" ");
            }
            buff.push_str(name);

            buff.push_str("\n");

            if child == next {
                go(lang, &path[1..], level + 1, buff);
            }
        }
    }
    let root = file.root();
    let mut result = String::new();
    let offset = TextUnit::from_usize(offset);
    let leaf = if let Some(leaf) = find_leaf_at_offset(root, offset).right_biased() {
        leaf
    } else {
        return String::new()
    };
    let mut path: Vec<Node> = ancestors(leaf).collect();
    path.reverse();
    go(&file.language(), &path, 0, &mut result);
    result
}

fn modify_state<R, F, C>(state: &mut State, f: F, commit: C)
    where F: FnOnce(&State) -> R + ::std::panic::UnwindSafe,
          C: FnOnce(&mut State, R) {
    let changes = {
        let s: &State = &*state;
        let s = ::std::panic::AssertUnwindSafe(s);
        match ::std::panic::catch_unwind(move || f(*s)) {
            Ok(changes) => changes,
            Err(_) => return
        }
    };
    commit(state, changes)
}
<|endoftext|>


<commit_before>use crate::{error::{Error,
                    Result},
            os::system::Uname};
use errno::errno;
use libc;
use std::{ffi::CStr,
          mem};

pub fn uname() -> Result<Uname> { unsafe { uname_libc() } }

unsafe fn uname_libc() -> Result<Uname> {
    let mut utsname: libc::utsname = mem::MaybeUninit::uninit().assume_init();
    let rv = libc::uname(&mut utsname);
    if rv < 0 {
        let errno = errno();
        let code = errno.0 as i32;
        return Err(Error::UnameFailed(format!("Error {} when calling uname: \
                                               {}",
                                              code, errno)));
    }
    Ok(Uname { sys_name:  CStr::from_ptr(utsname.sysname.as_ptr()).to_string_lossy()
                                                                  .into_owned(),
               node_name: CStr::from_ptr(utsname.nodename.as_ptr()).to_string_lossy()
                                                                   .into_owned(),
               release:   CStr::from_ptr(utsname.release.as_ptr()).to_string_lossy()
                                                                  .into_owned(),
               version:   CStr::from_ptr(utsname.version.as_ptr()).to_string_lossy()
                                                                  .into_owned(),
               machine:   CStr::from_ptr(utsname.machine.as_ptr()).to_string_lossy()
                                                                  .into_owned(), })
}
<commit_msg>Make the MaybeUninit usage safer<commit_after>use crate::{error::{Error,
                    Result},
            os::system::Uname};
use errno::errno;
use libc;
use std::{ffi::CStr,
          mem};

pub fn uname() -> Result<Uname> { unsafe { uname_libc() } }

unsafe fn uname_libc() -> Result<Uname> {
    let mut utsname = mem::MaybeUninit::uninit();
    let rv = libc::uname(utsname.as_mut_ptr());
    let utsname = utsname.assume_init();

    if rv < 0 {
        let errno = errno();
        let code = errno.0 as i32;
        return Err(Error::UnameFailed(format!("Error {} when calling uname: \
                                               {}",
                                              code, errno)));
    }
    Ok(Uname { sys_name:  CStr::from_ptr(utsname.sysname.as_ptr()).to_string_lossy()
                                                                  .into_owned(),
               node_name: CStr::from_ptr(utsname.nodename.as_ptr()).to_string_lossy()
                                                                   .into_owned(),
               release:   CStr::from_ptr(utsname.release.as_ptr()).to_string_lossy()
                                                                  .into_owned(),
               version:   CStr::from_ptr(utsname.version.as_ptr()).to_string_lossy()
                                                                  .into_owned(),
               machine:   CStr::from_ptr(utsname.machine.as_ptr()).to_string_lossy()
                                                                  .into_owned(), })
}
<|endoftext|>


<commit_before>use super::{escape, load_property_sheet, HighlightEvent, Highlighter, Properties, Scope};
use regex::Regex;
use std::collections::HashMap;
use std::ffi::CStr;
use std::io::Write;
use std::os::raw::c_char;
use std::process::abort;
use std::{fmt, slice};
use tree_sitter::{Language, PropertySheet};

struct LanguageConfiguration {
    language: Language,
    property_sheet: PropertySheet<Properties>,
    injection_regex: Option<Regex>,
}

pub struct TSHighlighter {
    languages: HashMap<String, LanguageConfiguration>,
    attribute_strings: Vec<&'static [u8]>,
}

pub struct TSHighlightBuffer {
    html: Vec<u8>,
    line_offsets: Vec<u32>,
}

#[repr(C)]
pub enum ErrorCode {
    Ok,
    UnknownScope,
}

#[no_mangle]
pub extern "C" fn ts_highlighter_new(attribute_strings: *const *const c_char) -> *mut TSHighlighter {
    let attribute_strings =
        unsafe { slice::from_raw_parts(attribute_strings, Scope::Unknown as usize + 1) };
    let attribute_strings = attribute_strings
        .into_iter()
        .map(|s| {
            if s.is_null() {
                &[]
            } else {
                unsafe { CStr::from_ptr(*s).to_bytes() }
            }
        })
        .collect();
    Box::into_raw(Box::new(TSHighlighter {
        languages: HashMap::new(),
        attribute_strings,
    }))
}

#[no_mangle]
pub extern "C" fn ts_highlight_buffer_new() -> *mut TSHighlightBuffer {
    Box::into_raw(Box::new(TSHighlightBuffer {
        html: Vec::new(),
        line_offsets: Vec::new(),
    }))
}

#[no_mangle]
pub extern "C" fn ts_highlighter_delete(this: *mut TSHighlighter) {
    drop(unsafe { Box::from_raw(this) })
}

#[no_mangle]
pub extern "C" fn ts_highlight_buffer_delete(this: *mut TSHighlightBuffer) {
    drop(unsafe { Box::from_raw(this) })
}

#[no_mangle]
pub extern "C" fn ts_highlight_buffer_content(this: *mut TSHighlightBuffer) -> *const u8 {
    let this = unwrap_ptr(this);
    this.html.as_slice().as_ptr()
}

#[no_mangle]
pub extern "C" fn ts_highlight_buffer_line_offsets(this: *mut TSHighlightBuffer) -> *const u32 {
    let this = unwrap_ptr(this);
    this.line_offsets.as_slice().as_ptr()
}

#[no_mangle]
pub extern "C" fn ts_highlight_buffer_len(this: *mut TSHighlightBuffer) -> u32 {
    let this = unwrap_ptr(this);
    this.html.len() as u32
}

#[no_mangle]
pub extern "C" fn ts_highlight_buffer_line_count(this: *mut TSHighlightBuffer) -> u32 {
    let this = unwrap_ptr(this);
    this.line_offsets.len() as u32
}

#[no_mangle]
pub extern "C" fn ts_highlighter_add_language(
    this: *mut TSHighlighter,
    scope_name: *const c_char,
    language: Language,
    property_sheet_json: *const c_char,
    injection_regex: *const c_char,
) -> ErrorCode {
    let this = unwrap_ptr(this);
    let scope_name = unsafe { CStr::from_ptr(scope_name) };
    let scope_name = unwrap(scope_name.to_str()).to_string();
    let property_sheet_json = unsafe { CStr::from_ptr(property_sheet_json) };
    let property_sheet_json = unwrap(property_sheet_json.to_str());

    let property_sheet = unwrap(load_property_sheet(language, property_sheet_json));
    let injection_regex = if injection_regex.is_null() {
        None
    } else {
        let pattern = unsafe { CStr::from_ptr(injection_regex) };
        Some(unwrap(Regex::new(unwrap(pattern.to_str()))))
    };

    this.languages.insert(
        scope_name,
        LanguageConfiguration {
            language,
            property_sheet,
            injection_regex,
        },
    );

    ErrorCode::Ok
}

#[no_mangle]
pub extern "C" fn ts_highlighter_highlight(
    this: *mut TSHighlighter,
    scope_name: *const c_char,
    source_code: *const c_char,
    source_code_len: u32,
    output: *mut TSHighlightBuffer,
) -> ErrorCode {
    let this = unwrap_ptr(this);
    let output = unwrap_ptr(output);
    let scope_name = unwrap(unsafe { CStr::from_ptr(scope_name).to_str() });
    let source_code =
        unsafe { slice::from_raw_parts(source_code as *const u8, source_code_len as usize) };
    this.highlight(source_code, scope_name, output)
}

impl TSHighlighter {
    fn highlight(
        &mut self,
        source_code: &[u8],
        scope_name: &str,
        output: &mut TSHighlightBuffer,
    ) -> ErrorCode {
        let configuration = self.languages.get(scope_name);
        if configuration.is_none() {
            return ErrorCode::UnknownScope;
        }
        let configuration = configuration.unwrap();
        let languages = &self.languages;

        let highlighter = unwrap(Highlighter::new(
            source_code,
            configuration.language,
            &configuration.property_sheet,
            |injection_string| {
                languages.values().find_map(|conf| {
                    conf.injection_regex.as_ref().and_then(|regex| {
                        if regex.is_match(injection_string) {
                            Some((conf.language, &conf.property_sheet))
                        } else {
                            None
                        }
                    })
                })
            },
        ));

        output.html.clear();
        output.line_offsets.clear();
        output.line_offsets.push(0);
        let mut scopes = Vec::new();
        for event in highlighter {
            match event {
                HighlightEvent::ScopeStart(s) => {
                    scopes.push(s);
                    output.start_scope(s, &self.attribute_strings);
                }
                HighlightEvent::ScopeEnd => {
                    scopes.pop();
                    output.end_scope();
                }
                HighlightEvent::Source(src) => {
                    output.add_text(src, &scopes, &self.attribute_strings);
                }
            };
        }

        ErrorCode::Ok
    }
}

impl TSHighlightBuffer {
    fn start_scope(&mut self, s: Scope, attribute_strings: &[&[u8]]) {
        let attribute_string = attribute_strings[s as usize];
        self.html.extend(b"");
    }

    fn end_scope(&mut self) {
        self.html.extend(b"");
    }

    fn finish_line(&mut self) {
        self.line_offsets.push(self.html.len() as u32);
    }

    fn add_text(&mut self, src: &str, scopes: &Vec<Scope>, attribute_strings: &[&[u8]]) {
        let mut multiline = false;
        for line in src.split('\n') {
            let line = line.trim_end_matches('\r');
            if multiline {
                scopes.iter().for_each(|_| self.end_scope());
                self.finish_line();
                scopes
                    .iter()
                    .for_each(|scope| self.start_scope(*scope, attribute_strings));
            }
            write!(&mut self.html, "{}", escape::Escape(line)).unwrap();
            multiline = true;
        }
    }
}

fn unwrap_ptr<'a, T>(result: *mut T) -> &'a mut T {
    unsafe { result.as_mut() }.unwrap_or_else(|| {
        eprintln!("{}:{} - pointer must not be null", file!(), line!());
        abort();
    })
}

fn unwrap<T, E: fmt::Display>(result: Result<T, E>) -> T {
    result.unwrap_or_else(|error| {
        eprintln!("tree-sitter highlight error: {}", error);
        abort();
    })
}
<commit_msg>Highlight.highlight does not mutate<commit_after>use super::{escape, load_property_sheet, HighlightEvent, Highlighter, Properties, Scope};
use regex::Regex;
use std::collections::HashMap;
use std::ffi::CStr;
use std::io::Write;
use std::os::raw::c_char;
use std::process::abort;
use std::{fmt, slice};
use tree_sitter::{Language, PropertySheet};

struct LanguageConfiguration {
    language: Language,
    property_sheet: PropertySheet<Properties>,
    injection_regex: Option<Regex>,
}

pub struct TSHighlighter {
    languages: HashMap<String, LanguageConfiguration>,
    attribute_strings: Vec<&'static [u8]>,
}

pub struct TSHighlightBuffer {
    html: Vec<u8>,
    line_offsets: Vec<u32>,
}

#[repr(C)]
pub enum ErrorCode {
    Ok,
    UnknownScope,
}

#[no_mangle]
pub extern "C" fn ts_highlighter_new(attribute_strings: *const *const c_char) -> *mut TSHighlighter {
    let attribute_strings =
        unsafe { slice::from_raw_parts(attribute_strings, Scope::Unknown as usize + 1) };
    let attribute_strings = attribute_strings
        .into_iter()
        .map(|s| {
            if s.is_null() {
                &[]
            } else {
                unsafe { CStr::from_ptr(*s).to_bytes() }
            }
        })
        .collect();
    Box::into_raw(Box::new(TSHighlighter {
        languages: HashMap::new(),
        attribute_strings,
    }))
}

#[no_mangle]
pub extern "C" fn ts_highlight_buffer_new() -> *mut TSHighlightBuffer {
    Box::into_raw(Box::new(TSHighlightBuffer {
        html: Vec::new(),
        line_offsets: Vec::new(),
    }))
}

#[no_mangle]
pub extern "C" fn ts_highlighter_delete(this: *mut TSHighlighter) {
    drop(unsafe { Box::from_raw(this) })
}

#[no_mangle]
pub extern "C" fn ts_highlight_buffer_delete(this: *mut TSHighlightBuffer) {
    drop(unsafe { Box::from_raw(this) })
}

#[no_mangle]
pub extern "C" fn ts_highlight_buffer_content(this: *mut TSHighlightBuffer) -> *const u8 {
    let this = unwrap_ptr(this);
    this.html.as_slice().as_ptr()
}

#[no_mangle]
pub extern "C" fn ts_highlight_buffer_line_offsets(this: *mut TSHighlightBuffer) -> *const u32 {
    let this = unwrap_ptr(this);
    this.line_offsets.as_slice().as_ptr()
}

#[no_mangle]
pub extern "C" fn ts_highlight_buffer_len(this: *mut TSHighlightBuffer) -> u32 {
    let this = unwrap_ptr(this);
    this.html.len() as u32
}

#[no_mangle]
pub extern "C" fn ts_highlight_buffer_line_count(this: *mut TSHighlightBuffer) -> u32 {
    let this = unwrap_ptr(this);
    this.line_offsets.len() as u32
}

#[no_mangle]
pub extern "C" fn ts_highlighter_add_language(
    this: *mut TSHighlighter,
    scope_name: *const c_char,
    language: Language,
    property_sheet_json: *const c_char,
    injection_regex: *const c_char,
) -> ErrorCode {
    let this = unwrap_ptr(this);
    let scope_name = unsafe { CStr::from_ptr(scope_name) };
    let scope_name = unwrap(scope_name.to_str()).to_string();
    let property_sheet_json = unsafe { CStr::from_ptr(property_sheet_json) };
    let property_sheet_json = unwrap(property_sheet_json.to_str());

    let property_sheet = unwrap(load_property_sheet(language, property_sheet_json));
    let injection_regex = if injection_regex.is_null() {
        None
    } else {
        let pattern = unsafe { CStr::from_ptr(injection_regex) };
        Some(unwrap(Regex::new(unwrap(pattern.to_str()))))
    };

    this.languages.insert(
        scope_name,
        LanguageConfiguration {
            language,
            property_sheet,
            injection_regex,
        },
    );

    ErrorCode::Ok
}

#[no_mangle]
pub extern "C" fn ts_highlighter_highlight(
    this: *mut TSHighlighter,
    scope_name: *const c_char,
    source_code: *const c_char,
    source_code_len: u32,
    output: *mut TSHighlightBuffer,
) -> ErrorCode {
    let this = unwrap_ptr(this);
    let output = unwrap_ptr(output);
    let scope_name = unwrap(unsafe { CStr::from_ptr(scope_name).to_str() });
    let source_code =
        unsafe { slice::from_raw_parts(source_code as *const u8, source_code_len as usize) };
    this.highlight(source_code, scope_name, output)
}

impl TSHighlighter {
    fn highlight(
        &self,
        source_code: &[u8],
        scope_name: &str,
        output: &mut TSHighlightBuffer,
    ) -> ErrorCode {
        let configuration = self.languages.get(scope_name);
        if configuration.is_none() {
            return ErrorCode::UnknownScope;
        }
        let configuration = configuration.unwrap();
        let languages = &self.languages;

        let highlighter = unwrap(Highlighter::new(
            source_code,
            configuration.language,
            &configuration.property_sheet,
            |injection_string| {
                languages.values().find_map(|conf| {
                    conf.injection_regex.as_ref().and_then(|regex| {
                        if regex.is_match(injection_string) {
                            Some((conf.language, &conf.property_sheet))
                        } else {
                            None
                        }
                    })
                })
            },
        ));

        output.html.clear();
        output.line_offsets.clear();
        output.line_offsets.push(0);
        let mut scopes = Vec::new();
        for event in highlighter {
            match event {
                HighlightEvent::ScopeStart(s) => {
                    scopes.push(s);
                    output.start_scope(s, &self.attribute_strings);
                }
                HighlightEvent::ScopeEnd => {
                    scopes.pop();
                    output.end_scope();
                }
                HighlightEvent::Source(src) => {
                    output.add_text(src, &scopes, &self.attribute_strings);
                }
            };
        }

        ErrorCode::Ok
    }
}

impl TSHighlightBuffer {
    fn start_scope(&mut self, s: Scope, attribute_strings: &[&[u8]]) {
        let attribute_string = attribute_strings[s as usize];
        self.html.extend(b"");
    }

    fn end_scope(&mut self) {
        self.html.extend(b"");
    }

    fn finish_line(&mut self) {
        self.line_offsets.push(self.html.len() as u32);
    }

    fn add_text(&mut self, src: &str, scopes: &Vec<Scope>, attribute_strings: &[&[u8]]) {
        let mut multiline = false;
        for line in src.split('\n') {
            let line = line.trim_end_matches('\r');
            if multiline {
                scopes.iter().for_each(|_| self.end_scope());
                self.finish_line();
                scopes
                    .iter()
                    .for_each(|scope| self.start_scope(*scope, attribute_strings));
            }
            write!(&mut self.html, "{}", escape::Escape(line)).unwrap();
            multiline = true;
        }
    }
}

fn unwrap_ptr<'a, T>(result: *mut T) -> &'a mut T {
    unsafe { result.as_mut() }.unwrap_or_else(|| {
        eprintln!("{}:{} - pointer must not be null", file!(), line!());
        abort();
    })
}

fn unwrap<T, E: fmt::Display>(result: Result<T, E>) -> T {
    result.unwrap_or_else(|error| {
        eprintln!("tree-sitter highlight error: {}", error);
        abort();
    })
}
<|endoftext|>


<commit_before>#![deny(warnings)]

use std::cell::Cell;
use std::rc::Rc;

use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Error, Response, Server};

fn main() {
    pretty_env_logger::init();

    // Configure a runtime that runs everything on the current thread
    let rt = tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()
        .expect("build runtime");

    // Combine it with a `LocalSet,  which means it can spawn !Send futures...
    let local = tokio::task::LocalSet::new();
    local.block_on(&rt, run());
}

async fn run() {
    let addr = ([127, 0, 0, 1], 3000).into();

    // Using a !Send request counter is fine on 1 thread...
    let counter = Rc::new(Cell::new(0));

    let make_service = make_service_fn(move |_| {
        // For each connection, clone the counter to use in our service...
        let cnt = counter.clone();

        async move {
            Ok::<_, Error>(service_fn(move |_| {
                let prev = cnt.get();
                cnt.set(prev + 1);
                let value = cnt.get();
                async move { Ok::<_, Error>(Response::new(Body::from(format!("Request #{}", value)))) }
            }))
        }
    });

    let server = Server::bind(&addr).executor(LocalExec).serve(make_service);

    println!("Listening on http://{}", addr);

    // The server would block on current thread to await !Send futures.
    if let Err(e) = server.await {
        eprintln!("server error: {}", e);
    }
}

// Since the Server needs to spawn some background tasks, we needed
// to configure an Executor that can spawn !Send futures...
#[derive(Clone, Copy, Debug)]
struct LocalExec;

impl<F> hyper::rt::Executor<F> for LocalExec
where
    F: std::future::Future + 'static, // not requiring `Send`
{
    fn execute(&self, fut: F) {
        // This will spawn into the currently running `LocalSet`.
        tokio::task::spawn_local(fut);
    }
}
<commit_msg>test(server): Use a !Send and !Sync HttpBody in an example<commit_after>#![deny(warnings)]

use std::cell::Cell;
use std::rc::Rc;

use hyper::body::{Bytes, HttpBody};
use hyper::header::{HeaderMap, HeaderValue};
use hyper::service::{make_service_fn, service_fn};
use hyper::{Error, Response, Server};
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};

struct Body {
    // Our Body type is !Send and !Sync:
    _marker: PhantomData<*const ()>,
    data: Option<Bytes>,
}

impl From<String> for Body {
    fn from(a: String) -> Self {
        Body {
            _marker: PhantomData,
            data: Some(a.into()),
        }
    }
}

impl HttpBody for Body {
    type Data = Bytes;
    type Error = Error;

    fn poll_data(
        self: Pin<&mut Self>,
        _: &mut Context<'_>,
    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
        Poll::Ready(self.get_mut().data.take().map(Ok))
    }

    fn poll_trailers(
        self: Pin<&mut Self>,
        _: &mut Context<'_>,
    ) -> Poll<Result<Option<HeaderMap<HeaderValue>>, Self::Error>> {
        Poll::Ready(Ok(None))
    }
}

fn main() {
    pretty_env_logger::init();

    // Configure a runtime that runs everything on the current thread
    let rt = tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()
        .expect("build runtime");

    // Combine it with a `LocalSet,  which means it can spawn !Send futures...
    let local = tokio::task::LocalSet::new();
    local.block_on(&rt, run());
}

async fn run() {
    let addr = ([127, 0, 0, 1], 3000).into();

    // Using a !Send request counter is fine on 1 thread...
    let counter = Rc::new(Cell::new(0));

    let make_service = make_service_fn(move |_| {
        // For each connection, clone the counter to use in our service...
        let cnt = counter.clone();

        async move {
            Ok::<_, Error>(service_fn(move |_| {
                let prev = cnt.get();
                cnt.set(prev + 1);
                let value = cnt.get();
                async move { Ok::<_, Error>(Response::new(Body::from(format!("Request #{}", value)))) }
            }))
        }
    });

    let server = Server::bind(&addr).executor(LocalExec).serve(make_service);

    println!("Listening on http://{}", addr);

    // The server would block on current thread to await !Send futures.
    if let Err(e) = server.await {
        eprintln!("server error: {}", e);
    }
}

// Since the Server needs to spawn some background tasks, we needed
// to configure an Executor that can spawn !Send futures...
#[derive(Clone, Copy, Debug)]
struct LocalExec;

impl<F> hyper::rt::Executor<F> for LocalExec
where
    F: std::future::Future + 'static, // not requiring `Send`
{
    fn execute(&self, fut: F) {
        // This will spawn into the currently running `LocalSet`.
        tokio::task::spawn_local(fut);
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use fnv::{FnvBuildHasher, FnvHashMap};
use graphql_syntax::FloatValue;
use graphql_syntax::OperationKind;
use indexmap::IndexMap;
use interner::StringKey;

#[derive(Eq, PartialEq, Hash, Debug)]
pub struct ObjectEntry {
    pub key: StringKey,
    pub value: Primitive,
}

/// An interned codegen AST
#[derive(Eq, PartialEq, Hash, Debug)]
pub enum Ast {
    Object(Vec<ObjectEntry>),
    Array(Vec<Primitive>),
}

impl Ast {
    pub fn assert_object(&self) -> &[ObjectEntry] {
        match self {
            Ast::Object(result) => result,
            Ast::Array(_) => panic!("Expected an object"),
        }
    }

    pub fn assert_array(&self) -> &[Primitive] {
        match self {
            Ast::Object(_) => panic!("Expected an array"),
            Ast::Array(result) => result,
        }
    }
}

#[derive(Eq, PartialEq, Hash, Debug)]
pub enum Primitive {
    Key(AstKey),
    String(StringKey),
    Float(FloatValue),
    Int(i64),
    Bool(bool),
    Null,
    StorageKey(StringKey, AstKey),
    RawString(String),
    GraphQLModuleDependency(StringKey),
    JSModuleDependency(StringKey),
}

impl Primitive {
    pub fn assert_string(&self) -> StringKey {
        if let Primitive::String(key) = self {
            *key
        } else {
            panic!("Expected a string");
        }
    }

    pub fn assert_key(&self) -> AstKey {
        if let Primitive::Key(key) = self {
            *key
        } else {
            panic!("Expected a key");
        }
    }

    pub fn string_or_null(str: Option<StringKey>) -> Primitive {
        match str {
            None => Primitive::Null,
            Some(str) => Primitive::String(str),
        }
    }
}

type Table = IndexMap<Ast, usize, FnvBuildHasher>;

#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
pub struct AstKey(usize);

impl AstKey {
    pub fn as_usize(self) -> usize {
        self.0
    }
}

#[derive(Default)]
pub struct AstBuilder {
    table: Table,
}

impl AstBuilder {
    pub fn intern(&mut self, ast: Ast) -> AstKey {
        if let Some(ix) = self.table.get(&ast) {
            AstKey(*ix)
        } else {
            let ix = self.table.len();
            self.table.insert(ast, ix);
            AstKey(ix)
        }
    }

    pub fn lookup(&self, key: AstKey) -> &Ast {
        self.table.get_index(key.as_usize()).unwrap().0
    }
}

pub enum QueryID {
    Persisted { id: String, text_hash: String },
    External(StringKey),
}

pub struct RequestParameters<'a> {
    pub id: &'a Option<QueryID>,
    pub metadata: FnvHashMap<String, String>,
    pub name: StringKey,
    pub operation_kind: OperationKind,
    pub text: Option<String>,
}
<commit_msg>use IndexSet in codegen<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use fnv::{FnvBuildHasher, FnvHashMap};
use graphql_syntax::FloatValue;
use graphql_syntax::OperationKind;
use indexmap::IndexSet;
use interner::StringKey;

#[derive(Eq, PartialEq, Hash, Debug)]
pub struct ObjectEntry {
    pub key: StringKey,
    pub value: Primitive,
}

/// An interned codegen AST
#[derive(Eq, PartialEq, Hash, Debug)]
pub enum Ast {
    Object(Vec<ObjectEntry>),
    Array(Vec<Primitive>),
}

impl Ast {
    pub fn assert_object(&self) -> &[ObjectEntry] {
        match self {
            Ast::Object(result) => result,
            Ast::Array(_) => panic!("Expected an object"),
        }
    }

    pub fn assert_array(&self) -> &[Primitive] {
        match self {
            Ast::Object(_) => panic!("Expected an array"),
            Ast::Array(result) => result,
        }
    }
}

#[derive(Eq, PartialEq, Hash, Debug)]
pub enum Primitive {
    Key(AstKey),
    String(StringKey),
    Float(FloatValue),
    Int(i64),
    Bool(bool),
    Null,
    StorageKey(StringKey, AstKey),
    RawString(String),
    GraphQLModuleDependency(StringKey),
    JSModuleDependency(StringKey),
}

impl Primitive {
    pub fn assert_string(&self) -> StringKey {
        if let Primitive::String(key) = self {
            *key
        } else {
            panic!("Expected a string");
        }
    }

    pub fn assert_key(&self) -> AstKey {
        if let Primitive::Key(key) = self {
            *key
        } else {
            panic!("Expected a key");
        }
    }

    pub fn string_or_null(str: Option<StringKey>) -> Primitive {
        match str {
            None => Primitive::Null,
            Some(str) => Primitive::String(str),
        }
    }
}

#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
pub struct AstKey(usize);

impl AstKey {
    pub fn as_usize(self) -> usize {
        self.0
    }
}

#[derive(Default)]
pub struct AstBuilder {
    table: IndexSet<Ast, FnvBuildHasher>,
}

impl AstBuilder {
    pub fn intern(&mut self, ast: Ast) -> AstKey {
        AstKey(self.table.insert_full(ast).0)
    }

    pub fn lookup(&self, key: AstKey) -> &Ast {
        self.table.get_index(key.as_usize()).unwrap()
    }
}

pub enum QueryID {
    Persisted { id: String, text_hash: String },
    External(StringKey),
}

pub struct RequestParameters<'a> {
    pub id: &'a Option<QueryID>,
    pub metadata: FnvHashMap<String, String>,
    pub name: StringKey,
    pub operation_kind: OperationKind,
    pub text: Option<String>,
}
<|endoftext|>


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

//! Gecko's restyle damage computation (aka change hints, aka `nsChangeHint`).

use gecko_bindings::bindings;
use gecko_bindings::structs;
use gecko_bindings::structs::nsChangeHint;
use matching::{StyleChange, StyleDifference};
use properties::ComputedValues;
use std::ops::{BitAnd, BitOr, BitOrAssign, Not};

/// The representation of Gecko's restyle damage is just a wrapper over
/// `nsChangeHint`.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct GeckoRestyleDamage(nsChangeHint);

impl GeckoRestyleDamage {
    /// Trivially construct a new `GeckoRestyleDamage`.
    #[inline]
    pub fn new(raw: nsChangeHint) -> Self {
        GeckoRestyleDamage(raw)
    }

    /// Get the inner change hint for this damage.
    #[inline]
    pub fn as_change_hint(&self) -> nsChangeHint {
        self.0
    }

    /// Get an empty change hint, that is (`nsChangeHint(0)`).
    #[inline]
    pub fn empty() -> Self {
        GeckoRestyleDamage(nsChangeHint(0))
    }

    /// Returns whether this restyle damage represents the empty damage.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.0 == nsChangeHint(0)
    }

    /// Computes the `StyleDifference` (including the appropriate change hint)
    /// given an old and a new style.
    pub fn compute_style_difference(
        old_style: &ComputedValues,
        new_style: &ComputedValues,
    ) -> StyleDifference {
        let mut any_style_changed = false;
        let mut reset_only = false;
        let hint = unsafe {
            bindings::Gecko_CalcStyleDifference(
                old_style,
                new_style,
                &mut any_style_changed,
                &mut reset_only,
            )
        };
        let change = if any_style_changed {
            StyleChange::Changed { reset_only }
        } else {
            StyleChange::Unchanged
        };
        StyleDifference::new(GeckoRestyleDamage(nsChangeHint(hint)), change)
    }

    /// Returns true if this restyle damage contains all the damage of |other|.
    pub fn contains(self, other: Self) -> bool {
        self & other == other
    }

    /// Gets restyle damage to reconstruct the entire frame, subsuming all
    /// other damage.
    pub fn reconstruct() -> Self {
        GeckoRestyleDamage(structs::nsChangeHint_nsChangeHint_ReconstructFrame)
    }
}

impl Default for GeckoRestyleDamage {
    fn default() -> Self {
        Self::empty()
    }
}

impl BitOr for GeckoRestyleDamage {
    type Output = Self;
    fn bitor(self, other: Self) -> Self {
        GeckoRestyleDamage(self.0 | other.0)
    }
}

impl BitOrAssign for GeckoRestyleDamage {
    fn bitor_assign(&mut self, other: Self) {
        *self = *self | other;
    }
}

impl BitAnd for GeckoRestyleDamage {
    type Output = Self;
    fn bitand(self, other: Self) -> Self {
        GeckoRestyleDamage(nsChangeHint((self.0).0 & (other.0).0))
    }
}

impl Not for GeckoRestyleDamage {
    type Output = Self;
    fn not(self) -> Self {
        GeckoRestyleDamage(nsChangeHint(!(self.0).0))
    }
}
<commit_msg>style: Skip custom properties comparison if other inherited properties changed.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Gecko's restyle damage computation (aka change hints, aka `nsChangeHint`).

use gecko_bindings::bindings;
use gecko_bindings::structs;
use gecko_bindings::structs::nsChangeHint;
use matching::{StyleChange, StyleDifference};
use properties::ComputedValues;
use std::ops::{BitAnd, BitOr, BitOrAssign, Not};

/// The representation of Gecko's restyle damage is just a wrapper over
/// `nsChangeHint`.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct GeckoRestyleDamage(nsChangeHint);

impl GeckoRestyleDamage {
    /// Trivially construct a new `GeckoRestyleDamage`.
    #[inline]
    pub fn new(raw: nsChangeHint) -> Self {
        GeckoRestyleDamage(raw)
    }

    /// Get the inner change hint for this damage.
    #[inline]
    pub fn as_change_hint(&self) -> nsChangeHint {
        self.0
    }

    /// Get an empty change hint, that is (`nsChangeHint(0)`).
    #[inline]
    pub fn empty() -> Self {
        GeckoRestyleDamage(nsChangeHint(0))
    }

    /// Returns whether this restyle damage represents the empty damage.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.0 == nsChangeHint(0)
    }

    /// Computes the `StyleDifference` (including the appropriate change hint)
    /// given an old and a new style.
    pub fn compute_style_difference(
        old_style: &ComputedValues,
        new_style: &ComputedValues,
    ) -> StyleDifference {
        let mut any_style_changed = false;
        let mut reset_only = false;
        let hint = unsafe {
            bindings::Gecko_CalcStyleDifference(
                old_style,
                new_style,
                &mut any_style_changed,
                &mut reset_only,
            )
        };
        if reset_only &&
           old_style.custom_properties() != new_style.custom_properties() {
            // The Gecko_CalcStyleDifference call only checks the non-custom
            // property structs, so we check the custom properties here. Since
            // they generate no damage themselves, we can skip this check if we
            // already know we had some inherited (regular) property
            // differences.
            any_style_changed = true;
            reset_only = false;
        }
        let change = if any_style_changed {
            StyleChange::Changed { reset_only }
        } else {
            StyleChange::Unchanged
        };
        StyleDifference::new(GeckoRestyleDamage(nsChangeHint(hint)), change)
    }

    /// Returns true if this restyle damage contains all the damage of |other|.
    pub fn contains(self, other: Self) -> bool {
        self & other == other
    }

    /// Gets restyle damage to reconstruct the entire frame, subsuming all
    /// other damage.
    pub fn reconstruct() -> Self {
        GeckoRestyleDamage(structs::nsChangeHint_nsChangeHint_ReconstructFrame)
    }
}

impl Default for GeckoRestyleDamage {
    fn default() -> Self {
        Self::empty()
    }
}

impl BitOr for GeckoRestyleDamage {
    type Output = Self;
    fn bitor(self, other: Self) -> Self {
        GeckoRestyleDamage(self.0 | other.0)
    }
}

impl BitOrAssign for GeckoRestyleDamage {
    fn bitor_assign(&mut self, other: Self) {
        *self = *self | other;
    }
}

impl BitAnd for GeckoRestyleDamage {
    type Output = Self;
    fn bitand(self, other: Self) -> Self {
        GeckoRestyleDamage(nsChangeHint((self.0).0 & (other.0).0))
    }
}

impl Not for GeckoRestyleDamage {
    type Output = Self;
    fn not(self) -> Self {
        GeckoRestyleDamage(nsChangeHint(!(self.0).0))
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::io::prelude::*;
// use std::io::Read;   // will include this

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

    let config = parse_config(&args);

    println!("Searching for {}", config.query);
    println!("In file {}", config.filename);

    let mut f = File::open(config.filename).expect("file not found");

    let mut contents = String::new();
    f.read_to_string(&mut contents).expect("somthing went wrong reading the file");

    println!("With text:\n{}", contents);
}

struct Config {
    query: String,
    filename: String
}

fn parse_config(args: &[String]) -> Config {
    let query = args[1].clone();
    let filename = args[2].clone();

    Config {
        query: query,
        filename: filename
    }
}<commit_msg>On io refactor: fn -> Config method.<commit_after>use std::env;
use std::fs::File;
use std::io::prelude::*;
// use std::io::Read;   // will include this

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

    let config = Config::new(&args);

    println!("Searching for {}", config.query);
    println!("In file {}", config.filename);

    let mut f = File::open(config.filename).expect("file not found");

    let mut contents = String::new();
    f.read_to_string(&mut contents)
        .expect("somthing went wrong reading the file");

    println!("With text:\n{}", contents);
}

struct Config {
    query: String,
    filename: String,
}

impl Config {
    fn new(args: &[String]) -> Config {
        let query = args[1].clone();
        let filename = args[2].clone();

        Config {
            query: query,
            filename: filename,
        }
    }
}
<|endoftext|>


<commit_before>#![no_main]
use libfuzzer_sys::fuzz_target;

fuzz_target!(|input: (String, usize)| {
    if input.0.len() > 100_000 {
        return; // Avoid timeouts in OSS-Fuzz.
    }

    let _ = textwrap::refill(&input.0, input.1);
});
<commit_msg>Avoid OOM in refill fuzz test<commit_after>#![no_main]
use libfuzzer_sys::fuzz_target;

fuzz_target!(|input: (String, usize)| {
    if input.0.len() > 100_000 {
        return; // Avoid timeouts in OSS-Fuzz.
    }

    let (_, options) = textwrap::unfill(&input.0);
    if options.subsequent_indent.len() > 10_000 {
        // Avoid out of memory in OSS-fuzz. The indentation is added
        // on every line of the output, meaning that is can make the
        // memory usage explode.
        return;
    }

    let _ = textwrap::refill(&input.0, input.1);
});
<|endoftext|>