<commit_before>#![feature(plugin)]
#![plugin(dynasm)]

#![allow(unused_imports)]

#[macro_use]
extern crate dynasmrt;

use dynasmrt::{DynasmApi, DynasmLabelApi};

// aliases, and dynasm! in item position
dynasm!(ops
    ; .alias test, rax
);

fn complex1() {
    let mut ops = dynasmrt::x64::Assembler::new();
    let d = 3;
    let c = 4;

    let label = ops.new_dynamic_label();

    // interesting testcases
    dynasm!(ops
        // no args
        ; ret
        // reserved keyword
        ; loop 5
        // immediate
        ; ret 16
        // register
        ; inc test
        // memory ref
        ; inc DWORD [16]
        ; inc DWORD [test]
        ; inc DWORD [rax*2]
        ; inc DWORD [rax*3]
        ; inc DWORD [rax*4]
        ; inc DWORD [rax*5]
        ; inc DWORD [rax*8]
        ; inc DWORD [rax*9]
        ; inc DWORD [rax + 16]
        ; inc DWORD [rax*8 + 16]
        ; inc DWORD [rax + rbx]
        ; inc DWORD [rax + rbx + 16]
        ; inc DWORD [rax*8 + rbx + 16]
        // special memoryref cases
        ; inc DWORD [rsp]
        ; inc DWORD [r12]
        ; inc DWORD [rsp + rax]
        ; inc DWORD [rax + rsp]
        ; inc DWORD [rbp]
        ; inc DWORD [r13]
        ; inc DWORD [rbp + 16]
        ; inc DWORD [rbp*8]
        ; inc DWORD [rip]
        ; inc DWORD [rip + 16]
        ; inc DWORD [1*r15]
        ; inc DWORD [NOSPLIT 1*r15]
        ; inc DWORD [2*r15]
        ; inc DWORD [NOSPLIT 2*r15]
        ; inc DWORD [1*r15 + r14]
        ; inc DWORD [rax + rax + rax + rax + rbx]
        // weird registers
        ; xchg al, ah
        ; xchg al, dil
        // register-specific forms
        ; adc rax, 5
        // multi arg forms
        ; mov rax, rbx
        ; mov rax, [rbx]
        ; mov [rbx], rax
        ; mov rax, 1
        ; mov BYTE [rax], 1
        ; imul rax, rbx, 1
        ; imul rax, [rbx], 1
        // prefixes
        ; fs inc DWORD [rax]
        ; lock fs inc DWORD [rax]
        ; rep stosq
        ; inc DWORD [eax]
        // really long instructions
        ; fs imul r9w, [r10d*8 + r11d + 0x66778899], 0x1122
        ; fs imul r9,  [edi*8 + r11d + 0x66778899], 0x11223344
        ; fs mov r9, QWORD 0x1122334455667788
        ; fs movabs rax, 0x1122334455667788
        // funky syntax features
        ; inc BYTE [rax]
        ; inc WORD [rax]
        ; inc DWORD [rax]
        ; inc QWORD [rax]
        ; inc QWORD [BYTE rax + 0]
        ; inc QWORD [DWORD rax + 0]
        // very odd memoryrefs
        ; mov rax, [rbx + rbx * 3 + 2 + c + rax + d]
        ; mov rax, [rbx - 4]
        // labels
        ; a: // local
        ; -> b: // global
        ; => label // dynamic. note the lack of a trailing :. this is due to : being a valid symbol within expressions that does not occur in any other normal rust expr contexts.
        // jumps
        ; jmp <a
        ; jmp -> b
        ; jmp => label
        // rip relative stuff
        ; lea rax, [->b]
        // dynamic registers
        ; inc Rb(1)
        ; inc Rh(5)
        ; inc Rw(1)
        ; inc Rd(1)
        ; inc Rq(1)
        ; mov Rb(7), [Rq(3)*4 + rax]
        ; fsub Rf(5), st0
        // other register families
        ; mov cr1, rax
        ; mov dr1, rax
        ; mov rax, cr1
        ; mov rax, dr1
        ; pop fs
        ; movmskps eax, xmm7
        ; movd mm7, eax
        ; movd eax, mm7
        ; fcomp st0
        // VEX/XOP instructions
        ; andn rax, rcx, rdx
        ; andn r8, r9, r10
        ; bextr rax, rbx, 1
        ; vaddpd xmm0, xmm1, [rax]
        // VSIB addressing
        ; vgatherqpd ymm1, QWORD [ymm15 + rsi + 0x11112222], ymm8
        ; vgatherqpd ymm1, QWORD [NOSPLIT rsi + ymm15 + 0x11112222], ymm8
        ; vgatherqpd ymm1, QWORD [ymm15*8 + rsi + 0x11112222], ymm8
        // 4 argument instructions
        ; vfmaddss xmm0, xmm1, xmm2, xmm3
        // directives
        ; string:
        //; .bytes "Hello world!\0".bytes()
    );

    // typemap support
    #[allow(dead_code)]
    struct Test {
        foo: i32,
        bar: u32
    }
    #[allow(dead_code)]
    struct SmallTest {
        foo: i8,
        bar: u8
    }
    let mut test_array = [Test {foo: 1, bar: 2}, Test {foo: 3, bar: 4}, Test {foo: 5, bar: 6}];
    let mut test_array = &mut test_array;
    let mut test_single = Test {foo: 7, bar: 8};
    let mut test_single = &mut test_single;
    dynasm!(ops
        ; mov rax, AWORD MutPointer!(test_array)
        ; mov ebx, 2
        ; vgatherqpd ymm13, QWORD rax => f64[ymm15], ymm14
        ; inc DWORD rax => Test[2].bar
        ; inc DWORD rax => Test[BYTE 2]
        ; inc DWORD rax => Test[BYTE 0].bar
        ; inc DWORD rax => Test[2 + rbx].bar
        ; inc DWORD rax => Test[rbx].bar
        ; inc DWORD rax => Test[rbx]
        ; inc DWORD rax => Test[rbx + 2]
        ; inc DWORD rax => SmallTest[4*rbx + 2].bar
        ; inc DWORD rax => SmallTest[BYTE 2*rbx + 2].bar
        ; mov rax, AWORD MutPointer!(test_single)
        ; inc DWORD rax => Test.bar
    );

    // dynasm in expr position
    match 1 {
        0 => (),
        _ => dynasm!(ops; inc rax)
    }

    // fixups
    let start = ops.offset();
    dynasm!( (ops)
        ; inc rbx
    );
    let end = ops.offset();
    ops.alter(|ops| {
        ops.goto(start);
        dynasm!(ops
            ; inc r12
        );
        ops.check(end);
    });

    let index = ops.offset();
    dynasm!(ops
        ; mov eax, 10203040
        ; ret
    );

    let buf = ops.finalize().unwrap();

    println!("Generated assembly:");
    for i in buf.iter() {
        print!("{:02x }", i);
    }
    println!("");

    let func: extern "C" fn() -> i64 = unsafe { std::mem::transmute(buf.ptr(index)) };
    println!("assembled function result: {}", func() );
}

#[test]
fn complex_complex1() {
    complex1();
}
<commit_msg>Fix newly added compiler warnings in tests<commit_after>#![feature(plugin)]
#![plugin(dynasm)]

#![allow(unused_imports)]

#[macro_use]
extern crate dynasmrt;

use dynasmrt::{DynasmApi, DynasmLabelApi};

// aliases, and dynasm! in item position
dynasm!(ops
    ; .alias test, rax
);

fn complex1() {
    let mut ops = dynasmrt::x64::Assembler::new();
    let d = 3;
    let c = 4;

    let label = ops.new_dynamic_label();

    // interesting testcases
    dynasm!(ops
        // no args
        ; ret
        // reserved keyword
        ; loop 5
        // immediate
        ; ret 16
        // register
        ; inc test
        // memory ref
        ; inc DWORD [16]
        ; inc DWORD [test]
        ; inc DWORD [rax*2]
        ; inc DWORD [rax*3]
        ; inc DWORD [rax*4]
        ; inc DWORD [rax*5]
        ; inc DWORD [rax*8]
        ; inc DWORD [rax*9]
        ; inc DWORD [rax + 16]
        ; inc DWORD [rax*8 + 16]
        ; inc DWORD [rax + rbx]
        ; inc DWORD [rax + rbx + 16]
        ; inc DWORD [rax*8 + rbx + 16]
        // special memoryref cases
        ; inc DWORD [rsp]
        ; inc DWORD [r12]
        ; inc DWORD [rsp + rax]
        ; inc DWORD [rax + rsp]
        ; inc DWORD [rbp]
        ; inc DWORD [r13]
        ; inc DWORD [rbp + 16]
        ; inc DWORD [rbp*8]
        ; inc DWORD [rip]
        ; inc DWORD [rip + 16]
        ; inc DWORD [1*r15]
        ; inc DWORD [NOSPLIT 1*r15]
        ; inc DWORD [2*r15]
        ; inc DWORD [NOSPLIT 2*r15]
        ; inc DWORD [1*r15 + r14]
        ; inc DWORD [rax + rax + rax + rax + rbx]
        // weird registers
        ; xchg al, ah
        ; xchg al, dil
        // register-specific forms
        ; adc rax, 5
        // multi arg forms
        ; mov rax, rbx
        ; mov rax, [rbx]
        ; mov [rbx], rax
        ; mov rax, 1
        ; mov BYTE [rax], 1
        ; imul rax, rbx, 1
        ; imul rax, [rbx], 1
        // prefixes
        ; fs inc DWORD [rax]
        ; lock fs inc DWORD [rax]
        ; rep stosq
        ; inc DWORD [eax]
        // really long instructions
        ; fs imul r9w, [r10d*8 + r11d + 0x66778899], 0x1122
        ; fs imul r9,  [edi*8 + r11d + 0x66778899], 0x11223344
        ; fs mov r9, QWORD 0x1122334455667788
        ; fs movabs rax, 0x1122334455667788
        // funky syntax features
        ; inc BYTE [rax]
        ; inc WORD [rax]
        ; inc DWORD [rax]
        ; inc QWORD [rax]
        ; inc QWORD [BYTE rax + 0]
        ; inc QWORD [DWORD rax + 0]
        // very odd memoryrefs
        ; mov rax, [rbx + rbx * 3 + 2 + c + rax + d]
        ; mov rax, [rbx - 4]
        // labels
        ; a: // local
        ; -> b: // global
        ; => label // dynamic. note the lack of a trailing :. this is due to : being a valid symbol within expressions that does not occur in any other normal rust expr contexts.
        // jumps
        ; jmp <a
        ; jmp -> b
        ; jmp => label
        // rip relative stuff
        ; lea rax, [->b]
        // dynamic registers
        ; inc Rb(1)
        ; inc Rh(5)
        ; inc Rw(1)
        ; inc Rd(1)
        ; inc Rq(1)
        ; mov Rb(7), [Rq(3)*4 + rax]
        ; fsub Rf(5), st0
        // other register families
        ; mov cr1, rax
        ; mov dr1, rax
        ; mov rax, cr1
        ; mov rax, dr1
        ; pop fs
        ; movmskps eax, xmm7
        ; movd mm7, eax
        ; movd eax, mm7
        ; fcomp st0
        // VEX/XOP instructions
        ; andn rax, rcx, rdx
        ; andn r8, r9, r10
        ; bextr rax, rbx, 1
        ; vaddpd xmm0, xmm1, [rax]
        // VSIB addressing
        ; vgatherqpd ymm1, QWORD [ymm15 + rsi + 0x11112222], ymm8
        ; vgatherqpd ymm1, QWORD [NOSPLIT rsi + ymm15 + 0x11112222], ymm8
        ; vgatherqpd ymm1, QWORD [ymm15*8 + rsi + 0x11112222], ymm8
        // 4 argument instructions
        ; vfmaddss xmm0, xmm1, xmm2, xmm3
        // directives
        ; string:
        //; .bytes "Hello world!\0".bytes()
    );

    // typemap support
    #[allow(dead_code)]
    struct Test {
        foo: i32,
        bar: u32
    }
    #[allow(dead_code)]
    struct SmallTest {
        foo: i8,
        bar: u8
    }
    let mut test_array = [Test {foo: 1, bar: 2}, Test {foo: 3, bar: 4}, Test {foo: 5, bar: 6}];
    let test_array = &mut test_array;
    let mut test_single = Test {foo: 7, bar: 8};
    let test_single = &mut test_single;
    dynasm!(ops
        ; mov rax, AWORD MutPointer!(test_array)
        ; mov ebx, 2
        ; vgatherqpd ymm13, QWORD rax => f64[ymm15], ymm14
        ; inc DWORD rax => Test[2].bar
        ; inc DWORD rax => Test[BYTE 2]
        ; inc DWORD rax => Test[BYTE 0].bar
        ; inc DWORD rax => Test[2 + rbx].bar
        ; inc DWORD rax => Test[rbx].bar
        ; inc DWORD rax => Test[rbx]
        ; inc DWORD rax => Test[rbx + 2]
        ; inc DWORD rax => SmallTest[4*rbx + 2].bar
        ; inc DWORD rax => SmallTest[BYTE 2*rbx + 2].bar
        ; mov rax, AWORD MutPointer!(test_single)
        ; inc DWORD rax => Test.bar
    );

    // dynasm in expr position
    match 1 {
        0 => (),
        _ => dynasm!(ops; inc rax)
    }

    // fixups
    let start = ops.offset();
    dynasm!( (ops)
        ; inc rbx
    );
    let end = ops.offset();
    ops.alter(|ops| {
        ops.goto(start);
        dynasm!(ops
            ; inc r12
        );
        ops.check(end);
    });

    let index = ops.offset();
    dynasm!(ops
        ; mov eax, 10203040
        ; ret
    );

    let buf = ops.finalize().unwrap();

    println!("Generated assembly:");
    for i in buf.iter() {
        print!("{:02x }", i);
    }
    println!("");

    let func: extern "C" fn() -> i64 = unsafe { std::mem::transmute(buf.ptr(index)) };
    println!("assembled function result: {}", func() );
}

