<commit_before>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

/// The standard logging macro.
///
/// This macro will generically log with the specified `Level` and `format!`
/// based argument list.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// use log::Level;
///
/// # fn main() {
/// let data = (42, "Forty-two");
/// let private_data = "private";
///
/// log!(Level::Error, "Received errors: {}, {}", data.0, data.1);
/// log!(target: "app_events", Level::Warn, "App warning: {}, {}, {}",
///     data.0, data.1, private_data);
/// # }
/// ```
#[macro_export]
macro_rules! log {
    (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
        let lvl = $lvl;
        if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() {
            $crate::__private_api_log(
                format_args!($($arg)+),
                lvl,
                &($target, module_path!(), file!(), line!()),
            );
        }
    });
    ($lvl:expr, $($arg:tt)+) => (log!(target: module_path!(), $lvl, $($arg)+))
}

/// Logs a message at the error level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// let (err_info, port) = ("No connection", 22);
///
/// error!("Error: {} on port {}", err_info, port);
/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22);
/// # }
/// ```
#[macro_export]
macro_rules! error {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Error, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Error, $($arg)*);
    )
}

/// Logs a message at the warn level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// let warn_description = "Invalid Input";
///
/// warn!("Warning! {}!", warn_description);
/// warn!(target: "input_events", "App received warning: {}", warn_description);
/// # }
/// ```
#[macro_export]
macro_rules! warn {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Warn, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Warn, $($arg)*);
    )
}

/// Logs a message at the info level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Connection { port: u32, speed: f32 }
/// let conn_info = Connection { port: 40, speed: 3.20 };
///
/// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed);
/// info!(target: "connection_events", "Successfull connection, port: {}, speed: {}",
///       conn_info.port, conn_info.speed);
/// # }
/// ```
#[macro_export]
macro_rules! info {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Info, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Info, $($arg)*);
    )
}

/// Logs a message at the debug level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// debug!("New position: x: {}, y: {}", pos.x, pos.y);
/// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y);
/// # }
/// ```
#[macro_export]
macro_rules! debug {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Debug, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Debug, $($arg)*);
    )
}

/// Logs a message at the trace level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// trace!("Position is: x: {}, y: {}", pos.x, pos.y);
/// trace!(target: "app_events", "x is {} and y is {}",
///        if pos.x >= 0.0 { "positive" } else { "negative" },
///        if pos.y >= 0.0 { "positive" } else { "negative" });
/// # }
/// ```
#[macro_export]
macro_rules! trace {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Trace, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Trace, $($arg)*);
    )
}

/// Determines if a message logged at the specified level in that module will
/// be logged.
///
/// This can be used to avoid expensive computation of log message arguments if
/// the message would be ignored anyway.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// use log::Level::Debug;
///
/// # fn foo() {
/// if log_enabled!(Debug) {
///     let data = expensive_call();
///     debug!("expensive debug data: {} {}", data.x, data.y);
/// }
/// if log_enabled!(target: "Global", Debug) {
///    let data = expensive_call();
///    debug!(target: "Global", "expensive debug data: {} {}", data.x, data.y);
/// }
/// # }
/// # struct Data { x: u32, y: u32 }
/// # fn expensive_call() -> Data { Data { x: 0, y: 0 } }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! log_enabled {
    (target: $target:expr, $lvl:expr) => {{
        let lvl = $lvl;
        lvl <= $crate::STATIC_MAX_LEVEL
            && lvl <= $crate::max_level()
            && $crate::__private_api_enabled(lvl, $target)
    }};
    ($lvl:expr) => {
        log_enabled!(target: module_path!(), $lvl)
    };
}
<commit_msg>Use local_inner_macros to resolve all local macros within $crate<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

/// The standard logging macro.
///
/// This macro will generically log with the specified `Level` and `format!`
/// based argument list.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// use log::Level;
///
/// # fn main() {
/// let data = (42, "Forty-two");
/// let private_data = "private";
///
/// log!(Level::Error, "Received errors: {}, {}", data.0, data.1);
/// log!(target: "app_events", Level::Warn, "App warning: {}, {}, {}",
///     data.0, data.1, private_data);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! log {
    (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
        let lvl = $lvl;
        if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() {
            $crate::__private_api_log(
                log_format_args!($($arg)+),
                lvl,
                &($target, log_module_path!(), log_file!(), log_line!()),
            );
        }
    });
    ($lvl:expr, $($arg:tt)+) => (log!(target: log_module_path!(), $lvl, $($arg)+))
}

/// Logs a message at the error level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// let (err_info, port) = ("No connection", 22);
///
/// error!("Error: {} on port {}", err_info, port);
/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! error {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Error, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Error, $($arg)*);
    )
}

/// Logs a message at the warn level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// let warn_description = "Invalid Input";
///
/// warn!("Warning! {}!", warn_description);
/// warn!(target: "input_events", "App received warning: {}", warn_description);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! warn {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Warn, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Warn, $($arg)*);
    )
}

/// Logs a message at the info level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Connection { port: u32, speed: f32 }
/// let conn_info = Connection { port: 40, speed: 3.20 };
///
/// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed);
/// info!(target: "connection_events", "Successfull connection, port: {}, speed: {}",
///       conn_info.port, conn_info.speed);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! info {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Info, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Info, $($arg)*);
    )
}

/// Logs a message at the debug level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// debug!("New position: x: {}, y: {}", pos.x, pos.y);
/// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! debug {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Debug, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Debug, $($arg)*);
    )
}

/// Logs a message at the trace level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// trace!("Position is: x: {}, y: {}", pos.x, pos.y);
/// trace!(target: "app_events", "x is {} and y is {}",
///        if pos.x >= 0.0 { "positive" } else { "negative" },
///        if pos.y >= 0.0 { "positive" } else { "negative" });
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! trace {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Trace, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Trace, $($arg)*);
    )
}

/// Determines if a message logged at the specified level in that module will
/// be logged.
///
/// This can be used to avoid expensive computation of log message arguments if
/// the message would be ignored anyway.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// use log::Level::Debug;
///
/// # fn foo() {
/// if log_enabled!(Debug) {
///     let data = expensive_call();
///     debug!("expensive debug data: {} {}", data.x, data.y);
/// }
/// if log_enabled!(target: "Global", Debug) {
///    let data = expensive_call();
///    debug!(target: "Global", "expensive debug data: {} {}", data.x, data.y);
/// }
/// # }
/// # struct Data { x: u32, y: u32 }
/// # fn expensive_call() -> Data { Data { x: 0, y: 0 } }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! log_enabled {
    (target: $target:expr, $lvl:expr) => {{
        let lvl = $lvl;
        lvl <= $crate::STATIC_MAX_LEVEL
            && lvl <= $crate::max_level()
            && $crate::__private_api_enabled(lvl, $target)
    }};
    ($lvl:expr) => {
        log_enabled!(target: log_module_path!(), $lvl)
    };
}

// The log macro above cannot invoke format_args directly because it uses
// local_inner_macros. A format_args invocation there would resolve to
// $crate::format_args which does not exist. Instead invoke format_args here
// outside of local_inner_macros so that it resolves (probably) to
// core::format_args or std::format_args. Same for the several macros that
// follow.
//
// This is a workaround until we drop support for pre-1.30 compilers. At that
// point we can remove use of local_inner_macros, use $crate:: when invoking
// local macros, and invoke format_args directly.
#[doc(hidden)]
#[macro_export]
macro_rules! log_format_args {
    ($($args:tt)*) => {
        format_args!($($args)*)
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! log_module_path {
    () => {
        module_path!()
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! log_file {
    () => {
        file!()
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! log_line {
    () => {
        line!()
    };
}
<|endoftext|>


<commit_before>// Adapton uses memoization under the covers, which needs an efficient
// mechanism to search for function pointers and compare them for
// equality.
//
// Meanwhile, Rust does not provide Eq and Hash implementations for
// trait Fn.  So, to identify Rust functions as values that we can
// hash and compare, we need to bundle additional static information
// along with the function pointer as use this data as a proxy for the
// function itself.  The idea is that this information uniquely
// identifies the function pointer (i.e., two distinct functions will
// always have two distinct identities).
//
use std::hash::{Hash,Hasher,SipHasher};
use std::fmt::{Formatter,Result,Debug};
//use std::mem::replace;

#[derive(PartialEq,Eq,Clone,Hash)]
pub struct ProgPt {
    // Symbolic identity, in Rust semantics:
    pub symbol:&'static str, // via stringify!(...)
    // module:Rc<String>, // via module!()

    // Location in local filesystem:
    //pub file:&'static str,   // via file!()
    //pub line:u32,        // via line!()
    //pub column:u32,      // via column!()
}

impl Debug for ProgPt {
    fn fmt(&self, f: &mut Formatter) -> Result { self.symbol.fmt(f) }
}

pub fn my_hash<T>(obj: T) -> u64
    where T: Hash
{
    let mut hasher = SipHasher::new();
    obj.hash(&mut hasher);
    hasher.finish()
}

pub fn my_hash_n<T>(obj: T, n:usize) -> u64
    where T: Hash
{
  let mut hasher = SipHasher::new();
  for i in 0..n {
    obj.hash(&mut hasher);
  }
  hasher.finish()
}

#[macro_export]
macro_rules! prog_pt {
    ($symbol:expr) => {{
        ProgPt{
            symbol:$symbol,
            //file:file!(),
            //line:line!(),
            //column:column!(),
        }
    }}
}

#[macro_export]
macro_rules! thunk {
    ( $st:expr , $nm:expr =>> $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, ()),
             ()
             )
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:ident , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             )
    }}
    ;
    ( $st:expr , $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             )
    }}
    ;
    ( $st:expr , $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             )
    }}
    ;
}