#[test]
fn complex_complex1() {
    complex1();
}
<|endoftext|>


<commit_before>mod statement_cache;
mod transaction_manager;

use backend::Backend;
use query_builder::{AsQuery, QueryFragment, QueryId};
use query_source::Queryable;
use result::*;
use types::HasSqlType;

pub use self::transaction_manager::{TransactionManager, AnsiTransactionManager};
#[doc(hidden)]
pub use self::statement_cache::{StatementCache, StatementCacheKey, MaybeCached};

/// Perform simple operations on a backend.
pub trait SimpleConnection {
    /// Execute multiple SQL statements within the same string.
    ///
    /// This function is typically used in migrations where the statements to upgrade or
    /// downgrade the database are stored in SQL batch files.
    fn batch_execute(&self, query: &str) -> QueryResult<()>;
}

/// Perform connections to a backend.
pub trait Connection: SimpleConnection + Sized + Send {
    /// The backend this connection represents.
    type Backend: Backend;
    #[doc(hidden)]
    type TransactionManager: TransactionManager<Self>;

    /// Establishes a new connection to the database at the given URL. The URL
    /// should be a valid connection string for a given backend. See the
    /// documentation for the specific backend for specifics.
    fn establish(database_url: &str) -> ConnectionResult<Self>;

    /// Executes the given function inside of a database transaction. When
    /// a transaction is already occurring, savepoints will be used to emulate a nested
    /// transaction.
    ///
    /// The error returned from the function must implement
    /// `From<diesel::result::Error>`.
    fn transaction<T, E, F>(&self, f: F) -> Result<T, E> where
        F: FnOnce() -> Result<T, E>,
        E: From<Error>,
    {
        let transaction_manager = self.transaction_manager();
        try!(transaction_manager.begin_transaction(self));
        match f() {
            Ok(value) => {
                try!(transaction_manager.commit_transaction(self));
                Ok(value)
            },
            Err(e) => {
                try!(transaction_manager.rollback_transaction(self));
                Err(e)
            },
        }
    }

    /// Creates a transaction that will never be committed. This is useful for
    /// tests. Panics if called while inside of a transaction.
    fn begin_test_transaction(&self) -> QueryResult<()> {
        let transaction_manager = self.transaction_manager();
        assert_eq!(transaction_manager.get_transaction_depth(), 0);
        transaction_manager.begin_transaction(self)
    }

    /// Executes the given function inside a transaction, but does not commit
    /// it. Panics if the given function returns an `Err`.
    fn test_transaction<T, E, F>(&self, f: F) -> T where
        F: FnOnce() -> Result<T, E>,
    {
        let mut user_result = None;
        let _ = self.transaction::<(), _, _>(|| {
            user_result = f().ok();
            Err(Error::RollbackTransaction)
        });
        user_result.expect("Transaction did not succeed")
    }

    #[doc(hidden)]
    fn execute(&self, query: &str) -> QueryResult<usize>;

    #[doc(hidden)]
    fn query_one<T, U>(&self, source: T) -> QueryResult<U> where
        T: AsQuery,
        T::Query: QueryFragment<Self::Backend> + QueryId,
        Self::Backend: HasSqlType<T::SqlType>,
        U: Queryable<T::SqlType, Self::Backend>,
    {
        self.query_all(source)
            .and_then(|e: Vec<U>| e.into_iter().next().ok_or(Error::NotFound))
    }

    #[doc(hidden)]
    fn query_all<T, U>(&self, source: T) -> QueryResult<Vec<U>> where
        T: AsQuery,
        T::Query: QueryFragment<Self::Backend> + QueryId,
        Self::Backend: HasSqlType<T::SqlType>,
        U: Queryable<T::SqlType, Self::Backend>;

    #[doc(hidden)]
    fn execute_returning_count<T>(&self, source: &T) -> QueryResult<usize> where
        T: QueryFragment<Self::Backend> + QueryId;

    #[doc(hidden)] fn silence_notices<F: FnOnce() -> T, T>(&self, f: F) -> T;
    #[doc(hidden)] fn transaction_manager(&self) -> &Self::TransactionManager;
    #[doc(hidden)] fn setup_helper_functions(&self);
}
<commit_msg>Add an example for the transactions function<commit_after>mod statement_cache;
mod transaction_manager;

use backend::Backend;
use query_builder::{AsQuery, QueryFragment, QueryId};
use query_source::Queryable;
use result::*;
use types::HasSqlType;

pub use self::transaction_manager::{TransactionManager, AnsiTransactionManager};
#[doc(hidden)]
pub use self::statement_cache::{StatementCache, StatementCacheKey, MaybeCached};

/// Perform simple operations on a backend.
pub trait SimpleConnection {
    /// Execute multiple SQL statements within the same string.
    ///
    /// This function is typically used in migrations where the statements to upgrade or
    /// downgrade the database are stored in SQL batch files.
    fn batch_execute(&self, query: &str) -> QueryResult<()>;
}

/// Perform connections to a backend.
pub trait Connection: SimpleConnection + Sized + Send {
    /// The backend this connection represents.
    type Backend: Backend;
    #[doc(hidden)]
    type TransactionManager: TransactionManager<Self>;

    /// Establishes a new connection to the database at the given URL. The URL
    /// should be a valid connection string for a given backend. See the
    /// documentation for the specific backend for specifics.
    fn establish(database_url: &str) -> ConnectionResult<Self>;

    /// Executes the given function inside of a database transaction. When
    /// a transaction is already occurring, savepoints will be used to emulate a nested
    /// transaction.
    ///
    /// The error returned from the function must implement
    /// `From<diesel::result::Error>`.
    ///
    /// # Examples:
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # #[macro_use] extern crate diesel_codegen;
    /// # include!("src/doctest_setup.rs");
    /// # table!(
    /// #    users(id) {
    /// #        id -> Integer,
    /// #        name -> Varchar,
    /// #    }
    /// # );
    /// # #[derive(Queryable, Debug, PartialEq)]
    /// # struct User {
    /// #     id: i32,
    /// #     name: String,
    /// # }
    /// use diesel::result::Error;
    ///
    /// fn main() {
    ///     let conn = establish_connection();
    ///     let _ = conn.transaction::<_, Error, _>(|| {
    ///         let new_user = NewUser { name: "Ruby".into() };
    ///         diesel::insert(&new_user).into(users::table).execute(&conn)?;
    ///         assert_eq!(users::table.load::<User>(&conn), Ok(vec![
    ///             User { id: 1, name: "Sean".into() },
    ///             User { id: 2, name: "Tess".into() },
    ///             User { id: 3, name: "Ruby".into() },
    ///         ]));
    ///
    ///         Ok(())
    ///     });
    ///
    ///     let _ = conn.transaction::<(), Error, _>(|| {
    ///         let new_user = NewUser { name: "Pascal".into() };
    ///         diesel::insert(&new_user).into(users::table).execute(&conn)?;
    ///
    ///         assert_eq!(users::table.load::<User>(&conn), Ok(vec![
    ///             User { id: 1, name: "Sean".into() },
    ///             User { id: 2, name: "Tess".into() },
    ///             User { id: 3, name: "Ruby".into() },
    ///             User { id: 4, name: "Pascal".into() },
    ///         ]));
    ///
    ///         Err(Error::RollbackTransaction) // Oh noeees, something bad happened :(
    ///     });
    ///
    ///     assert_eq!(users::table.load::<User>(&conn), Ok(vec![
    ///         User { id: 1, name: "Sean".into() },
    ///         User { id: 2, name: "Tess".into() },
    ///         User { id: 3, name: "Ruby".into() },
    ///     ]));
    /// }
    /// ```
    fn transaction<T, E, F>(&self, f: F) -> Result<T, E> where
        F: FnOnce() -> Result<T, E>,
        E: From<Error>,
    {
        let transaction_manager = self.transaction_manager();
        try!(transaction_manager.begin_transaction(self));
        match f() {
            Ok(value) => {
                try!(transaction_manager.commit_transaction(self));
                Ok(value)
            },
            Err(e) => {
                try!(transaction_manager.rollback_transaction(self));
                Err(e)
            },
        }
    }

    /// Creates a transaction that will never be committed. This is useful for
    /// tests. Panics if called while inside of a transaction.
    fn begin_test_transaction(&self) -> QueryResult<()> {
        let transaction_manager = self.transaction_manager();
        assert_eq!(transaction_manager.get_transaction_depth(), 0);
        transaction_manager.begin_transaction(self)
    }

    /// Executes the given function inside a transaction, but does not commit
    /// it. Panics if the given function returns an `Err`.
    fn test_transaction<T, E, F>(&self, f: F) -> T where
        F: FnOnce() -> Result<T, E>,
    {
        let mut user_result = None;
        let _ = self.transaction::<(), _, _>(|| {
            user_result = f().ok();
            Err(Error::RollbackTransaction)
        });
        user_result.expect("Transaction did not succeed")
    }

    #[doc(hidden)]
    fn execute(&self, query: &str) -> QueryResult<usize>;

    #[doc(hidden)]
    fn query_one<T, U>(&self, source: T) -> QueryResult<U> where
        T: AsQuery,
        T::Query: QueryFragment<Self::Backend> + QueryId,
        Self::Backend: HasSqlType<T::SqlType>,
        U: Queryable<T::SqlType, Self::Backend>,
    {
        self.query_all(source)
            .and_then(|e: Vec<U>| e.into_iter().next().ok_or(Error::NotFound))
    }

    #[doc(hidden)]
    fn query_all<T, U>(&self, source: T) -> QueryResult<Vec<U>> where
        T: AsQuery,
        T::Query: QueryFragment<Self::Backend> + QueryId,
        Self::Backend: HasSqlType<T::SqlType>,
        U: Queryable<T::SqlType, Self::Backend>;

    #[doc(hidden)]
    fn execute_returning_count<T>(&self, source: &T) -> QueryResult<usize> where
        T: QueryFragment<Self::Backend> + QueryId;

    #[doc(hidden)] fn silence_notices<F: FnOnce() -> T, T>(&self, f: F) -> T;
    #[doc(hidden)] fn transaction_manager(&self) -> &Self::TransactionManager;
    #[doc(hidden)] fn setup_helper_functions(&self);
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! disassemble-bpf
//!
//! Utility for disassembling and inspecting eBPF bytecode.

#![warn(missing_docs)]
#![deny(trivial_numeric_casts,
        unsafe_code, unstable_features,
        unused_import_braces, unused_qualifications)]

extern crate disassemble;

use disassemble::{Address, Function, Symbol};

fn main() {
    let prog = &[
            0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
            0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load ptr from r1[0x40] to r2
            0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
            0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load ptr from r1[0x50] to r1
            0x2d, 0x12, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
            0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
            0x67, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, // r0 >>= 56
            0xc7, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, // r0 <<= 56 (arsh)
            0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
        ];

    let f = Function::from_bpf(Symbol::new(Address::new(100000), Some("test")), prog);
    for i in f.instructions {
        println!("{:?}", i);
    }
}
<commit_msg>Display the eBPF instructions nicely.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! disassemble-bpf
//!
//! Utility for disassembling and inspecting eBPF bytecode.

#![warn(missing_docs)]
#![deny(trivial_numeric_casts,
        unsafe_code, unstable_features,
        unused_import_braces, unused_qualifications)]

extern crate disassemble;

use disassemble::{Address, Function, Symbol};

fn main() {
    let prog = &[
            0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
            0x79, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // load ptr from r1[0x40] to r2
            0x07, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // add r2, 5
            0x79, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // load ptr from r1[0x50] to r1
            0x2d, 0x12, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // if r2 > r1 skip 3 instructions
            0x71, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load r2 (= *(mem + 5)) into r0
            0x67, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, // r0 >>= 56
            0xc7, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, // r0 <<= 56 (arsh)
            0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
        ];

    let f = Function::from_bpf(Symbol::new(Address::new(100000), Some("test")), prog);
    for i in f.instructions {
        println!("{}", i);
    }
}
<|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 https://mozilla.org/MPL/2.0/. */

use proc_macro2::TokenStream;
use syn::{self, DeriveInput};

type Fields = syn::punctuated::Punctuated<syn::Field, syn::token::Comma>;

fn derive_trait(
    input: &DeriveInput,
    trait_name: TokenStream,
    generics: &syn::Generics,
    body: impl FnOnce() -> TokenStream,
) -> TokenStream {
    let struct_name = &input.ident;

    let (impl_generics, _, where_clause) = generics.split_for_impl();
    let (_, ty_generics, _) = input.generics.split_for_impl();

    let body = body();
    quote! {
        impl #impl_generics #trait_name for #struct_name #ty_generics #where_clause {
            #body
        }
    }
}