#[macro_export]
macro_rules! memo {
    ( $st:expr , $nm:expr =>> $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:path , $( $lab1:ident : $arg1:expr ),* ;; $( $lab2:ident : $arg2:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args1, args2|{
                     let ($( $lab1 ),*, _) = args1 ;
                     let ($( $lab2 ),*, _) = args2 ;
                     $f ( st, $( $lab1 ),* , $( $lab2 ),* )
                 })),
             ( $( $arg1 ),*, () ),
             ( $( $arg2 ),*, () ),
             );
        ($st).force(&t)
    }}
    ;
}

#[macro_export]
macro_rules! eager {
    ( $st:expr , $nm:expr =>> $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, ),
             ()
             );
        let res = ($st).force(&t) ;
        (t, res)
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             );
        let res = ($st).force(&t) ;
        (t, res)
    }}
    ;
    ( $st:expr , $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             );
        let res = ($st).force(&t) ;
        (t, res)
    }}
    ;
    ( $st:expr , $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             );
        let res = ($st).force(&t) ;
        (t, res)
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:path , $( $lab1:ident : $arg1:expr ),* ;; $( $lab2:ident : $arg2:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args1, args2|{
                     let ($( $lab1 ),*, _) = args1 ;
                     let ($( $lab2 ),*, _) = args2 ;
                     $f ( st, $( $lab1 ),* , $( $lab2 ),* )
                 })),
             ( $( $arg1 ),*, () ),
             ( $( $arg2 ),*, () ),
             );
        let res = ($st).force(&t) ;
        (t, res)
    }}
    ;
}

#[macro_export]
macro_rules! cell_call {
    ( $st:expr , $nm:expr =>> $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
      let res = {
        $f :: < $( $ty ),* >( $st, $( $arg ),*, )
      } ;
      let cell = ($st).cell($st, $nm, res) ;
      (cell, res)
    }}
}

// https://doc.rust-lang.org/book/macros.html
//
// macro_rules! o_O {
//     (
//         $(
//             $x:expr; [ $( $y:expr ),* ]
//          );*
//     ) => {
//         &[ $($( $x + $y ),*),* ]
//     }
// }
//
// fn main() {
//     let a: &[i32]
//         = o_O!(10; [1, 2, 3];
//                20; [4, 5, 6]);
//
//     assert_eq!(a, [11, 12, 13, 24, 25, 26]);
// }

// TODO: Need to gensym a variable for each argument below:
//
// macro_rules! thunk {
//     ( $f:ident , $st:expr , $( $arg:expr ),* ) => {
//         let fval = Rc::new(Box::new(
//             |st, args|{
//                 let ($( $arg ),*) = args ;
//                 f( st, $( $arg ),* )
//             })) ;
//         ($st).thunk (ArtId::Eager, prog_pt!($f), fval, $( $arg ),* )
//     }}
<commit_msg>fixed cell_call macro<commit_after>// Adapton uses memoization under the covers, which needs an efficient
// mechanism to search for function pointers and compare them for
// equality.
//
// Meanwhile, Rust does not provide Eq and Hash implementations for
// trait Fn.  So, to identify Rust functions as values that we can
// hash and compare, we need to bundle additional static information
// along with the function pointer as use this data as a proxy for the
// function itself.  The idea is that this information uniquely
// identifies the function pointer (i.e., two distinct functions will
// always have two distinct identities).
//
use std::hash::{Hash,Hasher,SipHasher};
use std::fmt::{Formatter,Result,Debug};
//use std::mem::replace;

#[derive(PartialEq,Eq,Clone,Hash)]
pub struct ProgPt {
    // Symbolic identity, in Rust semantics:
    pub symbol:&'static str, // via stringify!(...)
    // module:Rc<String>, // via module!()

    // Location in local filesystem:
    //pub file:&'static str,   // via file!()
    //pub line:u32,        // via line!()
    //pub column:u32,      // via column!()
}

impl Debug for ProgPt {
    fn fmt(&self, f: &mut Formatter) -> Result { self.symbol.fmt(f) }
}

pub fn my_hash<T>(obj: T) -> u64
    where T: Hash
{
    let mut hasher = SipHasher::new();
    obj.hash(&mut hasher);
    hasher.finish()
}

pub fn my_hash_n<T>(obj: T, n:usize) -> u64
    where T: Hash
{
  let mut hasher = SipHasher::new();
  for i in 0..n {
    obj.hash(&mut hasher);
  }
  hasher.finish()
}

#[macro_export]
macro_rules! prog_pt {
    ($symbol:expr) => {{
        ProgPt{
            symbol:$symbol,
            //file:file!(),
            //line:line!(),
            //column:column!(),
        }
    }}
}

#[macro_export]
macro_rules! thunk {
    ( $st:expr , $nm:expr =>> $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, ()),
             ()
             )
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:ident , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             )
    }}
    ;
    ( $st:expr , $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             )
    }}
    ;
    ( $st:expr , $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             )
    }}
    ;
}

#[macro_export]
macro_rules! memo {
    ( $st:expr , $nm:expr =>> $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:path , $( $lab1:ident : $arg1:expr ),* ;; $( $lab2:ident : $arg2:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args1, args2|{
                     let ($( $lab1 ),*, _) = args1 ;
                     let ($( $lab2 ),*, _) = args2 ;
                     $f ( st, $( $lab1 ),* , $( $lab2 ),* )
                 })),
             ( $( $arg1 ),*, () ),
             ( $( $arg2 ),*, () ),
             );
        ($st).force(&t)
    }}
    ;
}

#[macro_export]
macro_rules! eager {
    ( $st:expr , $nm:expr =>> $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, ),
             ()
             );
        let res = ($st).force(&t) ;
        (t, res)
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             );
        let res = ($st).force(&t) ;
        (t, res)
    }}
    ;
    ( $st:expr , $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             );
        let res = ($st).force(&t) ;
        (t, res)
    }}
    ;
    ( $st:expr , $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             );
        let res = ($st).force(&t) ;
        (t, res)
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:path , $( $lab1:ident : $arg1:expr ),* ;; $( $lab2:ident : $arg2:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(stringify!($f)),
             Rc::new(Box::new(
                 |st, args1, args2|{
                     let ($( $lab1 ),*, _) = args1 ;
                     let ($( $lab2 ),*, _) = args2 ;
                     $f ( st, $( $lab1 ),* , $( $lab2 ),* )
                 })),
             ( $( $arg1 ),*, () ),
             ( $( $arg2 ),*, () ),
             );
        let res = ($st).force(&t) ;
        (t, res)
    }}
    ;
}

#[macro_export]
macro_rules! cell_call {
    ( $st:expr , $nm:expr =>> $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
      let res = {
        $f :: < $( $ty ),* >( $st, $( $arg ),*, )
      } ;
      let cell = ($st).cell($nm, res) ;
      let cell = ($st).read_only(cell);
      cell
    }}
}

// https://doc.rust-lang.org/book/macros.html
//
// macro_rules! o_O {
//     (
//         $(
//             $x:expr; [ $( $y:expr ),* ]
//          );*
//     ) => {
//         &[ $($( $x + $y ),*),* ]
//     }
// }
//
// fn main() {
//     let a: &[i32]
//         = o_O!(10; [1, 2, 3];
//                20; [4, 5, 6]);
//
//     assert_eq!(a, [11, 12, 13, 24, 25, 26]);
// }

// TODO: Need to gensym a variable for each argument below:
//
// macro_rules! thunk {
//     ( $f:ident , $st:expr , $( $arg:expr ),* ) => {
//         let fval = Rc::new(Box::new(
//             |st, args|{
//                 let ($( $arg ),*) = args ;
//                 f( st, $( $arg ),* )
//             })) ;
//         ($st).thunk (ArtId::Eager, prog_pt!($f), fval, $( $arg ),* )
//     }}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Tasks scheduled on a GJ event loop are not preemptive. For an event loop to make progress,
//! event callbacks must yield control by returning.
//!
//! GJ event loops are thread-local. To take advantage of multiprocessor hardware or to deal with
//! tasks that cannot easily yield, you can send tasks to separate threads where they will execute
//! on separate event loops. The example program illustrates how that might work, using
//! `std::thread::sleep_ms()` as a stand-in for a blocking computation.

extern crate gj;
use gj::io::{AsyncRead, AsyncWrite};

fn child_loop(delay: u32,
              stream: gj::io::unix::Stream,
              buf: Vec<u8>) -> gj::Promise<(), gj::io::Error<(gj::io::unix::Stream, Vec<u8>)>> {

    // This blocks the entire thread. This is okay because we are on a child thread
    // where nothing else needs to happen.
    ::std::thread::sleep_ms(delay);

    stream.write(buf).then(move |(stream, buf)| {
        child_loop(delay, stream, buf)
    })
}

fn child(delay: u32) -> Result<gj::io::unix::Stream, Box<::std::error::Error>> {
    let (_, stream) = try!(gj::io::unix::spawn(move |parent_stream, wait_scope| {
        try!(child_loop(delay, parent_stream, vec![0u8]).lift::<Box<::std::error::Error>>().wait(wait_scope));
        Ok(())
    }));
    return Ok(stream);
}

fn listen_to_child(id: &'static str,
                   stream: gj::io::unix::Stream,
                   buf: Vec<u8>) -> gj::Promise<(), gj::io::Error<(gj::io::unix::Stream, Vec<u8>)>> {
    stream.read(buf, 1).then(move |(stream, buf, _n)| {
        println!("heard back from {}", id);
        listen_to_child(id, stream, buf)
    })
}

fn parent_wait_loop() -> gj::Promise<(), ::std::io::Error> {
    println!("parent wait loop...");

    // If we used ::std::thread::sleep_ms() here, we would block the main event loop.
    gj::io::Timer.after_delay_ms(3000).then(|()| {
        parent_wait_loop()
    })
}

pub fn main() {
    gj::EventLoop::top_level(|wait_scope| {

        let children = vec![
            parent_wait_loop().lift::<Box<::std::error::Error>>(),
            listen_to_child("CHILD 1", try!(child(700)), vec![0]).lift(),
            listen_to_child("CHILD 2", try!(child(1900)), vec![0]).lift(),
            listen_to_child("CHILD 3", try!(child(2600)), vec![0]).lift()];

        try!(gj::join_promises(children).wait(wait_scope));

        Ok(())
    }).unwrap();
}
<commit_msg>sleep_ms() -> sleep<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Tasks scheduled on a GJ event loop are not preemptive. For an event loop to make progress,
//! event callbacks must yield control by returning.
//!
//! GJ event loops are thread-local. To take advantage of multiprocessor hardware or to deal with
//! tasks that cannot easily yield, you can send tasks to separate threads where they will execute
//! on separate event loops. The example program illustrates how that might work, using
//! `std::thread::sleep_ms()` as a stand-in for a blocking computation.

extern crate gj;
use gj::io::{AsyncRead, AsyncWrite};
use std::time::Duration;

fn child_loop(delay: Duration,
              stream: gj::io::unix::Stream,
              buf: Vec<u8>) -> gj::Promise<(), gj::io::Error<(gj::io::unix::Stream, Vec<u8>)>> {

    // This blocks the entire thread. This is okay because we are on a child thread
    // where nothing else needs to happen.
    ::std::thread::sleep(delay);

    stream.write(buf).then(move |(stream, buf)| {
        child_loop(delay, stream, buf)
    })
}

fn child(delay: Duration) -> Result<gj::io::unix::Stream, Box<::std::error::Error>> {
    let (_, stream) = try!(gj::io::unix::spawn(move |parent_stream, wait_scope| {
        try!(child_loop(delay, parent_stream, vec![0u8]).lift::<Box<::std::error::Error>>().wait(wait_scope));
        Ok(())
    }));
    return Ok(stream);
}

fn listen_to_child(id: &'static str,
                   stream: gj::io::unix::Stream,
                   buf: Vec<u8>) -> gj::Promise<(), gj::io::Error<(gj::io::unix::Stream, Vec<u8>)>> {
    stream.read(buf, 1).then(move |(stream, buf, _n)| {
        println!("heard back from {}", id);
        listen_to_child(id, stream, buf)
    })
}

fn parent_wait_loop() -> gj::Promise<(), ::std::io::Error> {
    println!("parent wait loop...");

    // If we used ::std::thread::sleep_ms() here, we would block the main event loop.
    gj::io::Timer.after_delay_ms(3000).then(|()| {
        parent_wait_loop()
    })
}

pub fn main() {
    gj::EventLoop::top_level(|wait_scope| {

        let children = vec![
            parent_wait_loop().lift::<Box<::std::error::Error>>(),
            listen_to_child("CHILD 1", try!(child(Duration::from_millis(700))), vec![0]).lift(),
            listen_to_child("CHILD 2", try!(child(Duration::from_millis(1900))), vec![0]).lift(),
            listen_to_child("CHILD 3", try!(child(Duration::from_millis(2600))), vec![0]).lift()];

        try!(gj::join_promises(children).wait(wait_scope));

        Ok(())
    }).unwrap();
}
<|endoftext|>


<commit_before>use std::{
    collections::HashMap,
    path::{Path, PathBuf},
};

use xtask::{
    codegen::{self, Mode},
    not_bash::{fs2, run},
    project_root, run_rustfmt, rust_files,
};

#[test]
fn generated_grammar_is_fresh() {
    if let Err(error) = codegen::generate_syntax(Mode::Verify) {
        panic!("{}. Please update it by running `cargo xtask codegen`", error);
    }
}

#[test]
fn generated_tests_are_fresh() {
    if let Err(error) = codegen::generate_parser_tests(Mode::Verify) {
        panic!("{}. Please update tests by running `cargo xtask codegen`", error);
    }
}

#[test]
fn generated_assists_are_fresh() {
    if let Err(error) = codegen::generate_assists_tests(Mode::Verify) {
        panic!("{}. Please update assists by running `cargo xtask codegen`", error);
    }
}

#[test]
fn check_code_formatting() {
    if let Err(error) = run_rustfmt(Mode::Verify) {
        panic!("{}. Please format the code by running `cargo format`", error);
    }
}

#[test]
fn rust_files_are_tidy() {
    let mut tidy_docs = TidyDocs::default();
    for path in rust_files(&project_root().join("crates")) {
        let text = fs2::read_to_string(&path).unwrap();
        check_todo(&path, &text);
        check_trailing_ws(&path, &text);
        deny_clippy(&path, &text);
        tidy_docs.visit(&path, &text);
    }
    tidy_docs.finish();
}

fn deny_clippy(path: &PathBuf, text: &String) {
    if text.contains("[\u{61}llow(clippy") {
        panic!(
            "\n\nallowing lints is forbidden: {}.
rust-analyzer intentionally doesn't check clippy on CI.
You can allow lint globally via `xtask clippy`.

",
            path.display()
        )
    }
}