fn derive_simple_trait(
    input: &DeriveInput,
    trait_name: TokenStream,
    t: &syn::TypeParam,
    body: impl FnOnce() -> TokenStream,
) -> TokenStream {
    let mut generics = input.generics.clone();
    generics
        .make_where_clause()
        .predicates
        .push(parse_quote!(#t: #trait_name));
    derive_trait(input, trait_name, &generics, body)
}

fn each_field_except_unit(
    fields: &Fields,
    unit: &syn::Field,
    mut field_expr: impl FnMut(&syn::Ident) -> TokenStream,
) -> TokenStream {
    fields.iter().filter(|f| f.ident != unit.ident).fold(quote! {}, |body, field| {
        let name = field.ident.as_ref().unwrap();
        let expr = field_expr(name);
        quote! {
            #body
            #expr
        }
    })
}

fn derive_struct_body(
    fields: &Fields,
    unit: &syn::Field,
    mut field_expr: impl FnMut(&syn::Ident) -> TokenStream,
) -> TokenStream {
    let body = each_field_except_unit(fields, unit, |name| {
        let expr = field_expr(name);
        quote! {
            #name: #expr,
        }
    });

    let unit_name = unit.ident.as_ref().unwrap();
    quote! {
        Self {
            #body
            #unit_name: PhantomData,
        }
    }
}

fn clone_impl(input: &DeriveInput, fields: &Fields, unit: &syn::Field, t: &syn::TypeParam) -> TokenStream {
    derive_simple_trait(input, quote! { Clone }, t, || {
        let body = derive_struct_body(fields, unit, |name| {
            quote! { self.#name.clone() }
        });
        quote! {
            fn clone(&self) -> Self {
                #body
            }
        }
    })
}

fn copy_impl(input: &DeriveInput, t: &syn::TypeParam) -> TokenStream {
    derive_simple_trait(input, quote!{ Copy }, t, || quote! {})
}

fn eq_impl(input: &DeriveInput, t: &syn::TypeParam) -> TokenStream {
    derive_simple_trait(input, quote!{ ::core::cmp::Eq }, t, || quote! {})
}

fn partialeq_impl(input: &DeriveInput, fields: &Fields, unit: &syn::Field, t: &syn::TypeParam) -> TokenStream {
    derive_simple_trait(input, quote!{ ::core::cmp::PartialEq }, t, || {
        let body = each_field_except_unit(fields, unit, |name| {
            quote! { && self.#name == other.#name }
        });

        quote! {
            fn eq(&self, other: &Self) -> bool {
                true #body
            }
        }
    })
}

fn hash_impl(input: &DeriveInput, fields: &Fields, unit: &syn::Field, t: &syn::TypeParam) -> TokenStream {
    derive_simple_trait(input, quote!{ ::core::hash::Hash }, t, || {
        let body = each_field_except_unit(fields, unit, |name| {
            quote! { self.#name.hash(h); }
        });

        quote! {
            fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
                #body
            }
        }
    })
}

fn serde_impl(
    input: &DeriveInput,
    fields: &Fields,
    unit: &syn::Field,
    t: &syn::TypeParam,
) -> TokenStream {
    let deserialize_impl = {
        let mut generics = input.generics.clone();
        generics.params.insert(0, parse_quote!('de));
        generics
            .make_where_clause()
            .predicates
            .push(parse_quote!(#t: ::serde::Deserialize<'de>));
        derive_trait(input, quote!{ ::serde::Deserialize<'de> }, &generics, || {
            let tuple = each_field_except_unit(fields, unit, |name| {
                quote! { #name, }
            });
            let body = derive_struct_body(fields, unit, |name| quote! { #name });
            quote! {
                fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
                where
                    D: ::serde::Deserializer<'de>,
                {
                    let (#tuple) = ::serde::Deserialize::deserialize(deserializer)?;
                    Ok(#body)
                }
            }
        })
    };

    let serialize_impl = derive_simple_trait(input, quote! { ::serde::Serialize }, t, || {
        let tuple = each_field_except_unit(fields, unit, |name| {
            quote! { &self.#name, }
        });
        quote! {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: ::serde::Serializer,
            {
                (#tuple).serialize(serializer)
            }
        }
    });

    quote! {
        #[cfg(feature = "serde")]
        #serialize_impl
        #[cfg(feature = "serde")]
        #deserialize_impl
    }
}

pub fn derive(input: DeriveInput) -> TokenStream {
    let s = match input.data {
        syn::Data::Struct(ref s) => s,
        _ => panic!("Need to derive this on a struct"),
    };

    let fields = match s.fields {
        syn::Fields::Named(ref named) => &named.named,
        _ => panic!("Need to use named fields"),
    };

    assert!(!fields.is_empty());

    let unit_field = fields.last().unwrap();
    assert_eq!(
        unit_field.value().ident.as_ref().unwrap().to_string(),
        "_unit",
        "You need to have a _unit field to derive this trait",
    );

    assert!(match unit_field.value().vis {
        syn::Visibility::Public(..) => true,
        _ => false,
    }, "Unit field should be public");

    assert!(input.attrs.iter().filter_map(|attr| attr.interpret_meta()).any(|attr| {
        match attr {
            syn::Meta::Word(..) |
            syn::Meta::NameValue(..) => false,
            syn::Meta::List(ref list) => {
                list.ident == "repr" && list.nested.iter().any(|meta| {
                    match meta {
                        syn::NestedMeta::Meta(syn::Meta::Word(ref w)) => w == "C",
                        _ => false,
                    }
                })
            }
        }
    }), "struct should be #[repr(C)]");

    let type_param =
        input.generics.type_params().next().cloned().expect("Need a T");

    let clone = clone_impl(&input, fields, unit_field.value(), &type_param);
    let copy = copy_impl(&input, &type_param);
    let serde = serde_impl(&input, fields, unit_field.value(), &type_param);
    let eq = eq_impl(&input, &type_param);
    let partialeq = partialeq_impl(&input, fields, unit_field.value(), &type_param);
    let hash = hash_impl(&input, fields, unit_field.value(), &type_param);

    quote! {
        #clone
        #copy
        #serde
        #eq
        #partialeq
        #hash
    }
}
<commit_msg>macros: Make it build with rust 1.23.<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 https://mozilla.org/MPL/2.0/. */

use proc_macro2::TokenStream;
use syn::{self, DeriveInput};

type Fields = syn::punctuated::Punctuated<syn::Field, syn::token::Comma>;

fn derive_trait<F>(
    input: &DeriveInput,
    trait_name: TokenStream,
    generics: &syn::Generics,
    body: F
) -> TokenStream
where
    F: FnOnce() -> TokenStream,
{
    let struct_name = &input.ident;

    let (impl_generics, _, where_clause) = generics.split_for_impl();
    let (_, ty_generics, _) = input.generics.split_for_impl();

    let body = body();
    quote! {
        impl #impl_generics #trait_name for #struct_name #ty_generics #where_clause {
            #body
        }
    }
}

fn derive_simple_trait<F>(
    input: &DeriveInput,
    trait_name: TokenStream,
    t: &syn::TypeParam,
    body: F,
) -> TokenStream
where
    F: FnOnce() -> TokenStream,
{
    let mut generics = input.generics.clone();
    generics
        .make_where_clause()
        .predicates
        .push(parse_quote!(#t: #trait_name));
    derive_trait(input, trait_name, &generics, body)
}

fn each_field_except_unit<F>(
    fields: &Fields,
    unit: &syn::Field,
    mut field_expr: F,
) -> TokenStream
where
    F: FnMut(&syn::Ident) -> TokenStream,
{
    fields.iter().filter(|f| f.ident != unit.ident).fold(quote! {}, |body, field| {
        let name = field.ident.as_ref().unwrap();
        let expr = field_expr(name);
        quote! {
            #body
            #expr
        }
    })
}

fn derive_struct_body<F>(
    fields: &Fields,
    unit: &syn::Field,
    mut field_expr: F,
) -> TokenStream
where
    F: FnMut(&syn::Ident) -> TokenStream,
{
    let body = each_field_except_unit(fields, unit, |name| {
        let expr = field_expr(name);
        quote! {
            #name: #expr,
        }
    });

    let unit_name = unit.ident.as_ref().unwrap();
    quote! {
        Self {
            #body
            #unit_name: PhantomData,
        }
    }
}

fn clone_impl(input: &DeriveInput, fields: &Fields, unit: &syn::Field, t: &syn::TypeParam) -> TokenStream {
    derive_simple_trait(input, quote! { Clone }, t, || {
        let body = derive_struct_body(fields, unit, |name| {
            quote! { self.#name.clone() }
        });
        quote! {
            fn clone(&self) -> Self {
                #body
            }
        }
    })
}

fn copy_impl(input: &DeriveInput, t: &syn::TypeParam) -> TokenStream {
    derive_simple_trait(input, quote!{ Copy }, t, || quote! {})
}

fn eq_impl(input: &DeriveInput, t: &syn::TypeParam) -> TokenStream {
    derive_simple_trait(input, quote!{ ::core::cmp::Eq }, t, || quote! {})
}

fn partialeq_impl(input: &DeriveInput, fields: &Fields, unit: &syn::Field, t: &syn::TypeParam) -> TokenStream {
    derive_simple_trait(input, quote!{ ::core::cmp::PartialEq }, t, || {
        let body = each_field_except_unit(fields, unit, |name| {
            quote! { && self.#name == other.#name }
        });

        quote! {
            fn eq(&self, other: &Self) -> bool {
                true #body
            }
        }
    })
}

fn hash_impl(input: &DeriveInput, fields: &Fields, unit: &syn::Field, t: &syn::TypeParam) -> TokenStream {
    derive_simple_trait(input, quote!{ ::core::hash::Hash }, t, || {
        let body = each_field_except_unit(fields, unit, |name| {
            quote! { self.#name.hash(h); }
        });

        quote! {
            fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
                #body
            }
        }
    })
}

fn serde_impl(
    input: &DeriveInput,
    fields: &Fields,
    unit: &syn::Field,
    t: &syn::TypeParam,
) -> TokenStream {
    let deserialize_impl = {
        let mut generics = input.generics.clone();
        generics.params.insert(0, parse_quote!('de));
        generics
            .make_where_clause()
            .predicates
            .push(parse_quote!(#t: ::serde::Deserialize<'de>));
        derive_trait(input, quote!{ ::serde::Deserialize<'de> }, &generics, || {
            let tuple = each_field_except_unit(fields, unit, |name| {
                quote! { #name, }
            });
            let body = derive_struct_body(fields, unit, |name| quote! { #name });
            quote! {
                fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
                where
                    D: ::serde::Deserializer<'de>,
                {
                    let (#tuple) = ::serde::Deserialize::deserialize(deserializer)?;
                    Ok(#body)
                }
            }
        })
    };

    let serialize_impl = derive_simple_trait(input, quote! { ::serde::Serialize }, t, || {
        let tuple = each_field_except_unit(fields, unit, |name| {
            quote! { &self.#name, }
        });
        quote! {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: ::serde::Serializer,
            {
                (#tuple).serialize(serializer)
            }
        }
    });

    quote! {
        #[cfg(feature = "serde")]
        #serialize_impl
        #[cfg(feature = "serde")]
        #deserialize_impl
    }
}

pub fn derive(input: DeriveInput) -> TokenStream {
    let s = match input.data {
        syn::Data::Struct(ref s) => s,
        _ => panic!("Need to derive this on a struct"),
    };

    let fields = match s.fields {
        syn::Fields::Named(ref named) => &named.named,
        _ => panic!("Need to use named fields"),
    };

    assert!(!fields.is_empty());

    let unit_field = fields.last().unwrap();
    assert_eq!(
        unit_field.value().ident.as_ref().unwrap().to_string(),
        "_unit",
        "You need to have a _unit field to derive this trait",
    );

    assert!(match unit_field.value().vis {
        syn::Visibility::Public(..) => true,
        _ => false,
    }, "Unit field should be public");

    assert!(input.attrs.iter().filter_map(|attr| attr.interpret_meta()).any(|attr| {
        match attr {
            syn::Meta::Word(..) |
            syn::Meta::NameValue(..) => false,
            syn::Meta::List(ref list) => {
                list.ident == "repr" && list.nested.iter().any(|meta| {
                    match *meta {
                        syn::NestedMeta::Meta(syn::Meta::Word(ref w)) => w == "C",
                        _ => false,
                    }
                })
            }
        }
    }), "struct should be #[repr(C)]");

    let type_param =
        input.generics.type_params().next().cloned().expect("Need a T");

    let clone = clone_impl(&input, fields, unit_field.value(), &type_param);
    let copy = copy_impl(&input, &type_param);
    let serde = serde_impl(&input, fields, unit_field.value(), &type_param);
    let eq = eq_impl(&input, &type_param);
    let partialeq = partialeq_impl(&input, fields, unit_field.value(), &type_param);
    let hash = hash_impl(&input, fields, unit_field.value(), &type_param);

    quote! {
        #clone
        #copy
        #serde
        #eq
        #partialeq
        #hash
    }
}
<|endoftext|>


<commit_before>//! EGL utilities
//!
//! This module contains bindings to the `libwayland-egl.so` library.
//!
//! This library is used to interface with the OpenGL stack, and creating
//! EGL surfaces from a wayland surface.
//!
//! See WlEglSurface documentation for details.

use Proxy;
use protocol::wl_surface::WlSurface;
use std::os::raw::c_void;

use wayland_sys::egl::*;
use wayland_sys::client::wl_proxy;

/// Checks if the wayland-egl lib is available and can be used
///
/// Trying to create an `WlEglSurface` while this function returns
/// `false` will result in a panic.
pub fn is_available() -> bool {
    is_lib_available()
}

unsafe impl Send for WlEglSurface {}
unsafe impl Sync for WlEglSurface {}

/// EGL surface
///
/// This object is a simple wrapper around a `WlSurface` to add the EGL
/// capabilities. Just use the `ptr` method once this object is created
/// to get the window pointer your OpenGL library is needing to initialize the
/// EGL context (you'll most likely need the display ptr as well, that you can
/// get via the `ptr` method of the `Proxy` trait on the `WlDisplay` object).
pub struct WlEglSurface {
    ptr: *mut wl_egl_window,
}

impl WlEglSurface {
    /// Create an EGL surface from a wayland surface
    pub fn new(surface: &WlSurface, width: i32, height: i32) -> WlEglSurface {
        unsafe { WlEglSurface::new_from_raw(surface.ptr(), width, height) }
    }

    /// Create an EGL surface from a raw pointer to a wayland surface
    ///
    /// This function is unsafe because `surface` must be a valid wl_surface pointer
    pub unsafe fn new_from_raw(surface: *mut wl_proxy, width: i32, height: i32) -> WlEglSurface {
        let ptr = ffi_dispatch!(WAYLAND_EGL_HANDLE,
                          wl_egl_window_create,
                          surface,
                          width,
                          height);
        WlEglSurface { ptr: ptr }
    }

    /// Fetch current size of the EGL surface
    pub fn get_size(&self) -> (i32, i32) {
        let mut w = 0i32;
        let mut h = 0i32;
        unsafe {
            ffi_dispatch!(WAYLAND_EGL_HANDLE,
                          wl_egl_window_get_attached_size,
                          self.ptr,
                          &mut w as *mut i32,
                          &mut h as *mut i32);
        }
        (w, h)
    }

    /// Resize the EGL surface
    ///
    /// The two first arguments `(width, height)` are the new size of
    /// the surface, the two others `(dx, dy)` represent the displacement
    /// of the top-left corner of the surface. It allows you to control the
    /// direction of the resizing if necessary.
    pub fn resize(&self, width: i32, height: i32, dx: i32, dy: i32) {
        unsafe {
            ffi_dispatch!(WAYLAND_EGL_HANDLE,
                          wl_egl_window_resize,
                          self.ptr,
                          width,
                          height,
                          dx,
                          dy)
        }
    }

    /// Raw pointer to the EGL surface
    ///
    /// You'll need this pointer to initialize the EGL context in your
    /// favourite OpenGL lib.
    pub fn ptr(&self) -> *const c_void {
        self.ptr as *const c_void
    }
}

impl Drop for WlEglSurface {
    fn drop(&mut self) {
        unsafe {
            ffi_dispatch!(WAYLAND_EGL_HANDLE, wl_egl_window_destroy, self.ptr);
        }
    }
}
<commit_msg>cargo fmt<commit_after>//! EGL utilities
//!
//! This module contains bindings to the `libwayland-egl.so` library.
//!
//! This library is used to interface with the OpenGL stack, and creating
//! EGL surfaces from a wayland surface.
//!
//! See WlEglSurface documentation for details.

use Proxy;
use protocol::wl_surface::WlSurface;
use std::os::raw::c_void;
use wayland_sys::client::wl_proxy;

use wayland_sys::egl::*;

/// Checks if the wayland-egl lib is available and can be used
///
/// Trying to create an `WlEglSurface` while this function returns
/// `false` will result in a panic.
pub fn is_available() -> bool {
    is_lib_available()
}

unsafe impl Send for WlEglSurface {}
unsafe impl Sync for WlEglSurface {}

/// EGL surface
///
/// This object is a simple wrapper around a `WlSurface` to add the EGL
/// capabilities. Just use the `ptr` method once this object is created
/// to get the window pointer your OpenGL library is needing to initialize the
/// EGL context (you'll most likely need the display ptr as well, that you can
/// get via the `ptr` method of the `Proxy` trait on the `WlDisplay` object).
pub struct WlEglSurface {
    ptr: *mut wl_egl_window,
}

impl WlEglSurface {
    /// Create an EGL surface from a wayland surface
    pub fn new(surface: &WlSurface, width: i32, height: i32) -> WlEglSurface {
        unsafe { WlEglSurface::new_from_raw(surface.ptr(), width, height) }
    }

    /// Create an EGL surface from a raw pointer to a wayland surface
    ///
    /// This function is unsafe because `surface` must be a valid wl_surface pointer
    pub unsafe fn new_from_raw(surface: *mut wl_proxy, width: i32, height: i32) -> WlEglSurface {
        let ptr = ffi_dispatch!(WAYLAND_EGL_HANDLE,
                                wl_egl_window_create,
                                surface,
                                width,
                                height);
        WlEglSurface { ptr: ptr }
    }

    /// Fetch current size of the EGL surface
    pub fn get_size(&self) -> (i32, i32) {
        let mut w = 0i32;
        let mut h = 0i32;
        unsafe {
            ffi_dispatch!(WAYLAND_EGL_HANDLE,
                          wl_egl_window_get_attached_size,
                          self.ptr,
                          &mut w as *mut i32,
                          &mut h as *mut i32);
        }
        (w, h)
    }

    /// Resize the EGL surface
    ///
    /// The two first arguments `(width, height)` are the new size of
    /// the surface, the two others `(dx, dy)` represent the displacement
    /// of the top-left corner of the surface. It allows you to control the
    /// direction of the resizing if necessary.
    pub fn resize(&self, width: i32, height: i32, dx: i32, dy: i32) {
        unsafe {
            ffi_dispatch!(WAYLAND_EGL_HANDLE,
                          wl_egl_window_resize,
                          self.ptr,
                          width,
                          height,
                          dx,
                          dy)
        }
    }

    /// Raw pointer to the EGL surface
    ///
    /// You'll need this pointer to initialize the EGL context in your
    /// favourite OpenGL lib.
    pub fn ptr(&self) -> *const c_void {
        self.ptr as *const c_void
    }
}

impl Drop for WlEglSurface {
    fn drop(&mut self) {
        unsafe {
            ffi_dispatch!(WAYLAND_EGL_HANDLE, wl_egl_window_destroy, self.ptr);
        }
    }
}
<|endoftext|>


<commit_before>//! An asynchronous, pipelined, PostgreSQL client.
//!
//! # Example
//!
//! ```no_run
//! #![feature(async_await)]
//!
//! use futures::{FutureExt, TryStreamExt};
//! use tokio_postgres::{NoTls, Error, Row};
//!
//! # #[cfg(not(feature = "runtime"))] fn main() {}
//! # #[cfg(feature = "runtime")]
//! #[tokio::main] // By default, tokio_postgres uses the tokio crate as its runtime.
//! async fn main() -> Result<(), Error> {
//!     // Connect to the database.
//!     let (mut client, connection) =
//!         tokio_postgres::connect("host=localhost user=postgres", NoTls).await?;
//!
//!     // The connection object performs the actual communication with the database,
//!     // so spawn it off to run on its own.
//!     let connection = connection.map(|r| {
//!         if let Err(e) = r {
//!             eprintln!("connection error: {}", e);
//!         }
//!     });
//!     tokio::spawn(connection);
//!
//!     // Now we can prepare a simple statement that just returns its parameter.
//!     let stmt = client.prepare("SELECT $1::TEXT").await?;
//!
//!     // And then execute it, returning a Stream of Rows which we collect into a Vec.
//!     let rows: Vec<Row> = client
//!         .query(&stmt, &[&"hello world"])
//!         .try_collect()
//!         .await?;
//!
//!     // Now we can check that we got back the same string we sent over.
//!     let value: &str = rows[0].get(0);
//!     assert_eq!(value, "hello world");
//!
//!     Ok(())
//! }
//! ```
//!
//! # Behavior
//!
//! Calling a method like `Client::query` on its own does nothing. The associated request is not sent to the database
//! until the future returned by the method is first polled. Requests are executed in the order that they are first
//! polled, not in the order that their futures are created.
//!
//! # Pipelining
//!
//! The client supports *pipelined* requests. Pipelining can improve performance in use cases in which multiple,
//! independent queries need to be executed. In a traditional workflow, each query is sent to the server after the
//! previous query completes. In contrast, pipelining allows the client to send all of the queries to the server up
//! front, minimizing time spent by one side waiting for the other to finish sending data:
//!
//! ```not_rust
//!             Sequential                              Pipelined
//! | Client         | Server          |    | Client         | Server          |
//! |----------------|-----------------|    |----------------|-----------------|
//! | send query 1   |                 |    | send query 1   |                 |
//! |                | process query 1 |    | send query 2   | process query 1 |
//! | receive rows 1 |                 |    | send query 3   | process query 2 |
//! | send query 2   |                 |    | receive rows 1 | process query 3 |
//! |                | process query 2 |    | receive rows 2 |                 |
//! | receive rows 2 |                 |    | receive rows 3 |                 |
//! | send query 3   |                 |
//! |                | process query 3 |
//! | receive rows 3 |                 |
//! ```
//!
//! In both cases, the PostgreSQL server is executing the queries sequentially - pipelining just allows both sides of
//! the connection to work concurrently when possible.
//!
//! Pipelining happens automatically when futures are polled concurrently (for example, by using the futures `join`
//! combinator):
//!
//! ```rust
//! use futures::future;
//! use std::future::Future;
//! use tokio_postgres::{Client, Error, Statement};
//!
//! fn pipelined_prepare(
//!     client: &mut Client,
//! ) -> impl Future<Output = Result<(Statement, Statement), Error>>
//! {
//!     future::try_join(
//!         client.prepare("SELECT * FROM foo"),
//!         client.prepare("INSERT INTO bar (id, name) VALUES ($1, $2)")
//!     )
//! }
//! ```
//!
//! # Runtime
//!
//! The client works with arbitrary `AsyncRead + AsyncWrite` streams. Convenience APIs are provided to handle the
//! connection process, but these are gated by the `runtime` Cargo feature, which is enabled by default. If disabled,
//! all dependence on the tokio runtime is removed.
//!
//! # SSL/TLS support
//!
//! TLS support is implemented via external libraries. `Client::connect` and `Config::connect` take a TLS implementation
//! as an argument. The `NoTls` type in this crate can be used when TLS is not required. Otherwise, the
//! `postgres-openssl` and `postgres-native-tls` crates provide implementations backed by the `openssl` and `native-tls`
//! crates, respectively.
#![doc(html_root_url = "https://docs.rs/tokio-postgres/0.4.0-rc.3")]
#![warn(rust_2018_idioms, clippy::all, missing_docs)]

pub use crate::client::Client;
pub use crate::config::Config;
pub use crate::connection::Connection;
use crate::error::DbError;
pub use crate::error::Error;
pub use crate::portal::Portal;
pub use crate::row::{Row, SimpleQueryRow};
#[cfg(feature = "runtime")]
pub use crate::socket::Socket;
#[cfg(feature = "runtime")]
use crate::tls::MakeTlsConnect;
pub use crate::tls::NoTls;
pub use crate::transaction::Transaction;
pub use statement::{Column, Statement};

mod bind;
#[cfg(feature = "runtime")]
mod cancel_query;
mod cancel_query_raw;
mod client;
mod codec;
pub mod config;
#[cfg(feature = "runtime")]
mod connect;
mod connect_raw;
#[cfg(feature = "runtime")]
mod connect_socket;
mod connect_tls;
mod connection;
mod copy_in;
mod copy_out;
pub mod error;
mod maybe_tls_stream;
mod portal;
mod prepare;
mod query;
pub mod row;
mod simple_query;
#[cfg(feature = "runtime")]
mod socket;
mod statement;
pub mod tls;
mod transaction;
pub mod types;

/// A convenience function which parses a connection string and connects to the database.
///
/// See the documentation for [`Config`] for details on the connection string format.
///
/// Requires the `runtime` Cargo feature (enabled by default).
///
/// [`Config`]: config/struct.Config.html
#[cfg(feature = "runtime")]
pub async fn connect<T>(
    config: &str,
    tls: T,
) -> Result<(Client, Connection<Socket, T::Stream>), Error>
where
    T: MakeTlsConnect<Socket>,
{
    let config = config.parse::<Config>()?;
    config.connect(tls).await
}

/// An asynchronous notification.
#[derive(Clone, Debug)]
pub struct Notification {
    process_id: i32,
    channel: String,
    payload: String,
}

impl Notification {
    /// The process ID of the notifying backend process.
    pub fn process_id(&self) -> i32 {
        self.process_id
    }

    /// The name of the channel that the notify has been raised on.
    pub fn channel(&self) -> &str {
        &self.channel
    }

    /// The "payload" string passed from the notifying process.
    pub fn payload(&self) -> &str {
        &self.payload
    }
}

/// An asynchronous message from the server.
#[allow(clippy::large_enum_variant)]
pub enum AsyncMessage {
    /// A notice.
    ///
    /// Notices use the same format as errors, but aren't "errors" per-se.
    Notice(DbError),
    /// A notification.
    ///
    /// Connections can subscribe to notifications with the `LISTEN` command.
    Notification(Notification),
    #[doc(hidden)]
    __NonExhaustive,
}

/// Message returned by the `SimpleQuery` stream.
pub enum SimpleQueryMessage {
    /// A row of data.
    Row(SimpleQueryRow),
    /// A statement in the query has completed.
    ///
    /// The number of rows modified or selected is returned.
    CommandComplete(u64),
    #[doc(hidden)]
    __NonExhaustive,
}
<commit_msg>Remove unneeded feature gate<commit_after>//! An asynchronous, pipelined, PostgreSQL client.
//!
//! # Example
//!
//! ```no_run
//! use futures::{FutureExt, TryStreamExt};
//! use tokio_postgres::{NoTls, Error, Row};
//!
//! # #[cfg(not(feature = "runtime"))] fn main() {}
//! # #[cfg(feature = "runtime")]
//! #[tokio::main] // By default, tokio_postgres uses the tokio crate as its runtime.
//! async fn main() -> Result<(), Error> {
//!     // Connect to the database.
//!     let (mut client, connection) =
//!         tokio_postgres::connect("host=localhost user=postgres", NoTls).await?;
//!
//!     // The connection object performs the actual communication with the database,
//!     // so spawn it off to run on its own.
//!     let connection = connection.map(|r| {
//!         if let Err(e) = r {
//!             eprintln!("connection error: {}", e);
//!         }
//!     });
//!     tokio::spawn(connection);
//!
//!     // Now we can prepare a simple statement that just returns its parameter.
//!     let stmt = client.prepare("SELECT $1::TEXT").await?;
//!
//!     // And then execute it, returning a Stream of Rows which we collect into a Vec.
//!     let rows: Vec<Row> = client
//!         .query(&stmt, &[&"hello world"])
//!         .try_collect()
//!         .await?;
//!
//!     // Now we can check that we got back the same string we sent over.
//!     let value: &str = rows[0].get(0);
//!     assert_eq!(value, "hello world");
//!
//!     Ok(())
//! }
//! ```
//!
//! # Behavior
//!
//! Calling a method like `Client::query` on its own does nothing. The associated request is not sent to the database
//! until the future returned by the method is first polled. Requests are executed in the order that they are first
//! polled, not in the order that their futures are created.
//!
//! # Pipelining
//!
//! The client supports *pipelined* requests. Pipelining can improve performance in use cases in which multiple,
//! independent queries need to be executed. In a traditional workflow, each query is sent to the server after the
//! previous query completes. In contrast, pipelining allows the client to send all of the queries to the server up
//! front, minimizing time spent by one side waiting for the other to finish sending data:
//!
//! ```not_rust
//!             Sequential                              Pipelined
//! | Client         | Server          |    | Client         | Server          |
//! |----------------|-----------------|    |----------------|-----------------|
//! | send query 1   |                 |    | send query 1   |                 |
//! |                | process query 1 |    | send query 2   | process query 1 |
//! | receive rows 1 |                 |    | send query 3   | process query 2 |
//! | send query 2   |                 |    | receive rows 1 | process query 3 |
//! |                | process query 2 |    | receive rows 2 |                 |
//! | receive rows 2 |                 |    | receive rows 3 |                 |
//! | send query 3   |                 |
//! |                | process query 3 |
//! | receive rows 3 |                 |
//! ```
//!
//! In both cases, the PostgreSQL server is executing the queries sequentially - pipelining just allows both sides of
//! the connection to work concurrently when possible.
//!
//! Pipelining happens automatically when futures are polled concurrently (for example, by using the futures `join`
//! combinator):
//!
//! ```rust
//! use futures::future;
//! use std::future::Future;
//! use tokio_postgres::{Client, Error, Statement};
//!
//! fn pipelined_prepare(
//!     client: &mut Client,
//! ) -> impl Future<Output = Result<(Statement, Statement), Error>>
//! {
//!     future::try_join(
//!         client.prepare("SELECT * FROM foo"),
//!         client.prepare("INSERT INTO bar (id, name) VALUES ($1, $2)")
//!     )
//! }
//! ```
//!
//! # Runtime
//!
//! The client works with arbitrary `AsyncRead + AsyncWrite` streams. Convenience APIs are provided to handle the
//! connection process, but these are gated by the `runtime` Cargo feature, which is enabled by default. If disabled,
//! all dependence on the tokio runtime is removed.
//!
//! # SSL/TLS support
//!
//! TLS support is implemented via external libraries. `Client::connect` and `Config::connect` take a TLS implementation
//! as an argument. The `NoTls` type in this crate can be used when TLS is not required. Otherwise, the
//! `postgres-openssl` and `postgres-native-tls` crates provide implementations backed by the `openssl` and `native-tls`
//! crates, respectively.
#![doc(html_root_url = "https://docs.rs/tokio-postgres/0.4.0-rc.3")]
#![warn(rust_2018_idioms, clippy::all, missing_docs)]

pub use crate::client::Client;
pub use crate::config::Config;
pub use crate::connection::Connection;
use crate::error::DbError;
pub use crate::error::Error;
pub use crate::portal::Portal;
pub use crate::row::{Row, SimpleQueryRow};
#[cfg(feature = "runtime")]
pub use crate::socket::Socket;
#[cfg(feature = "runtime")]
use crate::tls::MakeTlsConnect;
pub use crate::tls::NoTls;
pub use crate::transaction::Transaction;
pub use statement::{Column, Statement};

mod bind;
#[cfg(feature = "runtime")]
mod cancel_query;
mod cancel_query_raw;
mod client;
mod codec;
pub mod config;
#[cfg(feature = "runtime")]
mod connect;
mod connect_raw;
#[cfg(feature = "runtime")]
mod connect_socket;
mod connect_tls;
mod connection;
mod copy_in;
mod copy_out;
pub mod error;
mod maybe_tls_stream;
mod portal;
mod prepare;
mod query;
pub mod row;
mod simple_query;
#[cfg(feature = "runtime")]
mod socket;
mod statement;
pub mod tls;
mod transaction;
pub mod types;

/// A convenience function which parses a connection string and connects to the database.
///
/// See the documentation for [`Config`] for details on the connection string format.
///
/// Requires the `runtime` Cargo feature (enabled by default).
///
/// [`Config`]: config/struct.Config.html
#[cfg(feature = "runtime")]
pub async fn connect<T>(
    config: &str,
    tls: T,
) -> Result<(Client, Connection<Socket, T::Stream>), Error>
where
    T: MakeTlsConnect<Socket>,
{
    let config = config.parse::<Config>()?;
    config.connect(tls).await
}

/// An asynchronous notification.
#[derive(Clone, Debug)]
pub struct Notification {
    process_id: i32,
    channel: String,
    payload: String,
}

impl Notification {
    /// The process ID of the notifying backend process.
    pub fn process_id(&self) -> i32 {
        self.process_id
    }

    /// The name of the channel that the notify has been raised on.
    pub fn channel(&self) -> &str {
        &self.channel
    }

    /// The "payload" string passed from the notifying process.
    pub fn payload(&self) -> &str {
        &self.payload
    }
}

/// An asynchronous message from the server.
#[allow(clippy::large_enum_variant)]
pub enum AsyncMessage {
    /// A notice.
    ///
    /// Notices use the same format as errors, but aren't "errors" per-se.
    Notice(DbError),
    /// A notification.
    ///
    /// Connections can subscribe to notifications with the `LISTEN` command.
    Notification(Notification),
    #[doc(hidden)]
    __NonExhaustive,
}

/// Message returned by the `SimpleQuery` stream.
pub enum SimpleQueryMessage {
    /// A row of data.
    Row(SimpleQueryRow),
    /// A statement in the query has completed.
    ///
    /// The number of rows modified or selected is returned.
    CommandComplete(u64),
    #[doc(hidden)]
    __NonExhaustive,
}
<|endoftext|>


<commit_before>

// -*- rust -*-
fn main() { debug!("hello, world."); }
<commit_msg>test: Use println instead of debug in hello.rs<commit_after>// -*- rust -*-

fn main() {
    io::println("hello, world");
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::{process, env};
use std::path::Path;
use std::error::Error;
use std::fs::{self, OpenOptions};
/* Alias to avoid naming conflict for write_all!() */
use std::fmt::Write as std_write;

use url::Url;
use url_open::UrlOpen;

use serde_json::{from_str, to_string};

use util::*;
use config::Config;
use timesheet::traits::HasHTML;

use timesheet::session::Session;
use timesheet::session::EventType;

#[derive(Serialize, Deserialize, Debug)]
pub struct Timesheet {
    start            : u64,
    end              : u64,
    config           : Config,
    sessions         : Vec<Session>,
}

impl Timesheet {
    /** Initializes the .trk/timesheet.json file which holds
     * the serialized timesheet
     * Returns Some(newTimesheet) if operation succeeded */
    pub fn init(author_name: Option<&str>) -> Option<Timesheet> {
        /* Check if file already exists (no init permitted) */
        if Timesheet::is_init() {
            println!("Timesheet is already initialized!");
            return None;
        }
        /* File does not exist, initialize */
        let git_author_name = git_author();
        let author_name = match author_name {
            Some(name) => name,
            None => {
                match git_author_name {
                    Some(ref git_name) => git_name,
                    None => {
                        println!("Empty name not permitted. \
                                  Please run with 'trk init <name>'");
                        process::exit(0);
                    }
                }
            }
        };
        let mut config = Config::new();
        config.user_name = Some(author_name.to_string());
        let now = get_seconds();
        let sheet = Timesheet {
            start        : now,
            end          : now + 1,
            config       : config,
            sessions     : Vec::<Session>::new(),
        };
        let sheet = if sheet.write_files() {
            git_init_trk();
            Some(sheet)
        } else {
            None
        };
        sheet
    }

    fn is_init() -> bool {
        Path::new("./.trk/timesheet.json").exists() && Timesheet::load_from_file().is_some()
    }

    pub fn new_session(&mut self, timestamp: Option<u64>) -> bool {
        let possible = self.sessions
            .last_mut()
            .map_or(true, |session| {
                if session.is_running() {
                    println!("Last session is still running.");
                }
                !session.is_running()
        });
        if possible {
            match timestamp {
                Some(timestamp) => {
                    let is_valid_ts = match self.sessions.last() {
                        None => timestamp > self.start,
                        Some(last_session) => timestamp > last_session.end,
                    };
                    if is_valid_ts {
                        self.sessions.push(Session::new(Some(timestamp)));
                    } else {
                        println!("That timestamp is invalid.");
                        process::exit(0);
                    }
                }
                None => {
                    self.sessions.push(Session::new(None));
                }
            };
        }
        possible
    }

    pub fn end_session(&mut self, timestamp: Option<u64>) {
        match self.sessions.last_mut() {
            Some(session) => {
                session.update_end();
                session.finalize(timestamp);
                self.end = session.end + 1;
            }
            None => println!("No session to finalize."),
        }
    }

    pub fn pause(&mut self, timestamp: Option<u64>, note: Option<String>) {
        match self.sessions.last_mut() {
            Some(session) => {
                session.push_event(timestamp, note, EventType::Pause);
            }
            None => println!("No session to pause."),
        }
    }

    pub fn resume(&mut self, timestamp: Option<u64>) {
        match self.sessions.last_mut() {
            Some(session) => {
                session.push_event(timestamp, None, EventType::Resume);
            }
            None => println!("No session to pause."),
        }
    }

    pub fn note(&mut self, timestamp: Option<u64>, note_text: String) {
        match self.sessions.last_mut() {
            Some(session) => {
                session.push_event(timestamp, Some(note_text), EventType::Note);
            }
            None => println!("No session to add note to."),
        }
    }

    pub fn add_commit(&mut self, hash: String) {
        let new_needed = self.sessions
            .last()
            .map_or(true, |session| !session.is_running());
        if new_needed {
            self.new_session(None);
        }
        match self.sessions.last_mut() {
            Some(session) => {
                let message = git_commit_message(&hash).unwrap_or(String::new());
                session.push_event(None, Some(message), EventType::Commit { hash });
            }
            None => println!("No session to add commit to."),
        }
    }

    pub fn add_branch(&mut self, name: String) {
        self.sessions
            .last_mut()
            .map(|session| session.add_branch(name));
    }

    fn write_to_html(&self, ago: Option<u64>) -> bool {
        // TODO: avoid time-of-check-to-time-of-use race risk
        let path = Path::new("./timesheet.html");
        let file = OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(&path);

        match file {
            Ok(mut file) => {
                file.write_all(self.to_html(ago).as_bytes()).unwrap();
                format_file("timesheet.html");
                /* Save was successful */
                true
            }
            Err(why) => {
                println!("Could not report sheet! {}", why.description());
                false
            }
        }
    }

    fn write_last_session_html(&self) -> bool {
        let session = match self.sessions.last() {
            Some(session) => session,
            None => return true,
        };
        let path = Path::new("./session.html");
        let file = OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(&path);

        let mut file = match file {
            Ok(file) => file,
            Err(why) => {
                println!("Could not write report to session.html! {}",
                         why.description());
                return false;
            }
        };

        let stylesheets = if self.config.show_commits {
            r#"<link rel="stylesheet" type="text/css" href="style.css">
"#      } else {
            r#"<link rel="stylesheet" type="text/css" href="style.css">
<link rel="stylesheet" type="text/css" href="no_commit.css">
"#
        };

        let html = format!(r#"<!DOCTYPE html>

  {}
  <title>{} for {}</title>

{}

"#,
               stylesheets,
               "Session",
               "Rafael Bachmann",
               session.to_html());
    file.write_all(html.as_bytes()).unwrap();
    format_file("session.html");
    /* Save was successful */
    true
    }

    fn write_to_json(&self) -> bool {
        if !Path::new("./.trk").exists() {
            match fs::create_dir("./.trk") {
                Ok(_) => {}
                _ => {
                    println!("Could not create .trk directory.");
                    process::exit(0);
                }
            }
        }

        let path = Path::new("./.trk/timesheet.json");
        let file = OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(&path);

        match file {
            Ok(mut file) => {
                /* Convert the sheet to a JSON string. */
                let serialized =
                    to_string(&self).expect("Could not write serialized time sheet.");
                file.write_all(serialized.as_bytes()).unwrap();
                /* Save was successful */
                true
            }
            Err(why) => {
                println!("Could not open timesheet.json file: {}",
                         why.description());
                false
            }
        }
    }

    pub fn write_files(&self) -> bool {
        /* TODO: avoid time-of-check-to-time-of-use race risk */
        self.write_to_json() && self.write_to_html(None) && self.write_last_session_html()
    }

    /** Return a Some(Timesheet) struct if a timesheet.json file
     * is present and valid in the .trk directory, and None otherwise.
     * */
    pub fn load_from_file() -> Option<Timesheet> {
        let path = Path::new("./.trk/timesheet.json");
        let file = OpenOptions::new().read(true).open(&path);
        match file {
            Ok(mut file) => {
                let mut serialized = String::new();
                match file.read_to_string(&mut serialized) {
                    Ok(..) => from_str(&serialized).unwrap_or(None),
                    Err(..) => {
                        println!("IO error while reading the timesheet file.");
                        process::exit(0);
                    }
                }
            }
            Err(..) => None,
        }
    }

    pub fn clear() {
        /* Try to get user name */
        let sheet = Timesheet::load_from_file();
        /* In case there is a sheet, there must also be a name */
        let name: Option<String> = sheet.map(|s| s.config.user_name.unwrap());

        let path = Path::new("./.trk/timesheet.json");
        if path.exists() {
            fs::remove_file(&path).unwrap_or_else(|why| {
                println!("Could not remove sessions file: {}", why.description());
            });
        }
        Timesheet::init(name.as_ref().map(|s| s.as_str()));
    }

    pub fn timesheet_status(&self) -> String {
        let mut status = format!("Sheet running for {}\n",
                sec_to_hms_string(get_seconds() - self.start));
        match self.sessions.len() {
            0 => write!(&mut status, "No sessions yet.\n").unwrap(),
            n => {
                write!(&mut status,
                       "{} session(s) so far.\nLast session:\n{}",
                       n,
                       self.sessions[n - 1].status())
                       .unwrap()
            }
        };
        status
    }

    pub fn last_session_status(&self) -> String {
        let status = self.sessions.last().map(|session| session.status());
        status.unwrap_or("No session yet.".to_string())
    }

    fn open_local_html(&self, filename: String) {
        let file_url = match env::current_dir() {
            Ok(dir) => {
                match dir.join(&filename).to_str() {
                    Some(path) => format!("file://{}", path),
                    None => {
                        println!("Invalid filename: {}.", filename);
                        process::exit(0)
                    }
                }
            }
            Err(why) => {
                println!("Couldn't obtain current directory: {}", why.description());
                process::exit(0)
            }
        };
        match Url::parse(&file_url) {
            Ok(url) => url.open(),
            Err(why) => println!("Couldn't open file: {}", why.description()),
        }
    }

    pub fn report_last_session(&self) {
        self.write_to_html(None);
        self.open_local_html("session.html".to_string());
    }

    pub fn report_sheet(&self, ago: Option<u64>) {
        self.write_to_html(ago);
        self.open_local_html("timesheet.html".to_string());
        /* Leave complete sheet html */
        self.write_to_html(None);
    }

    pub fn show_commits(&mut self, on_off: bool) {
        self.config.show_commits = on_off;
    }

    pub fn set_repo_url(&mut self, repo: String) {
        let repo =
            if repo == "" { None } else { Some(repo) };
        self.config.repository = repo;
    }

    pub fn pause_time(&self) -> u64 {
        self.sessions.iter().fold(
            0, |total, session| total + session.pause_time())
    }

    pub fn work_time(&self) -> u64 {
        self.sessions.iter().fold(
            0, |total, session| total + session.work_time())
    }

    fn to_html(&self, ago: Option<u64>) -> String {
        let timestamp = ago.unwrap_or(self.start);
        let mut sessions_html = String::new();
        for session in &self.sessions {
            if session.start > timestamp {
                sessions_html.push_str(&format!("{}
", session.to_html()));
            }
        }

        let stylesheets = if self.config.show_commits {
            "<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n".to_string()
        } else {
            r#"<link rel="stylesheet" type="text/css" href="style.css">
<link rel="stylesheet" type="text/css" href="no_commit.css">
"#.to_string()
        };

        let mut html = format!(r#"<!DOCTYPE html>

        {}
        <title>{} for {}</title>

    {}"#,
              stylesheets,
              "Timesheet",
              "Rafael Bachmann",
              sessions_html);

        write!(&mut html,
               r#"

Worked for {}

Paused for {}

"#,
               sec_to_hms_string(self.work_time()),
               sec_to_hms_string(self.pause_time()))
               .unwrap();
        write!(&mut html, "\n").unwrap();
        html
    }
}
<commit_msg>adjust load_from_file so that trk can even be run from within the .trk dir<commit_after>use std::io::prelude::*;
use std::{process, env};
use std::path::Path;
use std::error::Error;
use std::fs::{self, OpenOptions};
/* Alias to avoid naming conflict for write_all!() */
use std::fmt::Write as std_write;

use url::Url;
use url_open::UrlOpen;

use serde_json::{from_str, to_string};

use util::*;
use config::Config;
use timesheet::traits::HasHTML;

use timesheet::session::Session;
use timesheet::session::EventType;

#[derive(Serialize, Deserialize, Debug)]
pub struct Timesheet {
    start            : u64,
    end              : u64,
    config           : Config,
    sessions         : Vec<Session>,
}

impl Timesheet {
    /** Initializes the .trk/timesheet.json file which holds
     * the serialized timesheet
     * Returns Some(newTimesheet) if operation succeeded */
    pub fn init(author_name: Option<&str>) -> Option<Timesheet> {
        /* Check if file already exists (no init permitted) */
        if Timesheet::is_init() {
            println!("Timesheet is already initialized!");
            return None;
        }
        /* File does not exist, initialize */
        let git_author_name = git_author();
        let author_name = match author_name {
            Some(name) => name,
            None => {
                match git_author_name {
                    Some(ref git_name) => git_name,
                    None => {
                        println!("Empty name not permitted. \
                                  Please run with 'trk init <name>'");
                        process::exit(0);
                    }
                }
            }
        };
        let mut config = Config::new();
        config.user_name = Some(author_name.to_string());
        let now = get_seconds();
        let sheet = Timesheet {
            start        : now,
            end          : now + 1,
            config       : config,
            sessions     : Vec::<Session>::new(),
        };
        let sheet = if sheet.write_files() {
            git_init_trk();
            Some(sheet)
        } else {
            None
        };
        sheet
    }

    fn is_init() -> bool {
        Path::new("./.trk/timesheet.json").exists() && Timesheet::load_from_file().is_some()
    }

    pub fn new_session(&mut self, timestamp: Option<u64>) -> bool {
        let possible = self.sessions
            .last_mut()
            .map_or(true, |session| {
                if session.is_running() {
                    println!("Last session is still running.");
                }
                !session.is_running()
        });
        if possible {
            match timestamp {
                Some(timestamp) => {
                    let is_valid_ts = match self.sessions.last() {
                        None => timestamp > self.start,
                        Some(last_session) => timestamp > last_session.end,
                    };
                    if is_valid_ts {
                        self.sessions.push(Session::new(Some(timestamp)));
                    } else {
                        println!("That timestamp is invalid.");
                        process::exit(0);
                    }
                }
                None => {
                    self.sessions.push(Session::new(None));
                }
            };
        }
        possible
    }

    pub fn end_session(&mut self, timestamp: Option<u64>) {
        match self.sessions.last_mut() {
            Some(session) => {
                session.update_end();
                session.finalize(timestamp);
                self.end = session.end + 1;
            }
            None => println!("No session to finalize."),
        }
    }

    pub fn pause(&mut self, timestamp: Option<u64>, note: Option<String>) {
        match self.sessions.last_mut() {
            Some(session) => {
                session.push_event(timestamp, note, EventType::Pause);
            }
            None => println!("No session to pause."),
        }
    }

    pub fn resume(&mut self, timestamp: Option<u64>) {
        match self.sessions.last_mut() {
            Some(session) => {
                session.push_event(timestamp, None, EventType::Resume);
            }
            None => println!("No session to pause."),
        }
    }

    pub fn note(&mut self, timestamp: Option<u64>, note_text: String) {
        match self.sessions.last_mut() {
            Some(session) => {
                session.push_event(timestamp, Some(note_text), EventType::Note);
            }
            None => println!("No session to add note to."),
        }
    }

    pub fn add_commit(&mut self, hash: String) {
        let new_needed = self.sessions
            .last()
            .map_or(true, |session| !session.is_running());
        if new_needed {
            self.new_session(None);
        }
        match self.sessions.last_mut() {
            Some(session) => {
                let message = git_commit_message(&hash).unwrap_or(String::new());
                session.push_event(None, Some(message), EventType::Commit { hash });
            }
            None => println!("No session to add commit to."),
        }
    }

    pub fn add_branch(&mut self, name: String) {
        self.sessions
            .last_mut()
            .map(|session| session.add_branch(name));
    }

    fn write_to_html(&self, ago: Option<u64>) -> bool {
        // TODO: avoid time-of-check-to-time-of-use race risk
        let path = Path::new("./timesheet.html");
        let file = OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(&path);

        match file {
            Ok(mut file) => {
                file.write_all(self.to_html(ago).as_bytes()).unwrap();
                format_file("timesheet.html");
                /* Save was successful */
                true
            }
            Err(why) => {
                println!("Could not report sheet! {}", why.description());
                false
            }
        }
    }

    fn write_last_session_html(&self) -> bool {
        let session = match self.sessions.last() {
            Some(session) => session,
            None => return true,
        };
        let path = Path::new("./session.html");
        let file = OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(&path);

        let mut file = match file {
            Ok(file) => file,
            Err(why) => {
                println!("Could not write report to session.html! {}",
                         why.description());
                return false;
            }
        };

        let stylesheets = if self.config.show_commits {
            r#"<link rel="stylesheet" type="text/css" href="style.css">
"#      } else {
            r#"<link rel="stylesheet" type="text/css" href="style.css">
<link rel="stylesheet" type="text/css" href="no_commit.css">
"#
        };

        let html = format!(r#"<!DOCTYPE html>

  {}
  <title>{} for {}</title>

{}

"#,
               stylesheets,
               "Session",
               "Rafael Bachmann",
               session.to_html());
    file.write_all(html.as_bytes()).unwrap();
    format_file("session.html");
    /* Save was successful */
    true
    }

    fn write_to_json(&self) -> bool {
        if !Path::new("./.trk").exists() {
            match fs::create_dir("./.trk") {
                Ok(_) => {}
                _ => {
                    println!("Could not create .trk directory.");
                    process::exit(0);
                }
            }
        }

        let path = Path::new("./.trk/timesheet.json");
        let file = OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(&path);

        match file {
            Ok(mut file) => {
                /* Convert the sheet to a JSON string. */
                let serialized =
                    to_string(&self).expect("Could not write serialized time sheet.");
                file.write_all(serialized.as_bytes()).unwrap();
                /* Save was successful */
                true
            }
            Err(why) => {
                println!("Could not open timesheet.json file: {}",
                         why.description());
                false
            }
        }
    }

    pub fn write_files(&self) -> bool {
        /* TODO: avoid time-of-check-to-time-of-use race risk */
        self.write_to_json() && self.write_to_html(None) && self.write_last_session_html()
    }

    /** Return a Some(Timesheet) struct if a timesheet.json file
     * is present and valid in the .trk directory, and None otherwise.
     * */
pub fn load_from_file() -> Option<Timesheet> {
    let mut path = env::current_dir().unwrap();
    loop {
        path.push(".trk");
        if path.exists() {
            env::set_current_dir(&path).is_ok();
            break;
        } else {
            path.pop();
            if !path.pop() {
                return None;
            }
        }
    }

    path.push("timesheet.json");
    let file = OpenOptions::new().read(true).open(&path);
    path.pop();
    env::set_current_dir(path).unwrap();
    match file {
        Ok(mut file) => {
            let mut serialized = String::new();
            match file.read_to_string(&mut serialized) {
                Ok(..) => from_str(&serialized).unwrap_or(None),
                Err(..) => {
                    println!("IO error while reading the timesheet file.");
                    process::exit(0);
                }
            }
        }
        Err(..) => None,
    }
}

    pub fn clear() {
        /* Try to get user name */
        let sheet = Timesheet::load_from_file();
        /* In case there is a sheet, there must also be a name */
        let name: Option<String> = sheet.map(|s| s.config.user_name.unwrap());

        let path = Path::new("./.trk/timesheet.json");
        if path.exists() {
            fs::remove_file(&path).unwrap_or_else(|why| {
                println!("Could not remove sessions file: {}", why.description());
            });
        }
        Timesheet::init(name.as_ref().map(|s| s.as_str()));
    }

    pub fn timesheet_status(&self) -> String {
        let mut status = format!("Sheet running for {}\n",
                sec_to_hms_string(get_seconds() - self.start));
        match self.sessions.len() {
            0 => write!(&mut status, "No sessions yet.\n").unwrap(),
            n => {
                write!(&mut status,
                       "{} session(s) so far.\nLast session:\n{}",
                       n,
                       self.sessions[n - 1].status())
                       .unwrap()
            }
        };
        status
    }

    pub fn last_session_status(&self) -> String {
        let status = self.sessions.last().map(|session| session.status());
        status.unwrap_or("No session yet.".to_string())
    }

    fn open_local_html(&self, filename: String) {
        let file_url = match env::current_dir() {
            Ok(dir) => {
                match dir.join(&filename).to_str() {
                    Some(path) => format!("file://{}", path),
                    None => {
                        println!("Invalid filename: {}.", filename);
                        process::exit(0)
                    }
                }
            }
            Err(why) => {
                println!("Couldn't obtain current directory: {}", why.description());
                process::exit(0)
            }
        };
        match Url::parse(&file_url) {
            Ok(url) => url.open(),
            Err(why) => println!("Couldn't open file: {}", why.description()),
        }
    }

    pub fn report_last_session(&self) {
        self.write_to_html(None);
        self.open_local_html("session.html".to_string());
    }

    pub fn report_sheet(&self, ago: Option<u64>) {
        self.write_to_html(ago);
        self.open_local_html("timesheet.html".to_string());
        /* Leave complete sheet html */
        self.write_to_html(None);
    }

    pub fn show_commits(&mut self, on_off: bool) {
        self.config.show_commits = on_off;
    }

    pub fn set_repo_url(&mut self, repo: String) {
        let repo =
            if repo == "" { None } else { Some(repo) };
        self.config.repository = repo;
    }

    pub fn pause_time(&self) -> u64 {
        self.sessions.iter().fold(
            0, |total, session| total + session.pause_time())
    }

    pub fn work_time(&self) -> u64 {
        self.sessions.iter().fold(
            0, |total, session| total + session.work_time())
    }

    fn to_html(&self, ago: Option<u64>) -> String {
        let timestamp = ago.unwrap_or(self.start);
        let mut sessions_html = String::new();
        for session in &self.sessions {
            if session.start > timestamp {
                sessions_html.push_str(&format!("{}
", session.to_html()));
            }
        }

        let stylesheets = if self.config.show_commits {
            "<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n".to_string()
        } else {
            r#"<link rel="stylesheet" type="text/css" href="style.css">
<link rel="stylesheet" type="text/css" href="no_commit.css">
"#.to_string()
        };

        let mut html = format!(r#"<!DOCTYPE html>

        {}
        <title>{} for {}</title>

    {}"#,
              stylesheets,
              "Timesheet",
              "Rafael Bachmann",
              sessions_html);

        write!(&mut html,
               r#"

Worked for {}

Paused for {}

"#,
               sec_to_hms_string(self.work_time()),
               sec_to_hms_string(self.pause_time()))
               .unwrap();
        write!(&mut html, "\n").unwrap();
        html
    }
}
<|endoftext|>


<commit_before>use super::context::*;
use super::module::*;
use super::signal::*;

use std::cell::RefCell;
use std::collections::BTreeMap;
use std::ptr;

#[must_use]
pub struct Instance<'a> {
    pub(super) context: &'a Context<'a>,
    pub(super) module: &'a Module<'a>,

    pub(crate) instantiated_module: &'a Module<'a>,
    pub(crate) name: String,
    pub(crate) driven_inputs: RefCell<BTreeMap<String, &'a Signal<'a>>>,
}

impl<'a> Instance<'a> {
    /// Drives the input of this `Module` `Instance` specified by `name` with the given `Signal`.
    ///
    /// # Panics
    ///
    /// Panics if `i` is from a different module than `self`, if `name` specifies an input that doesn't exist on this `Instance`'s `Module`, if this input is already driven on this `Instance`, or if `i`'s bit width differs from that of the input.
    ///
    /// # Examples
    ///
    /// ```
    /// use kaze::*;
    ///
    /// let c = Context::new();
    ///
    /// let inner = c.module("inner");
    /// inner.output("o", inner.input("i", 32));
    ///
    /// let outer = c.module("outer");
    /// let inner_inst = outer.instance("inner", "inner_inst");
    /// // Drive inner_inst's "i" input with a 32-bit literal
    /// inner_inst.drive_input("i", outer.lit(0xfadebabeu32, 32));
    /// ```
    pub fn drive_input<S: Into<String>>(&'a self, name: S, i: &'a Signal<'a>) {
        let name = name.into();
        let mut driven_inputs = self.driven_inputs.borrow_mut();
        if !ptr::eq(self.module, i.module) {
            panic!("Attempted to drive an instance input with a signal from a different module.");
        }
        if !self.instantiated_module.inputs.borrow().contains_key(&name) {
            panic!("Attempted to drive an input called \"{}\" on an instance of \"{}\", but no such input with this name exists on this module.", name, self.instantiated_module.name);
        }
        if driven_inputs.contains_key(&name) {
            panic!("Attempted to drive an input called \"{}\" on an instance of \"{}\", but this input is already driven for this instance.", name, self.instantiated_module.name);
        }
        let input_bit_width = self.instantiated_module.inputs.borrow()[&name].bit_width();
        if input_bit_width != i.bit_width() {
            panic!("Attempted to drive an input called \"{}\" on an instance of \"{}\", but this input and the provided signal have different bit widths ({} and {}, respectively).", name, self.instantiated_module.name, input_bit_width, i.bit_width());
        }
        driven_inputs.insert(name, i);
    }

    pub fn output<S: Into<String>>(&'a self, name: S) -> &Signal<'a> {
        // TODO: Error if there's no output called `name` on this module
        self.context.signal_arena.alloc(Signal {
            context: self.context,
            module: self.module,

            data: SignalData::InstanceOutput {
                instance: self,
                name: name.into(),
            },
        })
    }
}

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

    #[test]
    #[should_panic(
        expected = "Attempted to drive an instance input with a signal from a different module."
    )]
    fn drive_input_different_module_error() {
        let c = Context::new();

        let inner = c.module("inner");
        let _ = inner.input("a", 1);

        let m1 = c.module("a");
        let i1 = m1.input("a", 1);

        let m2 = c.module("b");
        let inner_inst = m2.instance("inner", "inner_inst");

        // Panic
        inner_inst.drive_input("a", i1);
    }

    #[test]
    #[should_panic(
        expected = "Attempted to drive an input called \"a\" on an instance of \"inner\", but no such input with this name exists on this module."
    )]
    fn drive_input_nonexistent_input_error() {
        let c = Context::new();

        let _ = c.module("inner");

        let m = c.module("a");
        let inner_inst = m.instance("inner", "inner_inst");

        // Panic
        inner_inst.drive_input("a", m.input("i", 1));
    }

    #[test]
    #[should_panic(
        expected = "Attempted to drive an input called \"a\" on an instance of \"inner\", but this input is already driven for this instance."
    )]
    fn drive_input_already_driven_error() {
        let c = Context::new();

        let inner = c.module("inner");
        let _ = inner.input("a", 1);

        let m = c.module("a");
        let inner_inst = m.instance("inner", "inner_inst");

        inner_inst.drive_input("a", m.input("i1", 1));

        // Panic
        inner_inst.drive_input("a", m.input("i2", 1));
    }

    #[test]
    #[should_panic(
        expected = "Attempted to drive an input called \"a\" on an instance of \"inner\", but this input and the provided signal have different bit widths (1 and 32, respectively)."
    )]
    fn drive_input_incompatible_bit_widths_error() {
        let c = Context::new();

        let inner = c.module("inner");
        let _ = inner.input("a", 1);

        let m = c.module("a");
        let inner_inst = m.instance("inner", "inner_inst");

        // Panic
        inner_inst.drive_input("a", m.input("i1", 32));
    }
}
<commit_msg>Document Instance type<commit_after>use super::context::*;
use super::module::*;
use super::signal::*;

use std::cell::RefCell;
use std::collections::BTreeMap;
use std::ptr;

/// Represents an instance of a [`Module`], created by the [`Module`]::[`instance`] method.
///
/// # Examples
///
/// ```
/// use kaze::*;
///
/// let c = Context::new();
///
/// // Inner module (simple pass-through)
/// let inner = c.module("inner");
/// inner.output("o", inner.input("i", 32));
///
/// // Outer module (wraps a single `inner` instance)
/// let outer = c.module("outer");
/// let inner_inst = outer.instance("inner", "inner_inst");
/// inner_inst.drive_input("i", outer.input("i", 32));
/// outer.output("o", inner_inst.output("o"));
/// ```
///
/// [`Module`]: ./struct.Module.html
/// [`instance`]: ./struct.Module.html#method.instance
#[must_use]
pub struct Instance<'a> {
    pub(super) context: &'a Context<'a>,
    pub(super) module: &'a Module<'a>,

    pub(crate) instantiated_module: &'a Module<'a>,
    pub(crate) name: String,
    pub(crate) driven_inputs: RefCell<BTreeMap<String, &'a Signal<'a>>>,
}

impl<'a> Instance<'a> {
    /// Drives the input of this `Module` `Instance` specified by `name` with the given `Signal`.
    ///
    /// # Panics
    ///
    /// Panics if `i` is from a different module than `self`, if `name` specifies an input that doesn't exist on this `Instance`'s `Module`, if this input is already driven on this `Instance`, or if `i`'s bit width differs from that of the input.
    ///
    /// # Examples
    ///
    /// ```
    /// use kaze::*;
    ///
    /// let c = Context::new();
    ///
    /// let inner = c.module("inner");
    /// inner.output("o", inner.input("i", 32));
    ///
    /// let outer = c.module("outer");
    /// let inner_inst = outer.instance("inner", "inner_inst");
    /// // Drive inner_inst's "i" input with a 32-bit literal
    /// inner_inst.drive_input("i", outer.lit(0xfadebabeu32, 32));
    /// ```
    pub fn drive_input<S: Into<String>>(&'a self, name: S, i: &'a Signal<'a>) {
        let name = name.into();
        let mut driven_inputs = self.driven_inputs.borrow_mut();
        if !ptr::eq(self.module, i.module) {
            panic!("Attempted to drive an instance input with a signal from a different module.");
        }
        if !self.instantiated_module.inputs.borrow().contains_key(&name) {
            panic!("Attempted to drive an input called \"{}\" on an instance of \"{}\", but no such input with this name exists on this module.", name, self.instantiated_module.name);
        }
        if driven_inputs.contains_key(&name) {
            panic!("Attempted to drive an input called \"{}\" on an instance of \"{}\", but this input is already driven for this instance.", name, self.instantiated_module.name);
        }
        let input_bit_width = self.instantiated_module.inputs.borrow()[&name].bit_width();
        if input_bit_width != i.bit_width() {
            panic!("Attempted to drive an input called \"{}\" on an instance of \"{}\", but this input and the provided signal have different bit widths ({} and {}, respectively).", name, self.instantiated_module.name, input_bit_width, i.bit_width());
        }
        driven_inputs.insert(name, i);
    }

    pub fn output<S: Into<String>>(&'a self, name: S) -> &Signal<'a> {
        // TODO: Error if there's no output called `name` on this module
        self.context.signal_arena.alloc(Signal {
            context: self.context,
            module: self.module,

            data: SignalData::InstanceOutput {
                instance: self,
                name: name.into(),
            },
        })
    }
}

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

    #[test]
    #[should_panic(
        expected = "Attempted to drive an instance input with a signal from a different module."
    )]
    fn drive_input_different_module_error() {
        let c = Context::new();

        let inner = c.module("inner");
        let _ = inner.input("a", 1);

        let m1 = c.module("a");
        let i1 = m1.input("a", 1);

        let m2 = c.module("b");
        let inner_inst = m2.instance("inner", "inner_inst");

        // Panic
        inner_inst.drive_input("a", i1);
    }

    #[test]
    #[should_panic(
        expected = "Attempted to drive an input called \"a\" on an instance of \"inner\", but no such input with this name exists on this module."
    )]
    fn drive_input_nonexistent_input_error() {
        let c = Context::new();

        let _ = c.module("inner");

        let m = c.module("a");
        let inner_inst = m.instance("inner", "inner_inst");

        // Panic
        inner_inst.drive_input("a", m.input("i", 1));
    }

    #[test]
    #[should_panic(
        expected = "Attempted to drive an input called \"a\" on an instance of \"inner\", but this input is already driven for this instance."
    )]
    fn drive_input_already_driven_error() {
        let c = Context::new();

        let inner = c.module("inner");
        let _ = inner.input("a", 1);

        let m = c.module("a");
        let inner_inst = m.instance("inner", "inner_inst");

        inner_inst.drive_input("a", m.input("i1", 1));

        // Panic
        inner_inst.drive_input("a", m.input("i2", 1));
    }

    #[test]
    #[should_panic(
        expected = "Attempted to drive an input called \"a\" on an instance of \"inner\", but this input and the provided signal have different bit widths (1 and 32, respectively)."
    )]
    fn drive_input_incompatible_bit_widths_error() {
        let c = Context::new();

        let inner = c.module("inner");
        let _ = inner.input("a", 1);

        let m = c.module("a");
        let inner_inst = m.instance("inner", "inner_inst");

        // Panic
        inner_inst.drive_input("a", m.input("i1", 32));
    }
}
<|endoftext|>