#[test]
fn check_licenses() {
    let expected = "
0BSD OR MIT OR Apache-2.0
Apache-2.0 OR BSL-1.0
Apache-2.0 OR MIT
Apache-2.0/MIT
BSD-2-Clause
BSD-3-Clause
CC0-1.0
ISC
MIT
MIT / Apache-2.0
MIT OR Apache-2.0
MIT/Apache-2.0
MIT/Apache-2.0 AND BSD-2-Clause
Unlicense OR MIT
Unlicense/MIT
Zlib
"
    .lines()
    .filter(|it| !it.is_empty())
    .collect::<Vec<_>>();

    let meta = run!("cargo metadata --format-version 1"; echo = false).unwrap();
    let mut licenses = meta
        .split(|c| c == ',' || c == '{' || c == '}')
        .filter(|it| it.contains(r#""license""#))
        .map(|it| it.trim())
        .map(|it| it[r#""license":"#.len()..].trim_matches('"'))
        .collect::<Vec<_>>();
    licenses.sort();
    licenses.dedup();
    assert_eq!(licenses, expected);
}

fn check_todo(path: &Path, text: &str) {
    let need_todo = &[
        // This file itself obviously needs to use todo (<- like this!).
        "tests/cli.rs",
        // Some of our assists generate `todo!()`.
        "tests/generated.rs",
        "handlers/add_missing_impl_members.rs",
        "handlers/add_turbo_fish.rs",
        "handlers/generate_function.rs",
        // To support generating `todo!()` in assists, we have `expr_todo()` in
        // `ast::make`.
        "ast/make.rs",
    ];
    if need_todo.iter().any(|p| path.ends_with(p)) {
        return;
    }
    if text.contains("TODO") || text.contains("TOOD") || text.contains("todo!") {
        panic!(
            "\nTODO markers or todo! macros should not be committed to the master branch,\n\
             use FIXME instead\n\
             {}\n",
            path.display(),
        )
    }
}

fn check_trailing_ws(path: &Path, text: &str) {
    if is_exclude_dir(path, &["test_data"]) {
        return;
    }
    for (line_number, line) in text.lines().enumerate() {
        if line.chars().last().map(char::is_whitespace) == Some(true) {
            panic!("Trailing whitespace in {} at line {}", path.display(), line_number)
        }
    }
}

#[derive(Default)]
struct TidyDocs {
    missing_docs: Vec<String>,
    contains_fixme: Vec<PathBuf>,
}

impl TidyDocs {
    fn visit(&mut self, path: &Path, text: &str) {
        // Test hopefully don't really need comments, and for assists we already
        // have special comments which are source of doc tests and user docs.
        if is_exclude_dir(path, &["tests", "test_data"]) {
            return;
        }

        if is_exclude_file(path) {
            return;
        }

        let first_line = match text.lines().next() {
            Some(it) => it,
            None => return,
        };

        if first_line.starts_with("//!") {
            if first_line.contains("FIXME") {
                self.contains_fixme.push(path.to_path_buf());
            }
        } else {
            if text.contains("// Feature:") || text.contains("// Assist:") {
                return;
            }
            self.missing_docs.push(path.display().to_string());
        }

        fn is_exclude_file(d: &Path) -> bool {
            let file_names = ["tests.rs"];

            d.file_name()
                .unwrap_or_default()
                .to_str()
                .map(|f_n| file_names.iter().any(|name| *name == f_n))
                .unwrap_or(false)
        }
    }

    fn finish(self) {
        if !self.missing_docs.is_empty() {
            panic!(
                "\nMissing docs strings\n\n\
                 modules:\n{}\n\n",
                self.missing_docs.join("\n")
            )
        }

        let poorly_documented = [
            "ra_hir",
            "ra_hir_expand",
            "ra_ide",
            "ra_mbe",
            "ra_parser",
            "ra_prof",
            "ra_project_model",
            "ra_syntax",
            "ra_tt",
            "ra_hir_ty",
        ];

        let mut has_fixmes =
            poorly_documented.iter().map(|it| (*it, false)).collect::<HashMap<&str, bool>>();
        'outer: for path in self.contains_fixme {
            for krate in poorly_documented.iter() {
                if path.components().any(|it| it.as_os_str() == *krate) {
                    has_fixmes.insert(krate, true);
                    continue 'outer;
                }
            }
            panic!("FIXME doc in a fully-documented crate: {}", path.display())
        }

        for (krate, has_fixme) in has_fixmes.iter() {
            if !has_fixme {
                panic!("crate {} is fully documented :tada:, remove it from the list of poorly documented crates", krate)
            }
        }
    }
}

fn is_exclude_dir(p: &Path, dirs_to_exclude: &[&str]) -> bool {
    p.strip_prefix(project_root())
        .unwrap()
        .components()
        .rev()
        .skip(1)
        .filter_map(|it| it.as_os_str().to_str())
        .any(|it| dirs_to_exclude.contains(&it))
}
<commit_msg>Minor<commit_after>use std::{
    collections::HashMap,
    path::{Path, PathBuf},
};

use xtask::{
    codegen::{self, Mode},
    not_bash::{fs2, run},
    project_root, run_rustfmt, rust_files,
};

#[test]
fn generated_grammar_is_fresh() {
    if let Err(error) = codegen::generate_syntax(Mode::Verify) {
        panic!("{}. Please update it by running `cargo xtask codegen`", error);
    }
}

#[test]
fn generated_tests_are_fresh() {
    if let Err(error) = codegen::generate_parser_tests(Mode::Verify) {
        panic!("{}. Please update tests by running `cargo xtask codegen`", error);
    }
}

#[test]
fn generated_assists_are_fresh() {
    if let Err(error) = codegen::generate_assists_tests(Mode::Verify) {
        panic!("{}. Please update assists by running `cargo xtask codegen`", error);
    }
}

#[test]
fn check_code_formatting() {
    if let Err(error) = run_rustfmt(Mode::Verify) {
        panic!("{}. Please format the code by running `cargo format`", error);
    }
}

#[test]
fn rust_files_are_tidy() {
    let mut tidy_docs = TidyDocs::default();
    for path in rust_files(&project_root().join("crates")) {
        let text = fs2::read_to_string(&path).unwrap();
        check_todo(&path, &text);
        check_trailing_ws(&path, &text);
        deny_clippy(&path, &text);
        tidy_docs.visit(&path, &text);
    }
    tidy_docs.finish();
}

fn deny_clippy(path: &PathBuf, text: &String) {
    if text.contains("[\u{61}llow(clippy") {
        panic!(
            "\n\nallowing lints is forbidden: {}.
rust-analyzer intentionally doesn't check clippy on CI.
You can allow lint globally via `xtask clippy`.
See https://github.com/rust-lang/rust-clippy/issues/5537 for discussion.

",
            path.display()
        )
    }
}

#[test]
fn check_licenses() {
    let expected = "
0BSD OR MIT OR Apache-2.0
Apache-2.0 OR BSL-1.0
Apache-2.0 OR MIT
Apache-2.0/MIT
BSD-2-Clause
BSD-3-Clause
CC0-1.0
ISC
MIT
MIT / Apache-2.0
MIT OR Apache-2.0
MIT/Apache-2.0
MIT/Apache-2.0 AND BSD-2-Clause
Unlicense OR MIT
Unlicense/MIT
Zlib
"
    .lines()
    .filter(|it| !it.is_empty())
    .collect::<Vec<_>>();

    let meta = run!("cargo metadata --format-version 1"; echo = false).unwrap();
    let mut licenses = meta
        .split(|c| c == ',' || c == '{' || c == '}')
        .filter(|it| it.contains(r#""license""#))
        .map(|it| it.trim())
        .map(|it| it[r#""license":"#.len()..].trim_matches('"'))
        .collect::<Vec<_>>();
    licenses.sort();
    licenses.dedup();
    assert_eq!(licenses, expected);
}

fn check_todo(path: &Path, text: &str) {
    let need_todo = &[
        // This file itself obviously needs to use todo (<- like this!).
        "tests/cli.rs",
        // Some of our assists generate `todo!()`.
        "tests/generated.rs",
        "handlers/add_missing_impl_members.rs",
        "handlers/add_turbo_fish.rs",
        "handlers/generate_function.rs",
        // To support generating `todo!()` in assists, we have `expr_todo()` in
        // `ast::make`.
        "ast/make.rs",
    ];
    if need_todo.iter().any(|p| path.ends_with(p)) {
        return;
    }
    if text.contains("TODO") || text.contains("TOOD") || text.contains("todo!") {
        panic!(
            "\nTODO markers or todo! macros should not be committed to the master branch,\n\
             use FIXME instead\n\
             {}\n",
            path.display(),
        )
    }
}

fn check_trailing_ws(path: &Path, text: &str) {
    if is_exclude_dir(path, &["test_data"]) {
        return;
    }
    for (line_number, line) in text.lines().enumerate() {
        if line.chars().last().map(char::is_whitespace) == Some(true) {
            panic!("Trailing whitespace in {} at line {}", path.display(), line_number)
        }
    }
}

#[derive(Default)]
struct TidyDocs {
    missing_docs: Vec<String>,
    contains_fixme: Vec<PathBuf>,
}

impl TidyDocs {
    fn visit(&mut self, path: &Path, text: &str) {
        // Test hopefully don't really need comments, and for assists we already
        // have special comments which are source of doc tests and user docs.
        if is_exclude_dir(path, &["tests", "test_data"]) {
            return;
        }

        if is_exclude_file(path) {
            return;
        }

        let first_line = match text.lines().next() {
            Some(it) => it,
            None => return,
        };

        if first_line.starts_with("//!") {
            if first_line.contains("FIXME") {
                self.contains_fixme.push(path.to_path_buf());
            }
        } else {
            if text.contains("// Feature:") || text.contains("// Assist:") {
                return;
            }
            self.missing_docs.push(path.display().to_string());
        }

        fn is_exclude_file(d: &Path) -> bool {
            let file_names = ["tests.rs"];

            d.file_name()
                .unwrap_or_default()
                .to_str()
                .map(|f_n| file_names.iter().any(|name| *name == f_n))
                .unwrap_or(false)
        }
    }

    fn finish(self) {
        if !self.missing_docs.is_empty() {
            panic!(
                "\nMissing docs strings\n\n\
                 modules:\n{}\n\n",
                self.missing_docs.join("\n")
            )
        }

        let poorly_documented = [
            "ra_hir",
            "ra_hir_expand",
            "ra_ide",
            "ra_mbe",
            "ra_parser",
            "ra_prof",
            "ra_project_model",
            "ra_syntax",
            "ra_tt",
            "ra_hir_ty",
        ];

        let mut has_fixmes =
            poorly_documented.iter().map(|it| (*it, false)).collect::<HashMap<&str, bool>>();
        'outer: for path in self.contains_fixme {
            for krate in poorly_documented.iter() {
                if path.components().any(|it| it.as_os_str() == *krate) {
                    has_fixmes.insert(krate, true);
                    continue 'outer;
                }
            }
            panic!("FIXME doc in a fully-documented crate: {}", path.display())
        }

        for (krate, has_fixme) in has_fixmes.iter() {
            if !has_fixme {
                panic!("crate {} is fully documented :tada:, remove it from the list of poorly documented crates", krate)
            }
        }
    }
}

fn is_exclude_dir(p: &Path, dirs_to_exclude: &[&str]) -> bool {
    p.strip_prefix(project_root())
        .unwrap()
        .components()
        .rev()
        .skip(1)
        .filter_map(|it| it.as_os_str().to_str())
        .any(|it| dirs_to_exclude.contains(&it))
}
<|endoftext|>


<commit_before>/// Internal metric representation
///
use std::fmt;

/// Enum of metric types
pub enum MetricKind {
    Counter(f64), // sample rate
    Gauge,
    Timer,
}

impl fmt::Debug for MetricKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            MetricKind::Gauge      => write!(f, "Gauge"),
            MetricKind::Timer      => write!(f, "Timer"),
            MetricKind::Counter(s) => write!(f, "Counter(s={})", s)
        }
    }
}

/// Error types for parsing Metrics from strings.
///
#[derive(Debug)]
pub enum ParseError {
    // Error message, column
    SyntaxError(&'static str, usize)
}

/// Metric value objects.
///
#[derive(Debug)]
pub struct Metric {
    pub kind: MetricKind,
    pub name: String,
    pub value: f64
}

impl Metric {
    /// Create a new metric
    ///
    /// Uses the Into trait to allow both str and String types.
    pub fn new<S: Into<String>>(name: S, value: f64, kind: MetricKind) -> Metric {
        Metric{name: name.into(), value: value, kind: kind}
    }

    /// Valid message formats are:
    ///
    /// - `<str:metric_name>:<f64:value>|<str:type>`
    /// - `<str:metric_name>:<f64:value>|c|@<f64:sample_rate>`
    ///
    /// Multiple metrics can be sent in a single UDP packet
    /// separated by newlines.
    pub fn parse(source: &str) -> Result<Vec<Metric>, ParseError> {
        let mut results: Vec<Metric> = Vec::new();

        for line in source.lines() {
            match Metric::parse_line(line) {
                Ok(metric) => results.push(metric),
                Err(e) => return Err(e)
            }
        }
        if results.len() == 0 {
            return Err(ParseError::SyntaxError(
                    "No metrics found",
                    0))
        }
        Ok(results)
    }

    fn parse_line(line: &str) -> Result<Metric, ParseError> {
        // Get the metric name
        let name_parts: Vec<&str> = line.trim_right_matches('\n')
            .split(':')
            .collect();

        if name_parts.len() < 2 || name_parts[0].is_empty() {
            return Err(ParseError::SyntaxError(
                    "Metrics require a name.",
                    0))
        }
        let name = name_parts[0].to_string();

        // Get the float val
        let val_parts: Vec<&str> = name_parts[1].split('|').collect();
        if val_parts.len() < 2 || val_parts[0].is_empty() {
            return Err(ParseError::SyntaxError(
                    "Metrics require a value.",
                    name.len()))
        }
        let value = val_parts[0].parse::<f64>().ok().unwrap();

        // Get kind parts
        let kind = match val_parts[1] {
            "ms" => MetricKind::Timer,
            "g" => MetricKind::Gauge,
            "c" => {
                let mut rate:f64 = 1.0;
                if val_parts.len() == 3 {
                    rate = val_parts[2].trim_left_matches('@')
                        .parse::<f64>().ok().unwrap();
                }
                MetricKind::Counter(rate)
            },
            _ => return Err(ParseError::SyntaxError(
                    "Unknown metric type.",
                    2))
        };
        Ok(Metric::new(name, value, kind))
    }
}

//
// Tests
//
#[cfg(test)]
mod test {
    use metric::{Metric,MetricKind};
    use std::collections::HashMap;

    #[test]
    fn test_metric_kind_debug_fmt() {
        assert_eq!(
            "Gauge",
            format!("{:?}", MetricKind::Gauge)
        );
        assert_eq!(
            "Timer",
            format!("{:?}", MetricKind::Timer)
        );
        assert_eq!(
            "Counter(s=6)",
            format!("{:?}", MetricKind::Counter(6.0))
        );
    }

    #[test]
    fn test_metric_parse_invalid_no_name() {
        let res = Metric::parse("");
        assert!(res.is_err(), "Should have an error");
        assert!(!res.is_ok(), "Should have an error");
    }

    #[test]
    fn test_metric_parse_invalid_no_value() {
        let res = Metric::parse("foo:");
        assert!(res.is_err(), "Should have an error");
        assert!(!res.is_ok(), "Should have an error");
    }

    #[test]
    fn test_metric_multiple() {
        let res = Metric::parse("a.b:12.1|g\nb.c:13.2|c").unwrap();
        assert_eq!(2, res.len());

        assert_eq!("a.b", res[0].name);
        assert_eq!(12.1, res[0].value);

        assert_eq!("b.c", res[1].name);
        assert_eq!(13.2, res[1].value);
    }

    #[test]
    fn test_metric_valid() {
        let mut valid = HashMap::new();
        valid.insert(
            "foo.test:12.3|ms\n",
            Metric::new("foo.test", 12.3, MetricKind::Timer)
        );
        valid.insert(
            "foo.test:12.3|ms",
            Metric::new("foo.test", 12.3, MetricKind::Timer)
        );
        valid.insert(
            "test:18.123|g",
            Metric::new("test", 18.123, MetricKind::Gauge)
        );
        valid.insert(
            "test:18.123|g",
            Metric::new("test", 18.123, MetricKind::Gauge)
        );
        valid.insert(
            "thing.total:12|c",
            Metric::new("thing.total", 12.0, MetricKind::Counter(1.0))
        );
        valid.insert(
            "thing.total:5.6|c|@123",
            Metric::new("thing.total", 5.6, MetricKind::Counter(123.0))
        );

        for (input, expected) in valid.iter() {
            let result = Metric::parse(*input);
            assert!(result.is_ok());

            let actual = result.ok().unwrap();
            assert_eq!(expected.name, actual[0].name);
            assert_eq!(expected.value, actual[0].value);

            // TODO this is stupid, there must be a better way.
            assert_eq!(
                format!("{:?}", expected.kind),
                format!("{:?}", actual[0].kind)
            );
        }
    }

    #[test]
    fn test_metric_invalid() {
        let invalid = vec![
            "",
            "metric",
            "metric|12",
            "metric:13|",
            "metric:14|c@1",
            ":|@",
            ":1.0|c"
        ];
        for input in invalid.iter() {
            let result = Metric::parse(*input);
            assert!(result.is_err());
        }
    }
}
<commit_msg>Add comment for parse_line.<commit_after>/// Internal metric representation
///
use std::fmt;

/// Enum of metric types
pub enum MetricKind {
    Counter(f64), // sample rate
    Gauge,
    Timer,
}

impl fmt::Debug for MetricKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            MetricKind::Gauge      => write!(f, "Gauge"),
            MetricKind::Timer      => write!(f, "Timer"),
            MetricKind::Counter(s) => write!(f, "Counter(s={})", s)
        }
    }
}

/// Error types for parsing Metrics from strings.
///
#[derive(Debug)]
pub enum ParseError {
    // Error message, column
    SyntaxError(&'static str, usize)
}

/// Metric value objects.
///
#[derive(Debug)]
pub struct Metric {
    pub kind: MetricKind,
    pub name: String,
    pub value: f64
}

impl Metric {
    /// Create a new metric
    ///
    /// Uses the Into trait to allow both str and String types.
    pub fn new<S: Into<String>>(name: S, value: f64, kind: MetricKind) -> Metric {
        Metric{name: name.into(), value: value, kind: kind}
    }

    /// Valid message formats are:
    ///
    /// - `<str:metric_name>:<f64:value>|<str:type>`
    /// - `<str:metric_name>:<f64:value>|c|@<f64:sample_rate>`
    ///
    /// Multiple metrics can be sent in a single UDP packet
    /// separated by newlines.
    pub fn parse(source: &str) -> Result<Vec<Metric>, ParseError> {
        let mut results: Vec<Metric> = Vec::new();

        for line in source.lines() {
            match Metric::parse_line(line) {
                Ok(metric) => results.push(metric),
                Err(e) => return Err(e)
            }
        }
        if results.len() == 0 {
            return Err(ParseError::SyntaxError(
                    "No metrics found",
                    0))
        }
        Ok(results)
    }

    /// Parses a metric from each line in a packet.
    fn parse_line(line: &str) -> Result<Metric, ParseError> {
        // Get the metric name
        let name_parts: Vec<&str> = line.trim_right_matches('\n')
            .split(':')
            .collect();

        if name_parts.len() < 2 || name_parts[0].is_empty() {
            return Err(ParseError::SyntaxError(
                    "Metrics require a name.",
                    0))
        }
        let name = name_parts[0].to_string();

        // Get the float val
        let val_parts: Vec<&str> = name_parts[1].split('|').collect();
        if val_parts.len() < 2 || val_parts[0].is_empty() {
            return Err(ParseError::SyntaxError(
                    "Metrics require a value.",
                    name.len()))
        }
        let value = val_parts[0].parse::<f64>().ok().unwrap();

        // Get kind parts
        let kind = match val_parts[1] {
            "ms" => MetricKind::Timer,
            "g" => MetricKind::Gauge,
            "c" => {
                let mut rate:f64 = 1.0;
                if val_parts.len() == 3 {
                    rate = val_parts[2].trim_left_matches('@')
                        .parse::<f64>().ok().unwrap();
                }
                MetricKind::Counter(rate)
            },
            _ => return Err(ParseError::SyntaxError(
                    "Unknown metric type.",
                    2))
        };
        Ok(Metric::new(name, value, kind))
    }
}

//
// Tests
//
#[cfg(test)]
mod test {
    use metric::{Metric,MetricKind};
    use std::collections::HashMap;

    #[test]
    fn test_metric_kind_debug_fmt() {
        assert_eq!(
            "Gauge",
            format!("{:?}", MetricKind::Gauge)
        );
        assert_eq!(
            "Timer",
            format!("{:?}", MetricKind::Timer)
        );
        assert_eq!(
            "Counter(s=6)",
            format!("{:?}", MetricKind::Counter(6.0))
        );
    }

    #[test]
    fn test_metric_parse_invalid_no_name() {
        let res = Metric::parse("");
        assert!(res.is_err(), "Should have an error");
        assert!(!res.is_ok(), "Should have an error");
    }

    #[test]
    fn test_metric_parse_invalid_no_value() {
        let res = Metric::parse("foo:");
        assert!(res.is_err(), "Should have an error");
        assert!(!res.is_ok(), "Should have an error");
    }

    #[test]
    fn test_metric_multiple() {
        let res = Metric::parse("a.b:12.1|g\nb.c:13.2|c").unwrap();
        assert_eq!(2, res.len());

        assert_eq!("a.b", res[0].name);
        assert_eq!(12.1, res[0].value);

        assert_eq!("b.c", res[1].name);
        assert_eq!(13.2, res[1].value);
    }

    #[test]
    fn test_metric_valid() {
        let mut valid = HashMap::new();
        valid.insert(
            "foo.test:12.3|ms\n",
            Metric::new("foo.test", 12.3, MetricKind::Timer)
        );
        valid.insert(
            "foo.test:12.3|ms",
            Metric::new("foo.test", 12.3, MetricKind::Timer)
        );
        valid.insert(
            "test:18.123|g",
            Metric::new("test", 18.123, MetricKind::Gauge)
        );
        valid.insert(
            "test:18.123|g",
            Metric::new("test", 18.123, MetricKind::Gauge)
        );
        valid.insert(
            "thing.total:12|c",
            Metric::new("thing.total", 12.0, MetricKind::Counter(1.0))
        );
        valid.insert(
            "thing.total:5.6|c|@123",
            Metric::new("thing.total", 5.6, MetricKind::Counter(123.0))
        );

        for (input, expected) in valid.iter() {
            let result = Metric::parse(*input);
            assert!(result.is_ok());

            let actual = result.ok().unwrap();
            assert_eq!(expected.name, actual[0].name);
            assert_eq!(expected.value, actual[0].value);

            // TODO this is stupid, there must be a better way.
            assert_eq!(
                format!("{:?}", expected.kind),
                format!("{:?}", actual[0].kind)
            );
        }
    }

    #[test]
    fn test_metric_invalid() {
        let invalid = vec![
            "",
            "metric",
            "metric|12",
            "metric:13|",
            "metric:14|c@1",
            ":|@",
            ":1.0|c"
        ];
        for input in invalid.iter() {
            let result = Metric::parse(*input);
            assert!(result.is_err());
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015-2016 Deyan Ginev. See the LICENSE
// file at the top-level directory of this distribution.
//
// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Backend models and traits for the CorTeX "Task store"

use std::fmt;
use rand::{thread_rng, Rng};
use helpers::TaskStatus;

use diesel::result::Error;
use diesel::{delete, insert_into, update};
use diesel::pg::PgConnection;
use diesel::prelude::*;
use schema::tasks;
use schema::log_infos;
use schema::log_warnings;
use schema::log_errors;
use schema::log_fatals;
use schema::log_invalids;
use concerns::{CortexInsertable, CortexDeletable};

// Tasks

#[derive(Identifiable, Queryable, AsChangeset, Clone)]
/// A CorTeX task, for a given corpus-service pair
pub struct Task {
  /// task primary key, auto-incremented by postgresql
  pub id: i64,
  /// id of the service owning this task
  pub serviceid: i32,
  /// id of the corpus hosting this task
  pub corpusid: i32,
  /// current processing status of this task
  pub status: i32,
  /// entry path on the file system
  pub entry: String,
}

#[derive(Insertable)]
#[table_name = "tasks"]
/// A new task, to be inserted into CorTeX
pub struct NewTask<'a> {
  /// id of the service owning this task
  pub serviceid: i32,
  /// id of the corpus hosting this task
  pub corpusid: i32,
  /// current processing status of this task
  pub status: i32,
  /// entry path on the file system
  pub entry: &'a str,
}

impl fmt::Display for Task {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    // The `f` value implements the `Write` trait, which is what the
    // write! macro is expecting. Note that this formatting ignores the
    // various flags provided to format strings.
    write!(
      f,
      "(id: {}, entry: {},\n\tserviceid: {},\n\tcorpusid: {},\n\t status: {})\n",
      self.id,
      self.entry,
      self.serviceid,
      self.corpusid,
      self.status
    )
  }
}
impl fmt::Debug for Task {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    // The `f` value implements the `Write` trait, which is what the
    // write! macro is expecting. Note that this formatting ignores the
    // various flags provided to format strings.
    write!(
      f,
      "(id: {},\n\tentry: {},\n\tserviceid: {},\n\tcorpusid: {},\n\t status: {})\n",
      self.id,
      self.entry,
      self.serviceid,
      self.corpusid,
      self.status
    )
  }
}

impl<'a> CortexInsertable for NewTask<'a> {
  fn create(&self, connection: &PgConnection) -> Result<usize, Error> {
    insert_into(tasks::table).values(self).execute(connection)
  }
}

impl CortexDeletable for Task {
  fn delete_by(&self, connection: &PgConnection, field: &str) -> Result<usize, Error> {
    match field {
      "entry" => self.delete_by_entry(connection),
      "serviceid" => self.delete_by_serviceid(connection),
      "id" => self.delete_by_id(connection),
      _ => Err(Error::QueryBuilderError(
        format!("unknown Task model field: {}", field).into(),
      )),
    }
  }
}
impl Task {
  fn delete_by_entry(&self, connection: &PgConnection) -> Result<usize, Error> {
    use schema::tasks::dsl::entry;
    delete(tasks::table.filter(entry.eq(&self.entry))).execute(connection)
  }
  fn delete_by_serviceid(&self, connection: &PgConnection) -> Result<usize, Error> {
    use schema::tasks::dsl::serviceid;
    delete(tasks::table.filter(serviceid.eq(&self.serviceid))).execute(connection)
  }
  fn delete_by_id(&self, connection: &PgConnection) -> Result<usize, Error> {
    use schema::tasks::dsl::id;
    delete(tasks::table.filter(id.eq(self.id))).execute(connection)
  }
}

impl<'a> CortexDeletable for NewTask<'a> {
  fn delete_by(&self, connection: &PgConnection, field: &str) -> Result<usize, Error> {
    match field {
      "entry" => self.delete_by_entry(connection),
      "serviceid" => self.delete_by_serviceid(connection),
      _ => Err(Error::QueryBuilderError(
        format!("unknown Task model field: {}", field).into(),
      )),
    }
  }
}

impl<'a> NewTask<'a> {
  fn delete_by_entry(&self, connection: &PgConnection) -> Result<usize, Error> {
    use schema::tasks::dsl::entry;
    delete(tasks::table.filter(entry.eq(&self.entry))).execute(connection)
  }
  fn delete_by_serviceid(&self, connection: &PgConnection) -> Result<usize, Error> {
    use schema::tasks::dsl::serviceid;
    delete(tasks::table.filter(serviceid.eq(&self.serviceid))).execute(connection)
  }
}

// Log Messages

#[derive(Identifiable, Queryable, AsChangeset, Clone)]
/// An info/debug message, as per the `LaTeXML` convention
pub struct LogInfo {
  /// task primary key, auto-incremented by postgresql
  pub id: i64,
  /// mid-level description (open set)
  pub category: String,
  /// low-level description (open set)
  pub what: String,
  /// technical details of the message (e.g. localization info)
  pub details: String,
}
#[derive(Identifiable, Queryable, AsChangeset, Clone)]
/// A warning message, as per the `LaTeXML` convention
pub struct LogWarning {
  /// task primary key, auto-incremented by postgresql
  pub id: i64,
  /// mid-level description (open set)
  pub category: String,
  /// low-level description (open set)
  pub what: String,
  /// technical details of the message (e.g. localization info)
  pub details: String,
}
#[derive(Identifiable, Queryable, AsChangeset, Clone)]
/// An error message, as per the `LaTeXML` convention
pub struct LogError {
  /// task primary key, auto-incremented by postgresql
  pub id: i64,
  /// mid-level description (open set)
  pub category: String,
  /// low-level description (open set)
  pub what: String,
  /// technical details of the message (e.g. localization info)
  pub details: String,
}
#[derive(Identifiable, Queryable, AsChangeset, Clone)]
/// A fatal message, as per the `LaTeXML` convention
pub struct LogFatal {
  /// task primary key, auto-incremented by postgresql
  pub id: i64,
  /// mid-level description (open set)
  pub category: String,
  /// low-level description (open set)
  pub what: String,
  /// technical details of the message (e.g. localization info)
  pub details: String,
}
#[derive(Identifiable, Queryable, AsChangeset, Clone)]
/// An invalid message, as per the `LaTeXML` convention
pub struct LogInvalid {
  /// task primary key, auto-incremented by postgresql
  pub id: i64,
  /// mid-level description (open set)
  pub category: String,
  /// low-level description (open set)
  pub what: String,
  /// technical details of the message (e.g. localization info)
  pub details: String,
}

// impl fmt::Display for TaskMessage {
//   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//     write!(f,
//            "(severity: {}, category: {},\n\twhat: {},\n\tdetails: {})\n",
//            self.severity,
//            self.category,
//            self.what,
//            self.details)
//   }
// }
// impl fmt::Debug for TaskMessage {
//   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//     write!(f,
//            "(severity: {}, category: {},\n\twhat: {},\n\tdetails: {})\n",
//            self.severity,
//            self.category,
//            self.what,
//            self.details)
//   }
// }

// Services
#[derive(Clone)]
/// A `CorTeX` processing service
pub struct Service {
  /// optional id (None for mock / yet-to-be-inserted rows)
  pub id: i32,
  /// a human-readable name for this service
  pub name: String,
  /// a floating-point number to mark the current version (e.g. 0.01)
  pub version: f32,
  /// the expected input format for this service (e.g. tex)
  pub inputformat: String,
  /// the produced output format by this service (e.g. html)
  pub outputformat: String,
  // pub xpath : String,
  // pub resource : String,
  /// prerequisite input conversion service, if any
  pub inputconverter: Option<String>,
  /// is this service requiring more than the main textual content of a document?
  /// mark "true" if unsure
  pub complex: bool,
}

// Aggregate methods, to be used by backend

/// Fetch a batch of `queue_size` TODO tasks for a given `service`.
pub fn fetch_tasks(
  service: &Service,
  queue_size: usize,
  connection: &PgConnection,
) -> Result<Vec<Task>, Error> {
  use schema::tasks::dsl::{serviceid, status};
  let mut rng = thread_rng();
  let mark: u16 = 1 + rng.gen::<u16>();

  let mut marked_tasks: Vec<Task> = Vec::new();
  try!(connection.transaction::<(), Error, _>(|| {
    let tasks_for_update = try!(
      tasks::table
        .for_update()
        .filter(serviceid.eq(service.id))
        .filter(status.eq(TaskStatus::TODO.raw()))
        .limit(queue_size as i64)
        .load(connection)
    );
    marked_tasks = tasks_for_update
      .into_iter()
      .map(|task| {
        Task {
          status: i32::from(mark),
          ..task
        }
      })
      .map(|task| task.save_changes(connection))
      .filter_map(|saved| saved.ok())
      .collect();
    Ok(())
  }));
  Ok(marked_tasks)
}

/// Mark all "limbo" (= "in progress", assumed disconnected) tasks as TODO
pub fn clear_limbo_tasks(connection: &PgConnection) -> Result<usize, Error> {
  use schema::tasks::dsl::status;
  update(tasks::table)
    .filter(status.gt(&TaskStatus::TODO.raw()))
    .set(status.eq(&TaskStatus::TODO.raw()))
    .execute(connection)
}<commit_msg>LogRecord trait beginnings<commit_after>// Copyright 2015-2016 Deyan Ginev. See the LICENSE
// file at the top-level directory of this distribution.
//
// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Backend models and traits for the CorTeX "Task store"

use std::fmt;
use rand::{thread_rng, Rng};
use helpers::TaskStatus;

use diesel::result::Error;
use diesel::{delete, insert_into, update};
use diesel::pg::PgConnection;
use diesel::prelude::*;
use schema::tasks;
use schema::log_infos;
use schema::log_warnings;
use schema::log_errors;
use schema::log_fatals;
use schema::log_invalids;
use concerns::{CortexInsertable, CortexDeletable};

// Tasks

#[derive(Identifiable, Queryable, AsChangeset, Clone)]
/// A CorTeX task, for a given corpus-service pair
pub struct Task {
  /// task primary key, auto-incremented by postgresql
  pub id: i64,
  /// id of the service owning this task
  pub serviceid: i32,
  /// id of the corpus hosting this task
  pub corpusid: i32,
  /// current processing status of this task
  pub status: i32,
  /// entry path on the file system
  pub entry: String,
}

#[derive(Insertable)]
#[table_name = "tasks"]
/// A new task, to be inserted into CorTeX
pub struct NewTask<'a> {
  /// id of the service owning this task
  pub serviceid: i32,
  /// id of the corpus hosting this task
  pub corpusid: i32,
  /// current processing status of this task
  pub status: i32,
  /// entry path on the file system
  pub entry: &'a str,
}

impl fmt::Display for Task {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(
      f,
      "(id: {}, entry: {},\n\tserviceid: {},\n\tcorpusid: {},\n\t status: {})\n",
      self.id,
      self.entry,
      self.serviceid,
      self.corpusid,
      self.status
    )
  }
}
impl fmt::Debug for Task {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(
      f,
      "(id: {},\n\tentry: {},\n\tserviceid: {},\n\tcorpusid: {},\n\t status: {})\n",
      self.id,
      self.entry,
      self.serviceid,
      self.corpusid,
      self.status
    )
  }
}

impl<'a> CortexInsertable for NewTask<'a> {
  fn create(&self, connection: &PgConnection) -> Result<usize, Error> {
    insert_into(tasks::table).values(self).execute(connection)
  }
}

impl CortexDeletable for Task {
  fn delete_by(&self, connection: &PgConnection, field: &str) -> Result<usize, Error> {
    match field {
      "entry" => self.delete_by_entry(connection),
      "serviceid" => self.delete_by_serviceid(connection),
      "id" => self.delete_by_id(connection),
      _ => Err(Error::QueryBuilderError(
        format!("unknown Task model field: {}", field).into(),
      )),
    }
  }
}
impl Task {
  fn delete_by_entry(&self, connection: &PgConnection) -> Result<usize, Error> {
    use schema::tasks::dsl::entry;
    delete(tasks::table.filter(entry.eq(&self.entry))).execute(connection)
  }
  fn delete_by_serviceid(&self, connection: &PgConnection) -> Result<usize, Error> {
    use schema::tasks::dsl::serviceid;
    delete(tasks::table.filter(serviceid.eq(&self.serviceid))).execute(connection)
  }
  fn delete_by_id(&self, connection: &PgConnection) -> Result<usize, Error> {
    use schema::tasks::dsl::id;
    delete(tasks::table.filter(id.eq(self.id))).execute(connection)
  }
}

impl<'a> CortexDeletable for NewTask<'a> {
  fn delete_by(&self, connection: &PgConnection, field: &str) -> Result<usize, Error> {
    match field {
      "entry" => self.delete_by_entry(connection),
      "serviceid" => self.delete_by_serviceid(connection),
      _ => Err(Error::QueryBuilderError(
        format!("unknown Task model field: {}", field).into(),
      )),
    }
  }
}

impl<'a> NewTask<'a> {
  fn delete_by_entry(&self, connection: &PgConnection) -> Result<usize, Error> {
    use schema::tasks::dsl::entry;
    delete(tasks::table.filter(entry.eq(&self.entry))).execute(connection)
  }
  fn delete_by_serviceid(&self, connection: &PgConnection) -> Result<usize, Error> {
    use schema::tasks::dsl::serviceid;
    delete(tasks::table.filter(serviceid.eq(&self.serviceid))).execute(connection)
  }
}

// Log Messages

#[derive(Identifiable, Queryable, AsChangeset, Clone)]
/// An info/debug message, as per the `LaTeXML` convention
pub struct LogInfo {
  /// task primary key, auto-incremented by postgresql
  pub id: i64,
  /// mid-level description (open set)
  pub category: String,
  /// low-level description (open set)
  pub what: String,
  /// technical details of the message (e.g. localization info)
  pub details: String,
}
#[derive(Identifiable, Queryable, AsChangeset, Clone)]
/// A warning message, as per the `LaTeXML` convention
pub struct LogWarning {
  /// task primary key, auto-incremented by postgresql
  pub id: i64,
  /// mid-level description (open set)
  pub category: String,
  /// low-level description (open set)
  pub what: String,
  /// technical details of the message (e.g. localization info)
  pub details: String,
}
#[derive(Identifiable, Queryable, AsChangeset, Clone)]
/// An error message, as per the `LaTeXML` convention
pub struct LogError {
  /// task primary key, auto-incremented by postgresql
  pub id: i64,
  /// mid-level description (open set)
  pub category: String,
  /// low-level description (open set)
  pub what: String,
  /// technical details of the message (e.g. localization info)
  pub details: String,
}
#[derive(Identifiable, Queryable, AsChangeset, Clone)]
/// A fatal message, as per the `LaTeXML` convention
pub struct LogFatal {
  /// task primary key, auto-incremented by postgresql
  pub id: i64,
  /// mid-level description (open set)
  pub category: String,
  /// low-level description (open set)
  pub what: String,
  /// technical details of the message (e.g. localization info)
  pub details: String,
}
#[derive(Identifiable, Queryable, AsChangeset, Clone)]
/// An invalid message, as per the `LaTeXML` convention
pub struct LogInvalid {
  /// task primary key, auto-incremented by postgresql
  pub id: i64,
  /// mid-level description (open set)
  pub category: String,
  /// low-level description (open set)
  pub what: String,
  /// technical details of the message (e.g. localization info)
  pub details: String,
}

/// Log actor trait, assumes already Identifiable (for id())
pub trait LogRecord {
  /// Category accessor
  fn category(&self) -> &str;
  /// What accessor
  fn what(&self) -> &str;
  /// Details accessor
  fn details(&self) -> &str;
  /// Severity accessor
  fn severity(&self) -> &str;
  /// Implements the fmt::Debug fmt
  fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(
      f,
      "{}(category: {},\n\twhat: {},\n\tdetails: {})\n",
      self.severity(),
      self.category(),
      self.what(),
      self.details()
    )
  }
}

// impl fmt::Display for TaskMessage {
//   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//     write!(f,
//            "(severity: {}, category: {},\n\twhat: {},\n\tdetails: {})\n",
//            self.severity,
//            self.category,
//            self.what,
//            self.details)
//   }
// }
impl LogRecord for LogInfo {
  fn category(&self) -> &str {
    &self.category
  }
  fn what(&self) -> &str {
    &self.what
  }
  fn details(&self) -> &str {
    &self.details
  }
  fn severity(&self) -> &str {
    "Info"
  }
}
impl fmt::Debug for LogInfo {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    self.debug(f)
  }
}
impl LogRecord for LogWarning {
  fn category(&self) -> &str {
    &self.category
  }
  fn what(&self) -> &str {
    &self.what
  }
  fn details(&self) -> &str {
    &self.details
  }
  fn severity(&self) -> &str {
    "Warning"
  }
}
impl fmt::Debug for LogWarning {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    self.debug(f)
  }
}
impl LogRecord for LogError {
  fn category(&self) -> &str {
    &self.category
  }
  fn what(&self) -> &str {
    &self.what
  }
  fn details(&self) -> &str {
    &self.details
  }
  fn severity(&self) -> &str {
    "Error"
  }
}
impl fmt::Debug for LogError {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    self.debug(f)
  }
}
impl LogRecord for LogFatal {
  fn category(&self) -> &str {
    &self.category
  }
  fn what(&self) -> &str {
    &self.what
  }
  fn details(&self) -> &str {
    &self.details
  }
  fn severity(&self) -> &str {
    "Fatal"
  }
}
impl fmt::Debug for LogFatal {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    self.debug(f)
  }
}
impl LogRecord for LogInvalid {
  fn category(&self) -> &str {
    &self.category
  }
  fn what(&self) -> &str {
    &self.what
  }
  fn details(&self) -> &str {
    &self.details
  }
  fn severity(&self) -> &str {
    "Invalid"
  }
}
impl fmt::Debug for LogInvalid {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    self.debug(f)
  }
}

// Services
#[derive(Clone)]
/// A `CorTeX` processing service
pub struct Service {
  /// optional id (None for mock / yet-to-be-inserted rows)
  pub id: i32,
  /// a human-readable name for this service
  pub name: String,
  /// a floating-point number to mark the current version (e.g. 0.01)
  pub version: f32,
  /// the expected input format for this service (e.g. tex)
  pub inputformat: String,
  /// the produced output format by this service (e.g. html)
  pub outputformat: String,
  // pub xpath : String,
  // pub resource : String,
  /// prerequisite input conversion service, if any
  pub inputconverter: Option<String>,
  /// is this service requiring more than the main textual content of a document?
  /// mark "true" if unsure
  pub complex: bool,
}

// Aggregate methods, to be used by backend

/// Fetch a batch of `queue_size` TODO tasks for a given `service`.
pub fn fetch_tasks(
  service: &Service,
  queue_size: usize,
  connection: &PgConnection,
) -> Result<Vec<Task>, Error> {
  use schema::tasks::dsl::{serviceid, status};
  let mut rng = thread_rng();
  let mark: u16 = 1 + rng.gen::<u16>();

  let mut marked_tasks: Vec<Task> = Vec::new();
  try!(connection.transaction::<(), Error, _>(|| {
    let tasks_for_update = try!(
      tasks::table
        .for_update()
        .filter(serviceid.eq(service.id))
        .filter(status.eq(TaskStatus::TODO.raw()))
        .limit(queue_size as i64)
        .load(connection)
    );
    marked_tasks = tasks_for_update
      .into_iter()
      .map(|task| {
        Task {
          status: i32::from(mark),
          ..task
        }
      })
      .map(|task| task.save_changes(connection))
      .filter_map(|saved| saved.ok())
      .collect();
    Ok(())
  }));
  Ok(marked_tasks)
}

/// Mark all "limbo" (= "in progress", assumed disconnected) tasks as TODO
pub fn clear_limbo_tasks(connection: &PgConnection) -> Result<usize, Error> {
  use schema::tasks::dsl::status;
  update(tasks::table)
    .filter(status.gt(&TaskStatus::TODO.raw()))
    .set(status.eq(&TaskStatus::TODO.raw()))
    .execute(connection)
}<|endoftext|>


<commit_before>use libc::c_char;
use ffi::prelude::{LLVMValueRef, LLVMModuleRef};
use ffi::{core, LLVMModule};
use ffi::bit_writer as writer;
use ffi::bit_reader as reader;
use cbox::CBox;
use std::ffi::CString;
use std::iter::{Iterator, IntoIterator};
use std::{fmt, mem};
use std::marker::PhantomData;
use buffer::MemoryBuffer;
use context::{Context, GetContext};
use value::Function;
use ty::Type;
use util;

/// Represents a translation unit
///
/// This is attached to the lifetime of the context that constructs it
pub struct Module;
native_ref!(&Module = LLVMModuleRef);
impl Module {
    /// Create a new module in the context given with the name given
    ///
    /// The lifetime of the module will match the lifetime of the context
    /// you instance it in because the context contains it
    ///
    /// ```rust
    /// use llvm::*;
    /// let context = Context::new();
    /// let module = Module::new("name", &context);
    /// println!("{:?}", module)
    /// ```
    pub fn new<'a>(name: &str, context: &'a Context) -> CBox<'a, Module> {
        let c_name = CString::new(name).unwrap();
        unsafe { CBox::new(core::LLVMModuleCreateWithNameInContext(c_name.as_ptr(), context.into())) }
    }
    /// Parse this bitcode file into a module
    pub fn parse_bitcode<'a, 'b>(context: &'a Context, path: &'b str) -> Result<CBox<'b, Module>, CBox<'b, str>> {
        unsafe {
            let mut out = mem::uninitialized();
            let mut err = mem::uninitialized();
            let buf = try!(MemoryBuffer::new_from_file(path));
            if reader::LLVMParseBitcodeInContext(context.into(), (&*buf).into(), &mut out, &mut err) == 1 {
                Err(CBox::new(err))
            } else {
                Ok(CBox::new(out))
            }
        }
    }
    /// Write this module's bitcode to the path given
    pub fn write_bitcode(&self, path: &str) {
        util::with_cstr(path, |cpath| unsafe {
            if writer::LLVMWriteBitcodeToFile(self.into(), cpath) != 0 {
                panic!("failed to write bitcode to file {}", path)
            }
        })
    }
    /// Add a function to the module with the name given
    pub fn add_function<'a>(&'a self, name: &str, sig: &'a Type) -> &'a mut Function {
        let c_name = CString::new(name).unwrap();
        unsafe { core::LLVMAddFunction(self.into(), c_name.as_ptr(), sig.into()) }.into()
    }
    /// Returns the function with the name given if it exists
    pub fn get_function<'a>(&'a self, name: &str) -> Option<&'a Function> {
        let c_name = CString::new(name).unwrap();
        let val = unsafe { core::LLVMGetNamedFunction(self.into(), c_name.as_ptr()) };
        if val.is_null() {
            None
        } else {
            Some(val.into())
        }
    }
    /// Returns the type with the name given if it exists
    pub fn get_type<'a>(&'a self, name: &str) -> Option<&'a Type> {
        let c_name = CString::new(name).unwrap();
        let ty = unsafe { core::LLVMGetTypeByName(self.into(), c_name.as_ptr()) };
        if ty.is_null() {
            None
        } else {
            Some(ty.into())
        }
    }
    /// Clone this module
    pub fn clone<'a>(&'a self) -> CBox<'a, Module> {
        CBox::new(unsafe { core::LLVMCloneModule(self.into()) })
    }

    /// Get the target data of this module
    pub fn get_target(&self) -> &str {
        unsafe {
            let target = core::LLVMGetTarget(self.into());
            util::to_str(target as *mut c_char)
        }
    }

    /// Set the target data of this module
    pub fn set_target(&mut self, target: &str) {
        let c_target = CString::new(target).unwrap();
        unsafe { core::LLVMSetTarget(self.into(), c_target.as_ptr()) }
    }
}
impl<'a> IntoIterator for &'a Module {
    type Item = &'a Function;
    type IntoIter = Functions<'a>;
    /// Iterate through the functions in the module
    fn into_iter(self) -> Functions<'a> {
        Functions {
            value: unsafe { core::LLVMGetFirstFunction(self.into()) },
            marker: PhantomData
        }
    }
}
get_context!(Module, LLVMGetModuleContext);
to_str!(Module, LLVMPrintModuleToString);
dispose!(Module, LLVMModule, core::LLVMDisposeModule);
#[derive(Copy, Clone)]
pub struct Functions<'a> {
    value: LLVMValueRef,
    marker: PhantomData<&'a ()>
}
impl<'a> Iterator for Functions<'a> {
    type Item = &'a Function;
    fn next(&mut self) -> Option<&'a Function> {
        if self.value.is_null() {
            None
        } else {
            let c_next = unsafe { core::LLVMGetNextFunction(self.value) };
            self.value = c_next;
            if c_next.is_null() {
                None
            } else {
                Some(c_next.into())
            }
        }
    }
}
<commit_msg>Use utility functions where applicable to reduce code duplication<commit_after>use libc::c_char;
use ffi::prelude::{LLVMValueRef, LLVMModuleRef};
use ffi::{core, LLVMModule};
use ffi::bit_writer as writer;
use ffi::bit_reader as reader;
use cbox::CBox;
use std::ffi::CString;
use std::iter::{Iterator, IntoIterator};
use std::{fmt, mem};
use std::marker::PhantomData;
use buffer::MemoryBuffer;
use context::{Context, GetContext};
use value::Function;
use ty::Type;
use util;

/// Represents a translation unit
///
/// This is attached to the lifetime of the context that constructs it
pub struct Module;
native_ref!(&Module = LLVMModuleRef);
impl Module {
    /// Create a new module in the context given with the name given
    ///
    /// The lifetime of the module will match the lifetime of the context
    /// you instance it in because the context contains it
    ///
    /// ```rust
    /// use llvm::*;
    /// let context = Context::new();
    /// let module = Module::new("name", &context);
    /// println!("{:?}", module)
    /// ```
    pub fn new<'a>(name: &str, context: &'a Context) -> CBox<'a, Module> {
        let c_name = CString::new(name).unwrap();
        unsafe { CBox::new(core::LLVMModuleCreateWithNameInContext(c_name.as_ptr(), context.into())) }
    }
    /// Parse this bitcode file into a module
    pub fn parse_bitcode<'a, 'b>(context: &'a Context, path: &'b str) -> Result<CBox<'b, Module>, CBox<'b, str>> {
        unsafe {
            let mut out = mem::uninitialized();
            let mut err = mem::uninitialized();
            let buf = try!(MemoryBuffer::new_from_file(path));
            if reader::LLVMParseBitcodeInContext(context.into(), (&*buf).into(), &mut out, &mut err) == 1 {
                Err(CBox::new(err))
            } else {
                Ok(CBox::new(out))
            }
        }
    }
    /// Write this module's bitcode to the path given
    pub fn write_bitcode(&self, path: &str) {
        util::with_cstr(path, |cpath| unsafe {
            if writer::LLVMWriteBitcodeToFile(self.into(), cpath) != 0 {
                panic!("failed to write bitcode to file {}", path)
            }
        })
    }
    /// Add a function to the module with the name given
    pub fn add_function<'a>(&'a self, name: &str, sig: &'a Type) -> &'a mut Function {
        let c_name = CString::new(name).unwrap();
        unsafe { core::LLVMAddFunction(self.into(), c_name.as_ptr(), sig.into()) }.into()
    }
    /// Returns the function with the name given if it exists
    pub fn get_function<'a>(&'a self, name: &str) -> Option<&'a Function> {
        let c_name = CString::new(name).unwrap();
        unsafe {
            let ty = core::LLVMGetNamedFunction(self.into(), c_name.as_ptr());
            util::ptr_to_null(ty)
        }
    }
    /// Returns the type with the name given if it exists
    pub fn get_type<'a>(&'a self, name: &str) -> Option<&'a Type> {
        let c_name = CString::new(name).unwrap();
        unsafe {
            let ty = core::LLVMGetTypeByName(self.into(), c_name.as_ptr());
            util::ptr_to_null(ty)
        }
    }
    /// Clone this module
    pub fn clone<'a>(&'a self) -> CBox<'a, Module> {
        CBox::new(unsafe { core::LLVMCloneModule(self.into()) })
    }

    /// Get the target data of this module
    pub fn get_target(&self) -> &str {
        unsafe {
            let target = core::LLVMGetTarget(self.into());
            util::to_str(target as *mut c_char)
        }
    }

    /// Set the target data of this module
    pub fn set_target(&mut self, target: &str) {
        let c_target = CString::new(target).unwrap();
        unsafe { core::LLVMSetTarget(self.into(), c_target.as_ptr()) }
    }
}
impl<'a> IntoIterator for &'a Module {
    type Item = &'a Function;
    type IntoIter = Functions<'a>;
    /// Iterate through the functions in the module
    fn into_iter(self) -> Functions<'a> {
        Functions {
            value: unsafe { core::LLVMGetFirstFunction(self.into()) },
            marker: PhantomData
        }
    }
}
get_context!(Module, LLVMGetModuleContext);
to_str!(Module, LLVMPrintModuleToString);
dispose!(Module, LLVMModule, core::LLVMDisposeModule);
#[derive(Copy, Clone)]
pub struct Functions<'a> {
    value: LLVMValueRef,
    marker: PhantomData<&'a ()>
}
impl<'a> Iterator for Functions<'a> {
    type Item = &'a Function;
    fn next(&mut self) -> Option<&'a Function> {
        if self.value.is_null() {
            None
        } else {
            let c_next = unsafe { core::LLVMGetNextFunction(self.value) };
            self.value = c_next;
            Some(self.value.into())
        }
    }
}
<|endoftext|>