<commit_before>use std::iter::FromIterator;
use std::slice::Iter;
use std::ascii::AsciiExt;
use std::path::{Path, PathBuf};
use std::sync::Arc;

use ::compiler::{Arg, CommandInfo, CompilationArgs, CompilationTask, InputKind, OutputKind, Scope};

enum ParamValue<T> {
    None,
    Single(T),
    Many(Vec<T>),
}

pub fn create_tasks(command: CommandInfo, args: &[String]) -> Result<Vec<CompilationTask>, String> {
    if args.iter()
        .find(|v| {
            match v as &str {
                "--analyze" => true,
                _ => false,
            }
        })
        .is_some() {
        // Support only compilation steps
        return Ok(Vec::new());
    }
    if args.iter()
        .find(|v| {
            match v as &str {
                "-c" => true,
                _ => false,
            }
        })
        .is_none() {
        // Support only compilation steps
        return Ok(Vec::new());
    }
    let parsed_args = try!(parse_arguments(args));
    // Source file name.
    let input_sources: Vec<PathBuf> = parsed_args.iter()
        .filter_map(|arg| {
            match arg {
                &Arg::Input { ref kind, ref file, .. } if *kind == InputKind::Source => {
                    Some(Path::new(file).to_path_buf())
                }
                _ => None,
            }
        })
        .collect();
    if input_sources.len() == 0 {
        return Err(format!("Can't find source file path."));
    }
    // Precompiled header file name.
    let input_precompiled = match find_param(&parsed_args, |arg: &Arg| -> Option<PathBuf> {
        match arg {
            &Arg::Input { ref kind, ref file, .. } if *kind == InputKind::Precompiled => {
                Some(Path::new(file).to_path_buf())
            }
            _ => None,
        }
    }) {
        ParamValue::None => None,
        ParamValue::Single(v) => Some(v),
        ParamValue::Many(v) => {
            return Err(format!("Found too many precompiled header files: {:?}", v));
        }
    };
    // Precompiled header file name.
    let marker_precompiled = parsed_args.iter()
        .filter_map(|arg| {
            match arg {
                &Arg::Param { ref flag, ref value, .. } if *flag == "include" => Some(value.clone()),
                _ => None,
            }
        })
        .next();
    // Output object file name.
    let output_object = match find_param(&parsed_args, |arg: &Arg| -> Option<PathBuf> {
        match arg {
            &Arg::Output { ref kind, ref file, .. } if *kind == OutputKind::Object => {
                Some(Path::new(file).to_path_buf())
            }
            _ => None,
        }
    }) {
        ParamValue::None => None,
        ParamValue::Single(v) => {
            if input_sources.len() > 1 {
                return Err("Cannot specify -o when generating multiple output files".to_string());
            }
            Some(v)
        }
        ParamValue::Many(v) => {
            return Err(format!("Found too many output object files: {:?}", v));
        }
    };
    // Language
    let language: Option<String> = match find_param(&parsed_args, |arg: &Arg| -> Option<String> {
        match arg {
            &Arg::Param { ref flag, ref value, .. } if *flag == "x" => Some(value.clone()),
            _ => None,
        }
    }) {
        ParamValue::None => None,
        ParamValue::Single(v) => {
            match &v[..] {
                "c" | "c++" => Some(v.to_string()),
                "c-header" | "c++-header" => {
                    // Precompiled headers must build locally
                    return Ok(Vec::new());
                }
                _ => {
                    return Err(format!("Unknown source language type: {}", v));
                }
            }
        }
        ParamValue::Many(v) => {
            return Err(format!("Found too many output object files: {:?}", v));
        }
    };
    let shared = Arc::new(CompilationArgs {
        command: command,
        args: parsed_args,
        output_precompiled: None,
        marker_precompiled: marker_precompiled,
        input_precompiled: input_precompiled,
    });
    input_sources.into_iter()
        .map(|source| {
            Ok(CompilationTask {
                shared: shared.clone(),
                language: try!(language.as_ref()
                    .map_or_else(|| {
                        source.extension()
                            .and_then(|ext| match ext.to_str() {
                                Some(e) if e.eq_ignore_ascii_case("cpp") => Some("c++"),
                                Some(e) if e.eq_ignore_ascii_case("c") => Some("c"),
                                Some(e) if e.eq_ignore_ascii_case("hpp") => Some("c++-header"),
                                Some(e) if e.eq_ignore_ascii_case("h") => Some("c-header"),
                                _ => None,
                            })
                            .map(|ext| ext.to_string())
                    },
                                 |lang| Some(lang.clone()))
                    .ok_or_else(|| {
                        format!("Can't detect file language by extension: {}",
                                source.as_os_str().to_string_lossy())
                    })),
                output_object: output_object.as_ref().map_or_else(|| source.with_extension("o"), |path| path.clone()),
                input_source: source,
            })
        })
        .collect()
}

fn find_param<T, R, F: Fn(&T) -> Option<R>>(args: &Vec<T>, filter: F) -> ParamValue<R> {
    let mut found = Vec::from_iter(args.iter().filter_map(filter));
    match found.len() {
        0 => ParamValue::None,
        1 => ParamValue::Single(found.pop().unwrap()),
        _ => ParamValue::Many(found),
    }
}

fn parse_arguments(args: &[String]) -> Result<Vec<Arg>, String> {
    let mut result: Vec<Arg> = Vec::new();
    let mut errors: Vec<String> = Vec::new();
    let mut iter = args.iter();
    loop {
        match parse_argument(&mut iter) {
            Some(parse_result) => {
                match parse_result {
                    Ok(arg) => {
                        result.push(arg);
                    }
                    Err(e) => {
                        errors.push(e);
                    }
                }
            }
            None => {
                break;
            }
        }
    }
    if errors.len() > 0 {
        return Err(format!("Found unknown command line arguments: {:?}", errors));
    }
    Ok(result)
}

fn parse_argument(iter: &mut Iter<String>) -> Option<Result<Arg, String>> {
    match iter.next() {
        Some(arg) => {
            Some(if arg.starts_with("--") {
                let (key, value) = match arg.find("=") {
                    Some(position) => (&arg[1..position], arg[position + 1..].to_string()),
                    None => {
                        match iter.next() {
                            Some(v) => (&arg[1..], v.clone()),
                            _ => {
                                return Some(Err(arg.to_string()));
                            }
                        }
                    }
                };
                match &key[1..] {
                    "sysroot" => Ok(Arg::flag(Scope::Shared, key.to_string() + "=" + &value)),
                    _ => Err(key.to_string()),
                }
            } else if has_param_prefix(arg) {
                let flag = &arg[1..];
                match is_spaceable_param(flag) {
                    Some((prefix, scope, next_flag)) => {
                        let value = match flag == prefix {
                            true => {
                                match iter.next() {
                                    Some(v) if next_flag == has_param_prefix(v) => v.to_string(),
                                    _ => {
                                        return Some(Err(arg.to_string()));
                                    }
                                }
                            }
                            false => flag[prefix.len()..].to_string(),
                        };
                        match flag {
                            "o" => Ok(Arg::output(OutputKind::Object, prefix, value)),
                            _ => Ok(Arg::param(scope, prefix, value)),
                        }
                    }
                    None => {
                        match flag {
                            "c" => Ok(Arg::flag(Scope::Ignore, flag)),
                            "pipe" => Ok(Arg::flag(Scope::Shared, flag)),
                            s if s.starts_with("f") => Ok(Arg::flag(Scope::Shared, flag)),
                            s if s.starts_with("g") => Ok(Arg::flag(Scope::Shared, flag)),
                            s if s.starts_with("O") => Ok(Arg::flag(Scope::Shared, flag)),
                            s if s.starts_with("W") => Ok(Arg::flag(Scope::Shared, flag)),
                            s if s.starts_with("m") => Ok(Arg::flag(Scope::Shared, flag)),
                            s if s.starts_with("std=") => Ok(Arg::flag(Scope::Shared, flag)),
                            _ => Err(arg.to_string()),
                        }
                    }
                }
            } else {
                Ok(Arg::input(InputKind::Source, String::new(), arg.to_string()))
            })
        }
        None => None,
    }
}

fn is_spaceable_param(flag: &str) -> Option<(&str, Scope, bool)> {
    match flag {
        "include" | "include-pch" => Some((flag, Scope::Preprocessor, false)),
        "target" => Some((flag, Scope::Shared, false)),
        _ => {
            for prefix in ["D", "o"].iter() {
                if flag.starts_with(*prefix) {
                    return Some((*prefix, Scope::Shared, false));
                }
            }
            for prefix in ["x"].iter() {
                if flag.starts_with(*prefix) {
                    return Some((*prefix, Scope::Ignore, false));
                }
            }
            for prefix in ["I"].iter() {
                if flag.starts_with(*prefix) {
                    return Some((*prefix, Scope::Preprocessor, false));
                }
            }
            None
        }
    }
}

fn has_param_prefix(arg: &String) -> bool {
    arg.starts_with("-")
}

#[test]
fn test_parse_argument_precompile() {
    let args = Vec::from_iter("-x c++-header -pipe -Wall -Werror -funwind-tables -Wsequence-point -mmmx -msse -msse2 \
                               -fno-math-errno -fno-rtti -g3 -gdwarf-3 -O2 -D_LINUX64 -IEngine/Source \
                               -IDeveloper/Public -I Runtime/Core/Private -D IS_PROGRAM=1 -D UNICODE \
                               -DIS_MONOLITHIC=1 -std=c++11 -o CorePrivatePCH.h.pch CorePrivatePCH.h"
        .split(" ")
        .map(|x| x.to_string()));
    assert_eq!(parse_arguments(&args).unwrap(),
               [Arg::param(Scope::Ignore, "x", "c++-header"),
                Arg::flag(Scope::Shared, "pipe"),
                Arg::flag(Scope::Shared, "Wall"),
                Arg::flag(Scope::Shared, "Werror"),
                Arg::flag(Scope::Shared, "funwind-tables"),
                Arg::flag(Scope::Shared, "Wsequence-point"),
                Arg::flag(Scope::Shared, "mmmx"),
                Arg::flag(Scope::Shared, "msse"),
                Arg::flag(Scope::Shared, "msse2"),
                Arg::flag(Scope::Shared, "fno-math-errno"),
                Arg::flag(Scope::Shared, "fno-rtti"),
                Arg::flag(Scope::Shared, "g3"),
                Arg::flag(Scope::Shared, "gdwarf-3"),
                Arg::flag(Scope::Shared, "O2"),
                Arg::param(Scope::Shared, "D", "_LINUX64"),
                Arg::param(Scope::Preprocessor, "I", "Engine/Source"),
                Arg::param(Scope::Preprocessor, "I", "Developer/Public"),
                Arg::param(Scope::Preprocessor, "I", "Runtime/Core/Private"),
                Arg::param(Scope::Shared, "D", "IS_PROGRAM=1"),
                Arg::param(Scope::Shared, "D", "UNICODE"),
                Arg::param(Scope::Shared, "D", "IS_MONOLITHIC=1"),
                Arg::flag(Scope::Shared, "std=c++11"),
                Arg::output(OutputKind::Object, "o", "CorePrivatePCH.h.pch"),
                Arg::input(InputKind::Source, "", "CorePrivatePCH.h")])
}

#[test]
fn test_parse_argument_compile() {
    let args = Vec::from_iter("-c -include-pch CorePrivatePCH.h.pch -pipe -Wall -Werror -funwind-tables \
                               -Wsequence-point -mmmx -msse -msse2 -fno-math-errno -fno-rtti -g3 -gdwarf-3 -O2 -D \
                               IS_PROGRAM=1 -D UNICODE -DIS_MONOLITHIC=1 -x c++ -std=c++11 -include CorePrivatePCH.h \
                               -o Module.Core.cpp.o Module.Core.cpp"
        .split(" ")
        .map(|x| x.to_string()));
    assert_eq!(parse_arguments(&args).unwrap(),
               [Arg::flag(Scope::Ignore, "c"),
                Arg::param(Scope::Preprocessor, "include-pch", "CorePrivatePCH.h.pch"),
                Arg::flag(Scope::Shared, "pipe"),
                Arg::flag(Scope::Shared, "Wall"),
                Arg::flag(Scope::Shared, "Werror"),
                Arg::flag(Scope::Shared, "funwind-tables"),
                Arg::flag(Scope::Shared, "Wsequence-point"),
                Arg::flag(Scope::Shared, "mmmx"),
                Arg::flag(Scope::Shared, "msse"),
                Arg::flag(Scope::Shared, "msse2"),
                Arg::flag(Scope::Shared, "fno-math-errno"),
                Arg::flag(Scope::Shared, "fno-rtti"),
                Arg::flag(Scope::Shared, "g3"),
                Arg::flag(Scope::Shared, "gdwarf-3"),
                Arg::flag(Scope::Shared, "O2"),
                Arg::param(Scope::Shared, "D", "IS_PROGRAM=1"),
                Arg::param(Scope::Shared, "D", "UNICODE"),
                Arg::param(Scope::Shared, "D", "IS_MONOLITHIC=1"),
                Arg::param(Scope::Ignore, "x", "c++"),
                Arg::flag(Scope::Shared, "std=c++11"),
                Arg::param(Scope::Preprocessor, "include", "CorePrivatePCH.h"),
                Arg::output(OutputKind::Object, "o", "Module.Core.cpp.o"),
                Arg::input(InputKind::Source, "", "Module.Core.cpp")])
}
<commit_msg>Add -nostdinc++ to whitelist (fixes #17)<commit_after>use std::iter::FromIterator;
use std::slice::Iter;
use std::ascii::AsciiExt;
use std::path::{Path, PathBuf};
use std::sync::Arc;

use ::compiler::{Arg, CommandInfo, CompilationArgs, CompilationTask, InputKind, OutputKind, Scope};

enum ParamValue<T> {
    None,
    Single(T),
    Many(Vec<T>),
}

pub fn create_tasks(command: CommandInfo, args: &[String]) -> Result<Vec<CompilationTask>, String> {
    if args.iter()
        .find(|v| {
            match v as &str {
                "--analyze" => true,
                _ => false,
            }
        })
        .is_some() {
        // Support only compilation steps
        return Ok(Vec::new());
    }
    if args.iter()
        .find(|v| {
            match v as &str {
                "-c" => true,
                _ => false,
            }
        })
        .is_none() {
        // Support only compilation steps
        return Ok(Vec::new());
    }
    let parsed_args = try!(parse_arguments(args));
    // Source file name.
    let input_sources: Vec<PathBuf> = parsed_args.iter()
        .filter_map(|arg| {
            match arg {
                &Arg::Input { ref kind, ref file, .. } if *kind == InputKind::Source => {
                    Some(Path::new(file).to_path_buf())
                }
                _ => None,
            }
        })
        .collect();
    if input_sources.len() == 0 {
        return Err(format!("Can't find source file path."));
    }
    // Precompiled header file name.
    let input_precompiled = match find_param(&parsed_args, |arg: &Arg| -> Option<PathBuf> {
        match arg {
            &Arg::Input { ref kind, ref file, .. } if *kind == InputKind::Precompiled => {
                Some(Path::new(file).to_path_buf())
            }
            _ => None,
        }
    }) {
        ParamValue::None => None,
        ParamValue::Single(v) => Some(v),
        ParamValue::Many(v) => {
            return Err(format!("Found too many precompiled header files: {:?}", v));
        }
    };
    // Precompiled header file name.
    let marker_precompiled = parsed_args.iter()
        .filter_map(|arg| {
            match arg {
                &Arg::Param { ref flag, ref value, .. } if *flag == "include" => Some(value.clone()),
                _ => None,
            }
        })
        .next();
    // Output object file name.
    let output_object = match find_param(&parsed_args, |arg: &Arg| -> Option<PathBuf> {
        match arg {
            &Arg::Output { ref kind, ref file, .. } if *kind == OutputKind::Object => {
                Some(Path::new(file).to_path_buf())
            }
            _ => None,
        }
    }) {
        ParamValue::None => None,
        ParamValue::Single(v) => {
            if input_sources.len() > 1 {
                return Err("Cannot specify -o when generating multiple output files".to_string());
            }
            Some(v)
        }
        ParamValue::Many(v) => {
            return Err(format!("Found too many output object files: {:?}", v));
        }
    };
    // Language
    let language: Option<String> = match find_param(&parsed_args, |arg: &Arg| -> Option<String> {
        match arg {
            &Arg::Param { ref flag, ref value, .. } if *flag == "x" => Some(value.clone()),
            _ => None,
        }
    }) {
        ParamValue::None => None,
        ParamValue::Single(v) => {
            match &v[..] {
                "c" | "c++" => Some(v.to_string()),
                "c-header" | "c++-header" => {
                    // Precompiled headers must build locally
                    return Ok(Vec::new());
                }
                _ => {
                    return Err(format!("Unknown source language type: {}", v));
                }
            }
        }
        ParamValue::Many(v) => {
            return Err(format!("Found too many output object files: {:?}", v));
        }
    };
    let shared = Arc::new(CompilationArgs {
        command: command,
        args: parsed_args,
        output_precompiled: None,
        marker_precompiled: marker_precompiled,
        input_precompiled: input_precompiled,
    });
    input_sources.into_iter()
        .map(|source| {
            Ok(CompilationTask {
                shared: shared.clone(),
                language: try!(language.as_ref()
                    .map_or_else(|| {
                        source.extension()
                            .and_then(|ext| match ext.to_str() {
                                Some(e) if e.eq_ignore_ascii_case("cpp") => Some("c++"),
                                Some(e) if e.eq_ignore_ascii_case("c") => Some("c"),
                                Some(e) if e.eq_ignore_ascii_case("hpp") => Some("c++-header"),
                                Some(e) if e.eq_ignore_ascii_case("h") => Some("c-header"),
                                _ => None,
                            })
                            .map(|ext| ext.to_string())
                    },
                                 |lang| Some(lang.clone()))
                    .ok_or_else(|| {
                        format!("Can't detect file language by extension: {}",
                                source.as_os_str().to_string_lossy())
                    })),
                output_object: output_object.as_ref().map_or_else(|| source.with_extension("o"), |path| path.clone()),
                input_source: source,
            })
        })
        .collect()
}

fn find_param<T, R, F: Fn(&T) -> Option<R>>(args: &Vec<T>, filter: F) -> ParamValue<R> {
    let mut found = Vec::from_iter(args.iter().filter_map(filter));
    match found.len() {
        0 => ParamValue::None,
        1 => ParamValue::Single(found.pop().unwrap()),
        _ => ParamValue::Many(found),
    }
}

fn parse_arguments(args: &[String]) -> Result<Vec<Arg>, String> {
    let mut result: Vec<Arg> = Vec::new();
    let mut errors: Vec<String> = Vec::new();
    let mut iter = args.iter();
    loop {
        match parse_argument(&mut iter) {
            Some(parse_result) => {
                match parse_result {
                    Ok(arg) => {
                        result.push(arg);
                    }
                    Err(e) => {
                        errors.push(e);
                    }
                }
            }
            None => {
                break;
            }
        }
    }
    if errors.len() > 0 {
        return Err(format!("Found unknown command line arguments: {:?}", errors));
    }
    Ok(result)
}

fn parse_argument(iter: &mut Iter<String>) -> Option<Result<Arg, String>> {
    match iter.next() {
        Some(arg) => {
            Some(if arg.starts_with("--") {
                let (key, value) = match arg.find("=") {
                    Some(position) => (&arg[1..position], arg[position + 1..].to_string()),
                    None => {
                        match iter.next() {
                            Some(v) => (&arg[1..], v.clone()),
                            _ => {
                                return Some(Err(arg.to_string()));
                            }
                        }
                    }
                };
                match &key[1..] {
                    "sysroot" => Ok(Arg::flag(Scope::Shared, key.to_string() + "=" + &value)),
                    _ => Err(key.to_string()),
                }
            } else if has_param_prefix(arg) {
                let flag = &arg[1..];
                match is_spaceable_param(flag) {
                    Some((prefix, scope, next_flag)) => {
                        let value = match flag == prefix {
                            true => {
                                match iter.next() {
                                    Some(v) if next_flag == has_param_prefix(v) => v.to_string(),
                                    _ => {
                                        return Some(Err(arg.to_string()));
                                    }
                                }
                            }
                            false => flag[prefix.len()..].to_string(),
                        };
                        match flag {
                            "o" => Ok(Arg::output(OutputKind::Object, prefix, value)),
                            _ => Ok(Arg::param(scope, prefix, value)),
                        }
                    }
                    None => {
                        match flag {
                            "c" => Ok(Arg::flag(Scope::Ignore, flag)),
                            "pipe" => Ok(Arg::flag(Scope::Shared, flag)),
                            s if s.starts_with("f") => Ok(Arg::flag(Scope::Shared, flag)),
                            s if s.starts_with("g") => Ok(Arg::flag(Scope::Shared, flag)),
                            s if s.starts_with("O") => Ok(Arg::flag(Scope::Shared, flag)),
                            s if s.starts_with("W") => Ok(Arg::flag(Scope::Shared, flag)),
                            s if s.starts_with("m") => Ok(Arg::flag(Scope::Shared, flag)),
                            s if s.starts_with("std=") => Ok(Arg::flag(Scope::Shared, flag)),
                            _ => Err(arg.to_string()),
                        }
                    }
                }
            } else {
                Ok(Arg::input(InputKind::Source, String::new(), arg.to_string()))
            })
        }
        None => None,
    }
}

fn is_spaceable_param(flag: &str) -> Option<(&str, Scope, bool)> {
    match flag {
        "include" | "include-pch" => Some((flag, Scope::Preprocessor, false)),
        "target" => Some((flag, Scope::Shared, false)),
        _ => {
            for prefix in ["D", "o"].iter() {
                if flag.starts_with(*prefix) {
                    return Some((*prefix, Scope::Shared, false));
                }
            }
            for prefix in ["x"].iter() {
                if flag.starts_with(*prefix) {
                    return Some((*prefix, Scope::Ignore, false));
                }
            }
            for prefix in ["I"].iter() {
                if flag.starts_with(*prefix) {
                    return Some((*prefix, Scope::Preprocessor, false));
                }
            }
            None
        }
    }
}

fn has_param_prefix(arg: &String) -> bool {
    arg.starts_with("-")
}

#[test]
fn test_parse_argument_precompile() {
    let args = Vec::from_iter("-x c++-header -pipe -Wall -Werror -funwind-tables -Wsequence-point -mmmx -msse -msse2 \
                               -fno-math-errno -fno-rtti -g3 -gdwarf-3 -O2 -D_LINUX64 -IEngine/Source \
                               -IDeveloper/Public -I Runtime/Core/Private -D IS_PROGRAM=1 -D UNICODE \
                               -DIS_MONOLITHIC=1 -std=c++11 -o CorePrivatePCH.h.pch CorePrivatePCH.h"
        .split(" ")
        .map(|x| x.to_string()));
    assert_eq!(parse_arguments(&args).unwrap(),
               [Arg::param(Scope::Ignore, "x", "c++-header"),
                Arg::flag(Scope::Shared, "pipe"),
                Arg::flag(Scope::Shared, "Wall"),
                Arg::flag(Scope::Shared, "Werror"),
                Arg::flag(Scope::Shared, "funwind-tables"),
                Arg::flag(Scope::Shared, "Wsequence-point"),
                Arg::flag(Scope::Shared, "mmmx"),
                Arg::flag(Scope::Shared, "msse"),
                Arg::flag(Scope::Shared, "msse2"),
                Arg::flag(Scope::Shared, "fno-math-errno"),
                Arg::flag(Scope::Shared, "fno-rtti"),
                Arg::flag(Scope::Shared, "g3"),
                Arg::flag(Scope::Shared, "gdwarf-3"),
                Arg::flag(Scope::Shared, "O2"),
                Arg::param(Scope::Shared, "D", "_LINUX64"),
                Arg::param(Scope::Preprocessor, "I", "Engine/Source"),
                Arg::param(Scope::Preprocessor, "I", "Developer/Public"),
                Arg::param(Scope::Preprocessor, "I", "Runtime/Core/Private"),
                Arg::param(Scope::Shared, "D", "IS_PROGRAM=1"),
                Arg::param(Scope::Shared, "D", "UNICODE"),
                Arg::param(Scope::Shared, "D", "IS_MONOLITHIC=1"),
                Arg::flag(Scope::Shared, "std=c++11"),
                Arg::output(OutputKind::Object, "o", "CorePrivatePCH.h.pch"),
                Arg::input(InputKind::Source, "", "CorePrivatePCH.h")])
}

#[test]
fn test_parse_argument_compile() {
    let args = Vec::from_iter("-c -include-pch CorePrivatePCH.h.pch -pipe -Wall -Werror -funwind-tables \
                               -Wsequence-point -mmmx -msse -msse2 -fno-math-errno -fno-rtti -g3 -gdwarf-3 -O2 -D \
                               IS_PROGRAM=1 -D UNICODE -DIS_MONOLITHIC=1 -x c++ -std=c++11 -include CorePrivatePCH.h \
                               -o Module.Core.cpp.o Module.Core.cpp"
        .split(" ")
        .map(|x| x.to_string()));
    assert_eq!(parse_arguments(&args).unwrap(),
               [Arg::flag(Scope::Ignore, "c"),
                Arg::param(Scope::Preprocessor, "include-pch", "CorePrivatePCH.h.pch"),
                Arg::flag(Scope::Shared, "pipe"),
                Arg::flag(Scope::Shared, "Wall"),
                Arg::flag(Scope::Shared, "Werror"),
                Arg::flag(Scope::Shared, "funwind-tables"),
                Arg::flag(Scope::Shared, "Wsequence-point"),
                Arg::flag(Scope::Shared, "mmmx"),
                Arg::flag(Scope::Shared, "msse"),
                Arg::flag(Scope::Shared, "msse2"),
                Arg::flag(Scope::Shared, "nostdinc++"),
                Arg::flag(Scope::Shared, "fno-math-errno"),
                Arg::flag(Scope::Shared, "fno-rtti"),
                Arg::flag(Scope::Shared, "g3"),
                Arg::flag(Scope::Shared, "gdwarf-3"),
                Arg::flag(Scope::Shared, "O2"),
                Arg::param(Scope::Shared, "D", "IS_PROGRAM=1"),
                Arg::param(Scope::Shared, "D", "UNICODE"),
                Arg::param(Scope::Shared, "D", "IS_MONOLITHIC=1"),
                Arg::param(Scope::Ignore, "x", "c++"),
                Arg::flag(Scope::Shared, "std=c++11"),
                Arg::param(Scope::Preprocessor, "include", "CorePrivatePCH.h"),
                Arg::output(OutputKind::Object, "o", "Module.Core.cpp.o"),
                Arg::input(InputKind::Source, "", "Module.Core.cpp")])
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017 Sreejith Krishnan R
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

mod mi;                         pub use self::mi::*;
mod mn;                         pub use self::mn::*;

use std::rc::Rc;

use ::props::{MathVariant, MathSize, Directionality};
use ::elements::{Element, PresentationPrivate, Property, PropertyCalculator};
use ::layout::{TokenLayout};
use ::platform::Context;

pub struct SpecifiedTokenProps {
    pub(crate) text: Rc<String>,

    pub(crate) math_variant: Option<MathVariant>,
    pub(crate) math_size: Option<MathSize>,
    pub(crate) dir: Option<Directionality>,
}

pub trait TokenPrivate<T: Element> : PresentationPrivate<T> {
    #[allow(const_err)]
    const PROP_MATH_VARIANT: Property<MathVariant, T> = Property::Specified {
        default:    || MathVariant::Normal,
        reader:     |s| s.math_variant()
    };

    #[allow(const_err)]
    const PROP_MATH_SIZE: Property<MathSize, T> = Property::Inherited {
        reader:     |i| i.math_size(),
        writer:     |v, fork| fork.math_size(v)
    };

    #[allow(const_err)]
    const PROP_DIR: Property<Directionality, T> = Property::Inherited {
        reader:     |i| i.dir(),
        writer:     |v, fork| fork.dir(v)
    };

    fn get_specified_token_props(&self) -> &SpecifiedTokenProps;
    fn get_specified_token_props_mut(&mut self) -> &mut SpecifiedTokenProps;

    fn layout_token_element(&self, context: &Context, calculator: &mut PropertyCalculator<T>) -> TokenLayout {
        let token_props = self.get_specified_token_props();

        let presentation_layout = self.layout_presentation(calculator);

        TokenLayout {
            text: token_props.text.clone(),
            math_variant: calculator.calculate(
                &Self::PROP_MATH_VARIANT, token_props.math_variant.as_ref()),
            math_size: presentation_layout.script_level.get_font_size(
                context,
                &calculator.calculate(
                    &Self::PROP_MATH_SIZE, token_props.math_size.as_ref())
            ),
            dir: calculator.calculate(&Self::PROP_DIR, token_props.dir.as_ref()),
            presentation_element: presentation_layout,
        }
    }
}

pub trait Token<T: Element> : TokenPrivate<T> {
    fn with_text<'a>(&'a mut self, text: String) -> &'a mut Self {
        self.get_specified_token_props_mut().text = Rc::new(text);
        self
    }

    fn get_text(&self) -> &str {
        &self.get_specified_token_props().text
    }

    fn with_math_variant<'a>(&'a mut self, variant: Option<MathVariant>) -> &'a mut Self {
        self.get_specified_token_props_mut().math_variant = variant;
        self
    }

    fn get_math_variant(&self) -> Option<&MathVariant> {
        self.get_specified_token_props().math_variant.as_ref()
    }

    fn with_math_size<'a>(&'a mut self, size: Option<MathSize>) -> &'a mut Self {
        self.get_specified_token_props_mut().math_size = size;
        self
    }

    fn get_math_size(&self) -> Option<&MathSize> {
        self.get_specified_token_props().math_size.as_ref()
    }

    fn with_dir<'a>(&'a mut self, dir: Option<Directionality>) -> &'a mut Self {
        self.get_specified_token_props_mut().dir = dir;
        self
    }

    fn get_dir(&self) -> Option<&Directionality> {
        self.get_specified_token_props().dir.as_ref()
    }
}<commit_msg>Mtext implementation<commit_after>/*
 * Copyright 2017 Sreejith Krishnan R
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

mod mi;                         pub use self::mi::*;
mod mn;                         pub use self::mn::*;
mod mtext;                      pub use self::mtext::*;

use std::rc::Rc;

use ::props::{MathVariant, MathSize, Directionality};
use ::elements::{Element, PresentationPrivate, Property, PropertyCalculator};
use ::layout::{TokenLayout};
use ::platform::Context;

pub struct SpecifiedTokenProps {
    pub(crate) text: Rc<String>,

    pub(crate) math_variant: Option<MathVariant>,
    pub(crate) math_size: Option<MathSize>,
    pub(crate) dir: Option<Directionality>,
}

pub trait TokenPrivate<T: Element> : PresentationPrivate<T> {
    #[allow(const_err)]
    const PROP_MATH_VARIANT: Property<MathVariant, T> = Property::Specified {
        default:    || MathVariant::Normal,
        reader:     |s| s.math_variant()
    };

    #[allow(const_err)]
    const PROP_MATH_SIZE: Property<MathSize, T> = Property::Inherited {
        reader:     |i| i.math_size(),
        writer:     |v, fork| fork.math_size(v)
    };

    #[allow(const_err)]
    const PROP_DIR: Property<Directionality, T> = Property::Inherited {
        reader:     |i| i.dir(),
        writer:     |v, fork| fork.dir(v)
    };

    fn get_specified_token_props(&self) -> &SpecifiedTokenProps;
    fn get_specified_token_props_mut(&mut self) -> &mut SpecifiedTokenProps;

    fn layout_token_element(&self, context: &Context, calculator: &mut PropertyCalculator<T>) -> TokenLayout {
        let token_props = self.get_specified_token_props();

        let presentation_layout = self.layout_presentation(calculator);

        TokenLayout {
            text: token_props.text.clone(),
            math_variant: calculator.calculate(
                &Self::PROP_MATH_VARIANT, token_props.math_variant.as_ref()),
            math_size: presentation_layout.script_level.get_font_size(
                context,
                &calculator.calculate(
                    &Self::PROP_MATH_SIZE, token_props.math_size.as_ref())
            ),
            dir: calculator.calculate(&Self::PROP_DIR, token_props.dir.as_ref()),
            presentation_element: presentation_layout,
        }
    }
}

pub trait Token<T: Element> : TokenPrivate<T> {
    fn with_text<'a>(&'a mut self, text: String) -> &'a mut Self {
        self.get_specified_token_props_mut().text = Rc::new(text);
        self
    }

    fn get_text(&self) -> &str {
        &self.get_specified_token_props().text
    }

    fn with_math_variant<'a>(&'a mut self, variant: Option<MathVariant>) -> &'a mut Self {
        self.get_specified_token_props_mut().math_variant = variant;
        self
    }

    fn get_math_variant(&self) -> Option<&MathVariant> {
        self.get_specified_token_props().math_variant.as_ref()
    }

    fn with_math_size<'a>(&'a mut self, size: Option<MathSize>) -> &'a mut Self {
        self.get_specified_token_props_mut().math_size = size;
        self
    }

    fn get_math_size(&self) -> Option<&MathSize> {
        self.get_specified_token_props().math_size.as_ref()
    }

    fn with_dir<'a>(&'a mut self, dir: Option<Directionality>) -> &'a mut Self {
        self.get_specified_token_props_mut().dir = dir;
        self
    }

    fn get_dir(&self) -> Option<&Directionality> {
        self.get_specified_token_props().dir.as_ref()
    }
}<|endoftext|>


<commit_before>//! Detecting diagnostic items.
//!
//! Diagnostic items are items that are not language-inherent, but can reasonably be expected to
//! exist for diagnostic purposes. This allows diagnostic authors to refer to specific items
//! directly, without having to guess module paths and crates.
//! Examples are:
//!
//! * Traits like `Debug`, that have no bearing on language semantics
//!
//! * Compiler internal types like `Ty` and `TyCtxt`

use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::def_id::{DefId, LOCAL_CRATE};
use rustc_span::symbol::{sym, Symbol};

struct DiagnosticItemCollector<'tcx> {
    // items from this crate
    items: FxHashMap<Symbol, DefId>,
    tcx: TyCtxt<'tcx>,
}

impl<'v, 'tcx> ItemLikeVisitor<'v> for DiagnosticItemCollector<'tcx> {
    fn visit_item(&mut self, item: &hir::Item<'_>) {
        self.observe_item(&item.attrs, item.hir_id);
    }

    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
        self.observe_item(&trait_item.attrs, trait_item.hir_id);
    }

    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
        self.observe_item(&impl_item.attrs, impl_item.hir_id);
    }
}

impl<'tcx> DiagnosticItemCollector<'tcx> {
    fn new(tcx: TyCtxt<'tcx>) -> DiagnosticItemCollector<'tcx> {
        DiagnosticItemCollector { tcx, items: Default::default() }
    }

    fn observe_item(&mut self, attrs: &[ast::Attribute], hir_id: hir::HirId) {
        if let Some(name) = extract(&self.tcx.sess, attrs) {
            let def_id = self.tcx.hir().local_def_id(hir_id);
            // insert into our table
            collect_item(self.tcx, &mut self.items, name, def_id.to_def_id());
        }
    }
}

fn collect_item(
    tcx: TyCtxt<'_>,
    items: &mut FxHashMap<Symbol, DefId>,
    name: Symbol,
    item_def_id: DefId,
) {
    // Check for duplicates.
    if let Some(original_def_id) = items.insert(name, item_def_id) {
        if original_def_id != item_def_id {
            let mut err = match tcx.hir().span_if_local(item_def_id) {
                Some(span) => tcx.sess.struct_span_err(
                    span,
                    &format!("duplicate diagnostic item found: `{}`.", name),
                ),
                None => tcx.sess.struct_err(&format!(
                    "duplicate diagnostic item in crate `{}`: `{}`.",
                    tcx.crate_name(item_def_id.krate),
                    name
                )),
            };
            if let Some(span) = tcx.hir().span_if_local(original_def_id) {
                err.span_note(span, "the diagnostic item is first defined here");
            } else {
                err.note(&format!(
                    "the diagnostic item is first defined in crate `{}`.",
                    tcx.crate_name(original_def_id.krate)
                ));
            }
            err.emit();
        }
    }
}

/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.
fn extract(sess: &Session, attrs: &[ast::Attribute]) -> Option<Symbol> {
    attrs.iter().find_map(|attr| {
        if sess.check_name(attr, sym::rustc_diagnostic_item) { attr.value_str() } else { None }
    })
}

/// Traverse and collect the diagnostic items in the current
fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> {
    // Initialize the collector.
    let mut collector = DiagnosticItemCollector::new(tcx);

    // Collect diagnostic items in this crate.
    tcx.hir().krate().visit_all_item_likes(&mut collector);
    // FIXME(visit_all_item_likes): Foreign items are not visited
    // here, so we have to manually look at them for now.
    for (_, foreign_module) in tcx.foreign_modules(LOCAL_CRATE).iter() {
        for &foreign_item in foreign_module.foreign_items.iter() {
            match tcx.hir().get(tcx.hir().local_def_id_to_hir_id(foreign_item.expect_local())) {
                hir::Node::ForeignItem(item) => {
                    collector.observe_item(item.attrs, item.hir_id);
                }
                item => bug!("unexpected foreign item {:?}", item),
            }
        }
    }

    collector.items
}

/// Traverse and collect all the diagnostic items in all crates.
fn collect_all<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> {
    // Initialize the collector.
    let mut collector = FxHashMap::default();

    // Collect diagnostic items in other crates.
    for &cnum in tcx.crates().iter().chain(std::iter::once(&LOCAL_CRATE)) {
        for (&name, &def_id) in tcx.diagnostic_items(cnum).iter() {
            collect_item(tcx, &mut collector, name, def_id);
        }
    }

    collector
}

pub fn provide(providers: &mut Providers) {
    providers.diagnostic_items = |tcx, id| {
        assert_eq!(id, LOCAL_CRATE);
        collect(tcx)
    };
    providers.all_diagnostic_items = |tcx, id| {
        assert_eq!(id, LOCAL_CRATE);
        collect_all(tcx)
    };
}
<commit_msg>Allow #[rustc_diagnostic_item] on macros.<commit_after>//! Detecting diagnostic items.
//!
//! Diagnostic items are items that are not language-inherent, but can reasonably be expected to
//! exist for diagnostic purposes. This allows diagnostic authors to refer to specific items
//! directly, without having to guess module paths and crates.
//! Examples are:
//!
//! * Traits like `Debug`, that have no bearing on language semantics
//!
//! * Compiler internal types like `Ty` and `TyCtxt`

use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::def_id::{DefId, LOCAL_CRATE};
use rustc_span::symbol::{sym, Symbol};

struct DiagnosticItemCollector<'tcx> {
    // items from this crate
    items: FxHashMap<Symbol, DefId>,
    tcx: TyCtxt<'tcx>,
}

impl<'v, 'tcx> ItemLikeVisitor<'v> for DiagnosticItemCollector<'tcx> {
    fn visit_item(&mut self, item: &hir::Item<'_>) {
        self.observe_item(&item.attrs, item.hir_id);
    }

    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
        self.observe_item(&trait_item.attrs, trait_item.hir_id);
    }

    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
        self.observe_item(&impl_item.attrs, impl_item.hir_id);
    }
}

impl<'tcx> DiagnosticItemCollector<'tcx> {
    fn new(tcx: TyCtxt<'tcx>) -> DiagnosticItemCollector<'tcx> {
        DiagnosticItemCollector { tcx, items: Default::default() }
    }

    fn observe_item(&mut self, attrs: &[ast::Attribute], hir_id: hir::HirId) {
        if let Some(name) = extract(&self.tcx.sess, attrs) {
            let def_id = self.tcx.hir().local_def_id(hir_id);
            // insert into our table
            collect_item(self.tcx, &mut self.items, name, def_id.to_def_id());
        }
    }
}

fn collect_item(
    tcx: TyCtxt<'_>,
    items: &mut FxHashMap<Symbol, DefId>,
    name: Symbol,
    item_def_id: DefId,
) {
    // Check for duplicates.
    if let Some(original_def_id) = items.insert(name, item_def_id) {
        if original_def_id != item_def_id {
            let mut err = match tcx.hir().span_if_local(item_def_id) {
                Some(span) => tcx.sess.struct_span_err(
                    span,
                    &format!("duplicate diagnostic item found: `{}`.", name),
                ),
                None => tcx.sess.struct_err(&format!(
                    "duplicate diagnostic item in crate `{}`: `{}`.",
                    tcx.crate_name(item_def_id.krate),
                    name
                )),
            };
            if let Some(span) = tcx.hir().span_if_local(original_def_id) {
                err.span_note(span, "the diagnostic item is first defined here");
            } else {
                err.note(&format!(
                    "the diagnostic item is first defined in crate `{}`.",
                    tcx.crate_name(original_def_id.krate)
                ));
            }
            err.emit();
        }
    }
}

/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.
fn extract(sess: &Session, attrs: &[ast::Attribute]) -> Option<Symbol> {
    attrs.iter().find_map(|attr| {
        if sess.check_name(attr, sym::rustc_diagnostic_item) { attr.value_str() } else { None }
    })
}

/// Traverse and collect the diagnostic items in the current
fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> {
    // Initialize the collector.
    let mut collector = DiagnosticItemCollector::new(tcx);

    // Collect diagnostic items in this crate.
    tcx.hir().krate().visit_all_item_likes(&mut collector);
    // FIXME(visit_all_item_likes): Foreign items are not visited
    // here, so we have to manually look at them for now.
    for (_, foreign_module) in tcx.foreign_modules(LOCAL_CRATE).iter() {
        for &foreign_item in foreign_module.foreign_items.iter() {
            match tcx.hir().get(tcx.hir().local_def_id_to_hir_id(foreign_item.expect_local())) {
                hir::Node::ForeignItem(item) => {
                    collector.observe_item(item.attrs, item.hir_id);
                }
                item => bug!("unexpected foreign item {:?}", item),
            }
        }
    }

    for m in tcx.hir().krate().exported_macros {
        collector.observe_item(m.attrs, m.hir_id);
    }

    collector.items
}

/// Traverse and collect all the diagnostic items in all crates.
fn collect_all<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> {
    // Initialize the collector.
    let mut collector = FxHashMap::default();

    // Collect diagnostic items in other crates.
    for &cnum in tcx.crates().iter().chain(std::iter::once(&LOCAL_CRATE)) {
        for (&name, &def_id) in tcx.diagnostic_items(cnum).iter() {
            collect_item(tcx, &mut collector, name, def_id);
        }
    }

    collector
}

pub fn provide(providers: &mut Providers) {
    providers.diagnostic_items = |tcx, id| {
        assert_eq!(id, LOCAL_CRATE);
        collect(tcx)
    };
    providers.all_diagnostic_items = |tcx, id| {
        assert_eq!(id, LOCAL_CRATE);
        collect_all(tcx)
    };
}
<|endoftext|>


<commit_before>
use std::path::Path;
use std::fs::{ File, PathExt };
use std::io::{ Read, Write };

use rustc_serialize::json;
use rustc_serialize::json::{ ToJson, Json };

use rustdoc::html::markdown::Markdown;

use handlebars::Handlebars;

use ::file_type::{ create_parent_links, Link, read_file };

#[derive(RustcEncodable)]
struct MarkdownModel {
    name: String,
    parents: Vec<Link>,
    content: String,
    base_url: String
}

impl ToJson for MarkdownModel {
    fn to_json(&self) -> Json {
        Json::from_str(&json::encode(&self).unwrap()).unwrap()
    }
}

pub fn register_handlebars<P: AsRef<Path>>(source_root: P, handlebars: &mut Handlebars) -> Result<(), &'static str> {
    let source_root = source_root.as_ref();
    let header_hbs_path = source_root.clone().join("partials/header.hbs");
    if !header_hbs_path.exists() {
        return Err("Missing partials/header.hbs");
    }

    let footer_hbs_path = source_root.clone().join("partials/footer.hbs");
    if !footer_hbs_path.exists() {
        return Err("Missing partials/footer.hbs");
    }

    let note_hbs_path = source_root.join("layouts/note.hbs");
    if !note_hbs_path.exists() {
        return Err("Missing /layouts/note.hbs");
    }

    let header_hbs_contents = try!(read_file(&header_hbs_path));//File::open(&header_hbs_path).read_to_string().unwrap();
    let footer_hbs_contents = try!(read_file(&note_hbs_path));//File::open(&footer_hbs_path).read_to_string().unwrap();
    let note_hbs_contents = try!(read_file(&note_hbs_path));//File::open(&note_hbs_path).read_to_string().unwrap();
    handlebars.register_template_string(type_str(), format!("{}\n{}\n{}", header_hbs_contents, note_hbs_contents, footer_hbs_contents))
        .ok().expect("Error registering header|note|footer template");

    Ok(())

}

pub fn is_valid_path<P: AsRef<Path>>(path: P) -> bool {
    let path = path.as_ref();
    let name = path.file_name().unwrap().to_str().unwrap();
    path.is_file() && (
        name.ends_with(".md") ||
        name.ends_with(".markdown") ||
        name.ends_with(".mkd"))
}

pub fn convert<P: AsRef<Path>>(context: &::AppContext, path: P) {
    let path = path.as_ref();
    let relative = path.relative_from(&context.root_notes).expect("Problem parsing relative url");
    let file_name = relative.file_stem().unwrap().to_str().unwrap();
    let dest_file = context.root_dest.clone().join(relative.parent().unwrap()).join(format!("{}.html", file_name));
    let mut source_contents = String::new();
    File::open(path).ok().unwrap().read_to_string(&mut source_contents).ok().expect("Could not read markdown file");
    // Create Model
    let content = Markdown(&source_contents);
    let parents = create_parent_links(&context.base_url, &relative, false);

    let model = MarkdownModel {
        name: String::from_str(file_name),
        parents : parents,
        content : format!("{}", content),
        base_url: context.base_url.clone()
    };
    match context.handlebars.render(type_str(), &model) {
        Ok(rendered) => {
            // Create File
            let mut file = File::create(&dest_file).ok().expect("Could not create markdown html file");
            //fs::chmod(&dest_file, USER_FILE).ok().expect("Couldn't chmod new file");
            file.write_all(rendered.as_bytes())
                .ok().expect("Could not write html to file");
        },
        Err(why) => panic!("Error rendering markdown: {:?}", why)
    }
}

pub fn get_url<P: AsRef<Path>>(context: &::AppContext, path: P) -> String {
    let path = path.as_ref();
    let file_name = path.file_stem().unwrap().to_str().unwrap();
    let relative = path.relative_from(&context.root_notes).expect("Problem parsing relative url");
    let parent_relative = if relative.parent().is_none() {
        String::from_str("")
    } else {
        format!("{}/", relative.parent().unwrap().to_str().unwrap())
    };
    format!("{}{}{}", context.base_url, parent_relative, format!("{}.html", file_name))
}

pub fn type_str() -> &'static str {
    "markdown"
}
<commit_msg>fixed repeating content bug<commit_after>
use std::path::Path;
use std::fs::{ File, PathExt };
use std::io::{ Read, Write };

use rustc_serialize::json;
use rustc_serialize::json::{ ToJson, Json };

use rustdoc::html::markdown::Markdown;

use handlebars::Handlebars;

use ::file_type::{ create_parent_links, Link, read_file };

#[derive(RustcEncodable)]
struct MarkdownModel {
    name: String,
    parents: Vec<Link>,
    content: String,
    base_url: String
}

impl ToJson for MarkdownModel {
    fn to_json(&self) -> Json {
        Json::from_str(&json::encode(&self).unwrap()).unwrap()
    }
}

pub fn register_handlebars<P: AsRef<Path>>(source_root: P, handlebars: &mut Handlebars) -> Result<(), &'static str> {
    let source_root = source_root.as_ref();
    let header_hbs_path = source_root.clone().join("partials/header.hbs");
    if !header_hbs_path.exists() {
        return Err("Missing partials/header.hbs");
    }

    let footer_hbs_path = source_root.clone().join("partials/footer.hbs");
    if !footer_hbs_path.exists() {
        return Err("Missing partials/footer.hbs");
    }

    let note_hbs_path = source_root.join("layouts/note.hbs");
    if !note_hbs_path.exists() {
        return Err("Missing /layouts/note.hbs");
    }

    let header_hbs_contents = try!(read_file(&header_hbs_path));
    let footer_hbs_contents = try!(read_file(&footer_hbs_path));
    let note_hbs_contents = try!(read_file(&note_hbs_path));
    handlebars.register_template_string(type_str(), format!("{}\n{}\n{}", header_hbs_contents, note_hbs_contents, footer_hbs_contents))
        .ok().expect("Error registering header|note|footer template");

    Ok(())

}

pub fn is_valid_path<P: AsRef<Path>>(path: P) -> bool {
    let path = path.as_ref();
    let name = path.file_name().unwrap().to_str().unwrap();
    path.is_file() && (
        name.ends_with(".md") ||
        name.ends_with(".markdown") ||
        name.ends_with(".mkd"))
}

pub fn convert<P: AsRef<Path>>(context: &::AppContext, path: P) {
    let path = path.as_ref();
    let relative = path.relative_from(&context.root_notes).expect("Problem parsing relative url");
    let file_name = relative.file_stem().unwrap().to_str().unwrap();
    let dest_file = context.root_dest.clone().join(relative.parent().unwrap()).join(format!("{}.html", file_name));
    let mut source_contents = String::new();
    File::open(path).ok().unwrap().read_to_string(&mut source_contents).ok().expect("Could not read markdown file");
    // Create Model
    let content = Markdown(&source_contents);
    let parents = create_parent_links(&context.base_url, &relative, false);

    let model = MarkdownModel {
        name: String::from_str(file_name),
        parents : parents,
        content : format!("{}", content),
        base_url: context.base_url.clone()
    };
    match context.handlebars.render(type_str(), &model) {
        Ok(rendered) => {
            // Create File
            let mut file = File::create(&dest_file).ok().expect("Could not create markdown html file");
            //fs::chmod(&dest_file, USER_FILE).ok().expect("Couldn't chmod new file");
            file.write_all(rendered.as_bytes())
                .ok().expect("Could not write html to file");
        },
        Err(why) => panic!("Error rendering markdown: {:?}", why)
    }
}

pub fn get_url<P: AsRef<Path>>(context: &::AppContext, path: P) -> String {
    let path = path.as_ref();
    let file_name = path.file_stem().unwrap().to_str().unwrap();
    let relative = path.relative_from(&context.root_notes).expect("Problem parsing relative url");
    let parent_relative = if relative.parent().is_none() {
        String::from_str("")
    } else {
        format!("{}/", relative.parent().unwrap().to_str().unwrap())
    };
    format!("{}{}{}", context.base_url, parent_relative, format!("{}.html", file_name))
}

pub fn type_str() -> &'static str {
    "markdown"
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate dialoguer;
extern crate duct;
#[macro_use]
extern crate error_chain;
extern crate serde;
extern crate serde_json;
extern crate snapshot;
extern crate walkdir;

use std::ffi::OsStr;
use std::fs::File;
use std::io::BufReader;
use std::process::{Command, Stdio};

use clap::{Arg, SubCommand};
use dialoguer::{Checkboxes, Select};
use duct::cmd;
use snapshot::SnapFileContents;
use walkdir::WalkDir;

error_chain!{
    types {
        Error, ErrorKind, ResultExt, SnapResult;
    }

    foreign_links {
        Io(::std::io::Error);
    }
}

quick_main!(run);

fn run() -> SnapResult<()> {
    let input = app_from_crate!()
        .subcommand(
            SubCommand::with_name("update")
                .about("Update snapshots.")
                .arg(Arg::with_name("all").short("a").long("all").help(
                    "Unconditionally update all snapshots, including unrecorded ones.",
                )),
        )
        .get_matches();

    if let Some(update_matches) = input.subcommand_matches("update") {
        if update_matches.is_present("all") {
            let output = cmd("cargo", &["test"])
                .env("UPDATE_SNAPSHOTS", "1")
                .stdout_capture()
                .stderr_capture()
                .run()
                .chain_err(|| "unable to execute cargo")?;

            if !output.status.success() {
                // TODO(dikaiosune) print what failed
                bail!("unable to update all snapshots!");
            }
        } else {
            interactive_process()?;
        }
        println!("\nAll updates processed!");
    } else {
        panic!("unsupported command");
    }

    Ok(())
}

fn interactive_process() -> SnapResult<()> {
    let cwd = ::std::env::current_dir()
        .chain_err(|| "unable to read cwd")?;

    // FIXME(adam) don't just throw away errors;
    let existing: Vec<SnapFileContents> = WalkDir::new(cwd)
        .into_iter()
        .map(|r| r.expect("unable to traverse project directory"))
        .filter(|e| e.path().extension() == Some(OsStr::new("snap")))
        .map(|p| BufReader::new(File::open(p.path()).expect("unable to open snapshot file")))
        .map(|r| serde_json::from_reader(r).expect("unable to parse snapshot file"))
        .collect::<Vec<_>>();

    let mut test_function_names = Vec::new();
    for snap_file in existing {
        for fun in snap_file.keys() {
            test_function_names.push(fun.clone());
        }
    }

    let mut failed_tests = Vec::new();

    println!("Checking for out of date snapshot tests...");
    for test_fn in test_function_names {
        let mut test_fn_chunks = test_fn.splitn(2, "::");

        // skip the crate name
        test_fn_chunks
            .next()
            .expect("looks like an empty test function name");

        let real_test_fn = test_fn_chunks
            .next()
            .expect("seemingly malformed test name");

        let first_run_status = Command::new("cargo")
            .arg("test")
            .arg(&real_test_fn)
            .stdout(Stdio::null()) // FIXME(dikaiosune) these should be captured as machine readable
            .stderr(Stdio::null()) // FIXME(dikaiosune) and just the tes
            .status()
            .chain_err(|| "unable to execute cargo")?;

        if !first_run_status.success() {
            failed_tests.push(real_test_fn.to_owned());
        }
    }

    if failed_tests.is_empty() {
        println!("\nNo snapshot tests require an update!");
        ::std::process::exit(0);
    } else {
        println!("\nPlease select which snapshot tests should be updated:");
        println!("  (press <Space> to select, <Enter> to submit)\n");

        let mut menu = Checkboxes::new();
        for failed in &failed_tests {
            menu.item(failed);
        }
        let all_to_update = menu.interact().expect("error accepting user selections");

        for fn_idx in all_to_update {
            let fn_to_update = &failed_tests[fn_idx];
            println!("Updating {}...", &fn_to_update);

            let mut run_test = true;
            while run_test {
                let run_status = Command::new("cargo")
                    .arg("test")
                    .arg(fn_to_update)
                    .env("UPDATE_SNAPSHOTS", "1")
                    .stdout(Stdio::null()) // FIXME(dikaiosune) these should be captured as JSON
                    .stderr(Stdio::null()) // FIXME(dikaiosune) and just the test output shown
                    .status()
                    .chain_err(|| "unable to execute cargo")?;

                if run_status.success() {
                    run_test = false;
                } else {
                    println!("\nUpdating {} failed! What would you like to do?",
                             fn_to_update);

                    let options = ["Retry", "Skip", "Abort"];

                    let selection = Select::new()
                        .items(&options)
                        .interact()
                        .chain_err(|| "unable to retrieve user input")?;

                    if options[selection] == "Retry" {
                        continue;
                    } else if options[selection] == "Skip" {
                        break;
                    } else if options[selection] == "Abort" {
                        ::std::process::exit(1);
                    } else {
                        bail!("invalid menu selection")
                    }
                }
            }
        }

        Ok(())
    }
}
<commit_msg>More duct, separating input gathering from control flow.<commit_after>#[macro_use]
extern crate clap;
extern crate dialoguer;
extern crate duct;
#[macro_use]
extern crate error_chain;
extern crate serde;
extern crate serde_json;
extern crate snapshot;
extern crate walkdir;

use std::ffi::OsStr;
use std::fs::File;
use std::io::BufReader;

use clap::{Arg, SubCommand};
use dialoguer::{Checkboxes, Select};
use duct::cmd;
use snapshot::SnapFileContents;
use walkdir::WalkDir;

error_chain!{
    types {
        Error, ErrorKind, ResultExt, SnapResult;
    }

    foreign_links {
        Io(::std::io::Error);
    }
}

quick_main!(run);

fn run() -> SnapResult<()> {
    let input = app_from_crate!()
        .subcommand(
            SubCommand::with_name("update")
                .about("Update snapshots.")
                .arg(Arg::with_name("all").short("a").long("all").help(
                    "Unconditionally update all snapshots, including unrecorded ones.",
                )),
        )
        .get_matches();

    if let Some(update_matches) = input.subcommand_matches("update") {
        if update_matches.is_present("all") {
            let output = cmd("cargo", &["test"])
                .env("UPDATE_SNAPSHOTS", "1")
                .stdout_capture()
                .stderr_capture()
                .run()
                .chain_err(|| "unable to execute cargo")?;

            if !output.status.success() {
                // TODO(dikaiosune) print what failed
                bail!("unable to update all snapshots!");
            }
        } else {
            interactive_process()?;
        }
        println!("\nAll updates processed!");
    } else {
        panic!("unsupported command");
    }

    Ok(())
}

fn interactive_process() -> SnapResult<()> {
    let cwd = ::std::env::current_dir()
        .chain_err(|| "unable to read cwd")?;

    // FIXME(adam) don't just throw away errors;
    let existing: Vec<SnapFileContents> = WalkDir::new(cwd)
        .into_iter()
        .map(|r| r.expect("unable to traverse project directory"))
        .filter(|e| e.path().extension() == Some(OsStr::new("snap")))
        .map(|p| BufReader::new(File::open(p.path()).expect("unable to open snapshot file")))
        .map(|r| serde_json::from_reader(r).expect("unable to parse snapshot file"))
        .collect::<Vec<_>>();

    let mut test_function_names = Vec::new();
    for snap_file in existing {
        for fun in snap_file.keys() {
            test_function_names.push(fun.clone());
        }
    }

    let mut failed_tests = Vec::new();

    println!("Checking for out of date snapshot tests...");
    for test_fn in test_function_names {
        let mut test_fn_chunks = test_fn.splitn(2, "::");

        // skip the crate name
        test_fn_chunks
            .next()
            .expect("looks like an empty test function name");

        let real_test_fn = test_fn_chunks
            .next()
            .expect("seemingly malformed test name");

        let first_run = cmd("cargo", &["test", &real_test_fn])
            .stdout_capture()
            .stderr_capture()
            .run()
            .chain_err(|| "unable to execute cargo")?;

        if !first_run.status.success() {
            failed_tests.push(real_test_fn.to_owned());
        }
    }

    if failed_tests.is_empty() {
        println!("\nNo snapshot tests require an update!");
        ::std::process::exit(0);
    } else {
        println!("\nPlease select which snapshot tests should be updated:");
        println!("  (press <Space> to select, <Enter> to submit)\n");

        let mut menu = Checkboxes::new();
        for failed in &failed_tests {
            menu.item(failed);
        }
        let all_to_update = menu.interact().expect("error accepting user selections");

        for fn_idx in all_to_update {
            let fn_to_update = &failed_tests[fn_idx];
            println!("Updating {}...", &fn_to_update);

            let mut run_test = true;
            while run_test {
                let run_output = cmd("cargo", &["test", fn_to_update])
                    .env("UPDATE_SNAPSHOTS", "1")
                    .stdout_capture()
                    .stderr_capture()
                    .run()
                    .chain_err(|| "unable to execute cargo")?;

                if run_output.status.success() {
                    run_test = false;
                } else {
                    println!("\nUpdating {} failed! What would you like to do?",
                             fn_to_update);

                    match capture_failure_selection()? {
                        TestFailureSelection::Retry => continue,
                        TestFailureSelection::Skip => break,
                        TestFailureSelection::Abort => {
                            println!("\nExiting...");
                            ::std::process::exit(1);
                        }
                    }
                }
            }
        }

        Ok(())
    }
}

enum TestFailureSelection {
    Retry,
    Skip,
    Abort,
}

fn capture_failure_selection() -> SnapResult<TestFailureSelection> {
    let options = ["Retry", "Skip", "Abort"];

    let selection = Select::new()
        .items(&options)
        .interact()
        .chain_err(|| "unable to retrieve user input")?;

    if options[selection] == "Retry" {
        Ok(TestFailureSelection::Retry)
    } else if options[selection] == "Skip" {
        Ok(TestFailureSelection::Skip)
    } else if options[selection] == "Abort" {
        Ok(TestFailureSelection::Abort)
    } else {
        bail!("invalid menu selection")
    }
}
<|endoftext|>


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

use eutil::fptr_is_null;
use libc::{c_int};
use std::collections::TreeMap;
use std::mem;
use std::slice;
use std::str;
use std::string::String;
use string::{cef_string_userfree_utf8_alloc,cef_string_userfree_utf8_free,cef_string_utf8_set};
use types::{cef_string_map_t,cef_string_t};

fn string_map_to_treemap(sm: *mut cef_string_map_t) -> *mut TreeMap<String, *mut cef_string_t> {
    sm as *mut TreeMap<String, *mut cef_string_t>
}

//cef_string_map

#[no_mangle]
pub extern "C" fn cef_string_map_alloc() -> *mut cef_string_map_t {
    unsafe {
         let sm: Box<TreeMap<String, *mut cef_string_t>> = box TreeMap::new();
         mem::transmute(sm)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_map_size(sm: *mut cef_string_map_t) -> c_int {
    unsafe {
        if fptr_is_null(mem::transmute(sm)) { return 0; }
        let v = string_map_to_treemap(sm);
        (*v).len() as c_int
    }
}

#[no_mangle]
pub extern "C" fn cef_string_map_append(sm: *mut cef_string_map_t, key: *const cef_string_t, value: *const cef_string_t) -> c_int {
    unsafe {
        if fptr_is_null(mem::transmute(sm)) { return 0; }
        let v = string_map_to_treemap(sm);
        slice::raw::buf_as_slice(mem::transmute((*key).str), (*key).length as uint, |result| {
            match str::from_utf8(result) {
                Some(k) => {
                    let s = String::from_str(k);
                    let csv = cef_string_userfree_utf8_alloc();
                    cef_string_utf8_set(mem::transmute((*value).str), (*value).length, csv, 1);
                    (*v).insert(s, csv);
                    1
                },
                None => 0
            }
        })
    }
}
<commit_msg>embedding: cef_string_map_find()<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use eutil::fptr_is_null;
use libc::{c_int};
use std::collections::TreeMap;
use std::mem;
use std::slice;
use std::str;
use std::string::String;
use string::{cef_string_userfree_utf8_alloc,cef_string_userfree_utf8_free,cef_string_utf8_set};
use types::{cef_string_map_t,cef_string_t};

fn string_map_to_treemap(sm: *mut cef_string_map_t) -> *mut TreeMap<String, *mut cef_string_t> {
    sm as *mut TreeMap<String, *mut cef_string_t>
}

//cef_string_map

#[no_mangle]
pub extern "C" fn cef_string_map_alloc() -> *mut cef_string_map_t {
    unsafe {
         let sm: Box<TreeMap<String, *mut cef_string_t>> = box TreeMap::new();
         mem::transmute(sm)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_map_size(sm: *mut cef_string_map_t) -> c_int {
    unsafe {
        if fptr_is_null(mem::transmute(sm)) { return 0; }
        let v = string_map_to_treemap(sm);
        (*v).len() as c_int
    }
}

#[no_mangle]
pub extern "C" fn cef_string_map_append(sm: *mut cef_string_map_t, key: *const cef_string_t, value: *const cef_string_t) -> c_int {
    unsafe {
        if fptr_is_null(mem::transmute(sm)) { return 0; }
        let v = string_map_to_treemap(sm);
        slice::raw::buf_as_slice(mem::transmute((*key).str), (*key).length as uint, |result| {
            match str::from_utf8(result) {
                Some(k) => {
                    let s = String::from_str(k);
                    let csv = cef_string_userfree_utf8_alloc();
                    cef_string_utf8_set(mem::transmute((*value).str), (*value).length, csv, 1);
                    (*v).insert(s, csv);
                    1
                },
                None => 0
            }
        })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_map_find(sm: *mut cef_string_map_t, key: *const cef_string_t, value: *mut cef_string_t) -> c_int {
    unsafe {
        if fptr_is_null(mem::transmute(sm)) { return 0; }
        let v = string_map_to_treemap(sm);
        slice::raw::buf_as_slice(mem::transmute((*key).str), (*key).length as uint, |result| {
            match str::from_utf8(result) {
                Some(k) => {
                    match (*v).find(&String::from_str(k)) {
                        Some(s) => {
                            cef_string_utf8_set(mem::transmute((**s).str), (**s).length, value, 1);
                            1
                        }
                        None => 0
                    }
                },
                None => 0
            }
        })
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use crate::cli::Options;
use bytecode::{
    borrow_analysis::BorrowAnalysisProcessor,
    clean_and_optimize::CleanAndOptimizeProcessor, eliminate_imm_refs::EliminateImmRefsProcessor,
    function_target_pipeline::FunctionTargetProcessor, livevar_analysis::LiveVarAnalysisProcessor,
    loop_analysis::LoopAnalysisProcessor, memory_instrumentation::MemoryInstrumentationProcessor,
    mut_ref_instrumentation::MutRefInstrumenter,
    reaching_def_analysis::ReachingDefProcessor, usage_analysis::UsageProcessor,
    verification_analysis::VerificationAnalysisProcessor,
};

/// Allows client to decide between one of two pipelines for ease of benchmarking
pub fn pipelines(options: &Options) -> Vec<Box<dyn FunctionTargetProcessor>> {
    if !options.experimental_pipeline {
        vec![
            EliminateImmRefsProcessor::new(),
            MutRefInstrumenter::new(),
            ReachingDefProcessor::new(),
            LiveVarAnalysisProcessor::new(),
            BorrowAnalysisProcessor::new(options.strong_edges),
            MemoryInstrumentationProcessor::new(),
            CleanAndOptimizeProcessor::new(),
            UsageProcessor::new(),
            VerificationAnalysisProcessor::new(),
            LoopAnalysisProcessor::new(),
        ]
    } else {
        // Enter your pipeline here
        panic!("No experimental pipeline set");
    }
}
<commit_msg>[move-prover] formatting fixes<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use crate::cli::Options;
use bytecode::{
    borrow_analysis::BorrowAnalysisProcessor, clean_and_optimize::CleanAndOptimizeProcessor,
    eliminate_imm_refs::EliminateImmRefsProcessor,
    function_target_pipeline::FunctionTargetProcessor, livevar_analysis::LiveVarAnalysisProcessor,
    loop_analysis::LoopAnalysisProcessor, memory_instrumentation::MemoryInstrumentationProcessor,
    mut_ref_instrumentation::MutRefInstrumenter, reaching_def_analysis::ReachingDefProcessor,
    usage_analysis::UsageProcessor, verification_analysis::VerificationAnalysisProcessor,
};

/// Allows client to decide between one of two pipelines for ease of benchmarking
pub fn pipelines(options: &Options) -> Vec<Box<dyn FunctionTargetProcessor>> {
    if !options.experimental_pipeline {
        vec![
            EliminateImmRefsProcessor::new(),
            MutRefInstrumenter::new(),
            ReachingDefProcessor::new(),
            LiveVarAnalysisProcessor::new(),
            BorrowAnalysisProcessor::new(options.strong_edges),
            MemoryInstrumentationProcessor::new(),
            CleanAndOptimizeProcessor::new(),
            UsageProcessor::new(),
            VerificationAnalysisProcessor::new(),
            LoopAnalysisProcessor::new(),
        ]
    } else {
        // Enter your pipeline here
        panic!("No experimental pipeline set");
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

//! Provides a request context that carries a deadline and trace context. This context is sent from
//! client to server and is used by the server to enforce response deadlines.

use crate::trace::{self, TraceId};
use static_assertions::assert_impl_all;
use std::time::{Duration, SystemTime};

/// A request context that carries request-scoped information like deadlines and trace information.
/// It is sent from client to server and is used by the server to enforce response deadlines.
///
/// The context should not be stored directly in a server implementation, because the context will
/// be different for each request in scope.
#[derive(Clone, Copy, Debug)]
#[non_exhaustive]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub struct Context {
    /// When the client expects the request to be complete by. The server should cancel the request
    /// if it is not complete by this time.
    #[cfg_attr(
        feature = "serde1",
        serde(serialize_with = "crate::util::serde::serialize_epoch_secs")
    )]
    #[cfg_attr(
        feature = "serde1",
        serde(deserialize_with = "crate::util::serde::deserialize_epoch_secs")
    )]
    #[cfg_attr(feature = "serde1", serde(default = "ten_seconds_from_now"))]
    pub deadline: SystemTime,
    /// Uniquely identifies requests originating from the same source.
    /// When a service handles a request by making requests itself, those requests should
    /// include the same `trace_id` as that included on the original request. This way,
    /// users can trace related actions across a distributed system.
    pub trace_context: trace::Context,
}

assert_impl_all!(Context: Send);

#[cfg(feature = "serde1")]
fn ten_seconds_from_now() -> SystemTime {
    SystemTime::now() + Duration::from_secs(10)
}

/// Returns the context for the current request, or a default Context if no request is active.
// TODO: populate Context with request-scoped data, with default fallbacks.
pub fn current() -> Context {
    Context {
        deadline: SystemTime::now() + Duration::from_secs(10),
        trace_context: trace::Context::new_root(),
    }
}

impl Context {
    /// Returns the ID of the request-scoped trace.
    pub fn trace_id(&self) -> &TraceId {
        &self.trace_context.trace_id
    }
}
<commit_msg>Ensure Context is Sync.<commit_after>// Copyright 2018 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

//! Provides a request context that carries a deadline and trace context. This context is sent from
//! client to server and is used by the server to enforce response deadlines.

use crate::trace::{self, TraceId};
use static_assertions::assert_impl_all;
use std::time::{Duration, SystemTime};

/// A request context that carries request-scoped information like deadlines and trace information.
/// It is sent from client to server and is used by the server to enforce response deadlines.
///
/// The context should not be stored directly in a server implementation, because the context will
/// be different for each request in scope.
#[derive(Clone, Copy, Debug)]
#[non_exhaustive]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub struct Context {
    /// When the client expects the request to be complete by. The server should cancel the request
    /// if it is not complete by this time.
    #[cfg_attr(
        feature = "serde1",
        serde(serialize_with = "crate::util::serde::serialize_epoch_secs")
    )]
    #[cfg_attr(
        feature = "serde1",
        serde(deserialize_with = "crate::util::serde::deserialize_epoch_secs")
    )]
    #[cfg_attr(feature = "serde1", serde(default = "ten_seconds_from_now"))]
    pub deadline: SystemTime,
    /// Uniquely identifies requests originating from the same source.
    /// When a service handles a request by making requests itself, those requests should
    /// include the same `trace_id` as that included on the original request. This way,
    /// users can trace related actions across a distributed system.
    pub trace_context: trace::Context,
}

assert_impl_all!(Context: Send, Sync);

#[cfg(feature = "serde1")]
fn ten_seconds_from_now() -> SystemTime {
    SystemTime::now() + Duration::from_secs(10)
}

/// Returns the context for the current request, or a default Context if no request is active.
// TODO: populate Context with request-scoped data, with default fallbacks.
pub fn current() -> Context {
    Context {
        deadline: SystemTime::now() + Duration::from_secs(10),
        trace_context: trace::Context::new_root(),
    }
}

impl Context {
    /// Returns the ID of the request-scoped trace.
    pub fn trace_id(&self) -> &TraceId {
        &self.trace_context.trace_id
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2020, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

#![deny(bare_trait_objects)]
#![allow(clippy::cast_lossless)]
#![allow(clippy::cast_ptr_alignment)]
#![allow(clippy::cognitive_complexity)]
#![allow(clippy::needless_range_loop)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::verbose_bit_mask)]
#![allow(clippy::unreadable_literal)]
#![allow(clippy::many_single_char_names)]
// Performance lints
#![warn(clippy::linkedlist)]
#![warn(clippy::missing_const_for_fn)]
#![warn(clippy::mutex_integer)]
#![warn(clippy::suboptimal_flops)]
// Correctness lints
#![warn(clippy::expl_impl_clone_on_copy)]
#![warn(clippy::mem_forget)]
#![warn(clippy::path_buf_push_overwrite)]
// Clarity/formatting lints
#![warn(clippy::map_flatten)]
#![warn(clippy::mut_mut)]
#![warn(clippy::needless_borrow)]
#![warn(clippy::needless_continue)]
#![warn(clippy::range_plus_one)]
// Documentation lints
#![warn(clippy::doc_markdown)]
#![warn(clippy::missing_errors_doc)]
#![warn(clippy::missing_panics_doc)]
#![warn(clippy::undocumented_unsafe_blocks)]

pub mod frame;
pub mod math;
pub mod pixel;
pub mod plane;

mod serialize {
  cfg_if::cfg_if! {
     if #[cfg(feature="serialize")] {
       pub use serde::*;
      } else {
        pub use noop_proc_macro::{Deserialize, Serialize};
     }
  }
}

mod wasm_bindgen {
  cfg_if::cfg_if! {
    if #[cfg(feature="wasm")] {
      pub use wasm_bindgen::prelude::*;
    } else {
      pub use noop_proc_macro::wasm_bindgen;
    }
  }
}

pub mod prelude {
  pub use crate::math::*;
  pub use crate::pixel::*;
}
<commit_msg>v_frame: Disable missing const fn clippy lint<commit_after>// Copyright (c) 2020, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

#![deny(bare_trait_objects)]
#![allow(clippy::cast_lossless)]
#![allow(clippy::cast_ptr_alignment)]
#![allow(clippy::cognitive_complexity)]
#![allow(clippy::needless_range_loop)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::verbose_bit_mask)]
#![allow(clippy::unreadable_literal)]
#![allow(clippy::many_single_char_names)]
// Performance lints
#![warn(clippy::linkedlist)]
#![warn(clippy::mutex_integer)]
#![warn(clippy::suboptimal_flops)]
// Correctness lints
#![warn(clippy::expl_impl_clone_on_copy)]
#![warn(clippy::mem_forget)]
#![warn(clippy::path_buf_push_overwrite)]
// Clarity/formatting lints
#![warn(clippy::map_flatten)]
#![warn(clippy::mut_mut)]
#![warn(clippy::needless_borrow)]
#![warn(clippy::needless_continue)]
#![warn(clippy::range_plus_one)]
// Documentation lints
#![warn(clippy::doc_markdown)]
#![warn(clippy::missing_errors_doc)]
#![warn(clippy::missing_panics_doc)]
#![warn(clippy::undocumented_unsafe_blocks)]

pub mod frame;
pub mod math;
pub mod pixel;
pub mod plane;

mod serialize {
  cfg_if::cfg_if! {
     if #[cfg(feature="serialize")] {
       pub use serde::*;
      } else {
        pub use noop_proc_macro::{Deserialize, Serialize};
     }
  }
}

mod wasm_bindgen {
  cfg_if::cfg_if! {
    if #[cfg(feature="wasm")] {
      pub use wasm_bindgen::prelude::*;
    } else {
      pub use noop_proc_macro::wasm_bindgen;
    }
  }
}

pub mod prelude {
  pub use crate::math::*;
  pub use crate::pixel::*;
}
<|endoftext|>


<commit_before>use std::cmp::min;
use std::mem;

use runtime::Messageable;
use id::{class, Id, IdVector};
use super::{INSCopying, INSObject};

pub trait INSDictionary<K: Messageable, V> : INSObject {
	fn count(&self) -> uint {
		let result = unsafe {
			msg_send![self count]
		};
		result as uint
	}

	fn object_for<'a>(&'a self, key: &K) -> Option<&'a V> {
		unsafe {
			let obj = msg_send![self objectForKey:key.as_ptr()];
			if obj.is_null() {
				None
			} else {
				Some(mem::transmute(obj))
			}
		}
	}

	unsafe fn from_refs<T: INSCopying<K>>(keys: &[&T], vals: &[&V]) -> Id<Self> {
		let cls = class::<Self>();
		let count = min(keys.len(), vals.len());
		let obj = msg_send![cls alloc];
		let obj = msg_send![obj initWithObjects:vals.as_ptr()
		                                forKeys:keys.as_ptr()
		                                  count:count];
		Id::from_retained_ptr(obj as *Self)
	}

	fn from_keys_and_objects<T: INSCopying<K>>(keys: &[&T], vals: Vec<Id<V>>) -> Id<Self> {
		let vals_refs = vals.as_refs_slice();
		unsafe {
			INSDictionary::from_refs(keys, vals_refs)
		}
	}
}

object_struct!(NSDictionary<K, V>)

impl<K: Messageable, V> INSDictionary<K, V> for NSDictionary<K, V> { }

impl<K: Messageable, V> Collection for NSDictionary<K, V> {
	fn len(&self) -> uint {
		self.count()
	}
}

impl<K: Messageable, V> Map<K, V> for NSDictionary<K, V> {
	fn find<'a>(&'a self, key: &K) -> Option<&'a V> {
		self.object_for(key)
	}
}
<commit_msg>Replaced Messageable with NSObject for NSDictionary.<commit_after>use std::cmp::min;
use std::mem;

use id::{class, Id, IdVector};
use super::{INSCopying, INSObject};

pub trait INSDictionary<K: INSObject, V> : INSObject {
	fn count(&self) -> uint {
		let result = unsafe {
			msg_send![self count]
		};
		result as uint
	}

	fn object_for<'a>(&'a self, key: &K) -> Option<&'a V> {
		unsafe {
			let obj = msg_send![self objectForKey:key.as_ptr()];
			if obj.is_null() {
				None
			} else {
				Some(mem::transmute(obj))
			}
		}
	}

	unsafe fn from_refs<T: INSCopying<K>>(keys: &[&T], vals: &[&V]) -> Id<Self> {
		let cls = class::<Self>();
		let count = min(keys.len(), vals.len());
		let obj = msg_send![cls alloc];
		let obj = msg_send![obj initWithObjects:vals.as_ptr()
		                                forKeys:keys.as_ptr()
		                                  count:count];
		Id::from_retained_ptr(obj as *Self)
	}

	fn from_keys_and_objects<T: INSCopying<K>>(keys: &[&T], vals: Vec<Id<V>>) -> Id<Self> {
		let vals_refs = vals.as_refs_slice();
		unsafe {
			INSDictionary::from_refs(keys, vals_refs)
		}
	}
}

object_struct!(NSDictionary<K, V>)

impl<K: INSObject, V> INSDictionary<K, V> for NSDictionary<K, V> { }

impl<K: INSObject, V> Collection for NSDictionary<K, V> {
	fn len(&self) -> uint {
		self.count()
	}
}

impl<K: INSObject, V> Map<K, V> for NSDictionary<K, V> {
	fn find<'a>(&'a self, key: &K) -> Option<&'a V> {
		self.object_for(key)
	}
}
<|endoftext|>


<commit_before>extern crate serde;
#[macro_use] extern crate serde_derive;

use std::collections::HashMap;
use std::fmt;

#[derive(Clone, Debug, PartialEq, Serialize)]
pub enum AMQPType {
    Boolean,
    ShortShortInt,
    ShortShortUInt,
    ShortInt,
    ShortUInt,
    LongInt,
    LongUInt,
    LongLongInt,
    LongLongUInt,
    Float,
    Double,
    DecimalValue,
    ShortString,
    LongString,
    FieldArray,
    TimeStamp,
    FieldTable,
    Void,
}

impl AMQPType {
    pub fn from_id(id: char) -> AMQPType {
        match id {
            't' => AMQPType::Boolean,
            'b' => AMQPType::ShortShortInt,
            'B' => AMQPType::ShortShortUInt,
            'U' => AMQPType::ShortInt,
            'u' => AMQPType::ShortUInt,
            'I' => AMQPType::LongInt,
            'i' => AMQPType::LongUInt,
            'L' => AMQPType::LongLongInt,
            'l' => AMQPType::LongLongUInt,
            'f' => AMQPType::Float,
            'd' => AMQPType::Double,
            'D' => AMQPType::DecimalValue,
            's' => AMQPType::ShortString,
            'S' => AMQPType::LongString,
            'A' => AMQPType::FieldArray,
            'T' => AMQPType::TimeStamp,
            'F' => AMQPType::FieldTable,
            'V' => AMQPType::Void,
            _ => panic!("Unknown type id {}", id), /*FIXME: don't panic*/
        }
    }

    pub fn get_id(&self) -> char {
        match *self {
            AMQPType::Boolean => 't',
            AMQPType::ShortShortInt => 'b',
            AMQPType::ShortShortUInt => 'B',
            AMQPType::ShortInt => 'U',
            AMQPType::ShortUInt => 'u',
            AMQPType::LongInt => 'I',
            AMQPType::LongUInt => 'i',
            AMQPType::LongLongInt => 'L',
            AMQPType::LongLongUInt => 'l',
            AMQPType::Float => 'f',
            AMQPType::Double => 'd',
            AMQPType::DecimalValue => 'D',
            AMQPType::ShortString => 's',
            AMQPType::LongString => 'S',
            AMQPType::FieldArray => 'A',
            AMQPType::TimeStamp => 'T',
            AMQPType::FieldTable => 'F',
            AMQPType::Void => 'V',
        }
    }

    pub fn to_string(&self) -> String {
        format!("{}", self)
    }
}

impl fmt::Display for AMQPType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

pub type Boolean        = bool;
pub type ShortShortInt  = i8;
pub type ShortShortUInt = u8;
pub type ShortInt       = i16;
pub type ShortUInt      = u16;
pub type LongInt        = i32;
pub type LongUInt       = u32;
pub type LongLongInt    = i64;
pub type LongLongUInt   = u64;
pub type Float          = f32;
pub type Double         = f64;
pub type ShortString    = String; /* TODO: don't allow size >= 255 */
pub type LongString     = String;
pub type FieldArray     = Vec<AMQPValue>;
pub type TimeStamp      = u64;
pub type FieldTable     = HashMap<String, AMQPValue>;
pub type Void           = ();

#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct DecimalValue {
    pub scale: u8,
    pub value: LongUInt,
}

#[derive(Clone, Debug, PartialEq, Serialize)]
pub enum AMQPValue {
    Boolean(Boolean),
    ShortShortInt(ShortShortInt),
    ShortShortUInt(ShortShortUInt),
    ShortInt(ShortInt),
    ShortUInt(ShortUInt),
    LongInt(LongInt),
    LongUInt(LongUInt),
    LongLongInt(LongLongInt),
    LongLongUInt(LongLongUInt),
    Float(Float),
    Double(Double),
    DecimalValue(DecimalValue),
    ShortString(ShortString),
    LongString(LongString),
    FieldArray(FieldArray),
    TimeStamp(TimeStamp),
    FieldTable(FieldTable),
    Void(Void),
}
<commit_msg>types: don't panic! on unknown type<commit_after>extern crate serde;
#[macro_use] extern crate serde_derive;

use std::collections::HashMap;
use std::fmt;

#[derive(Clone, Debug, PartialEq, Serialize)]
pub enum AMQPType {
    Boolean,
    ShortShortInt,
    ShortShortUInt,
    ShortInt,
    ShortUInt,
    LongInt,
    LongUInt,
    LongLongInt,
    LongLongUInt,
    Float,
    Double,
    DecimalValue,
    ShortString,
    LongString,
    FieldArray,
    TimeStamp,
    FieldTable,
    Void,
}

impl AMQPType {
    pub fn from_id(id: char) -> Option<AMQPType> {
        match id {
            't' => Some(AMQPType::Boolean),
            'b' => Some(AMQPType::ShortShortInt),
            'B' => Some(AMQPType::ShortShortUInt),
            'U' => Some(AMQPType::ShortInt),
            'u' => Some(AMQPType::ShortUInt),
            'I' => Some(AMQPType::LongInt),
            'i' => Some(AMQPType::LongUInt),
            'L' => Some(AMQPType::LongLongInt),
            'l' => Some(AMQPType::LongLongUInt),
            'f' => Some(AMQPType::Float),
            'd' => Some(AMQPType::Double),
            'D' => Some(AMQPType::DecimalValue),
            's' => Some(AMQPType::ShortString),
            'S' => Some(AMQPType::LongString),
            'A' => Some(AMQPType::FieldArray),
            'T' => Some(AMQPType::TimeStamp),
            'F' => Some(AMQPType::FieldTable),
            'V' => Some(AMQPType::Void),
            _   => None,
        }
    }

    pub fn get_id(&self) -> char {
        match *self {
            AMQPType::Boolean => 't',
            AMQPType::ShortShortInt => 'b',
            AMQPType::ShortShortUInt => 'B',
            AMQPType::ShortInt => 'U',
            AMQPType::ShortUInt => 'u',
            AMQPType::LongInt => 'I',
            AMQPType::LongUInt => 'i',
            AMQPType::LongLongInt => 'L',
            AMQPType::LongLongUInt => 'l',
            AMQPType::Float => 'f',
            AMQPType::Double => 'd',
            AMQPType::DecimalValue => 'D',
            AMQPType::ShortString => 's',
            AMQPType::LongString => 'S',
            AMQPType::FieldArray => 'A',
            AMQPType::TimeStamp => 'T',
            AMQPType::FieldTable => 'F',
            AMQPType::Void => 'V',
        }
    }

    pub fn to_string(&self) -> String {
        format!("{}", self)
    }
}

impl fmt::Display for AMQPType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

pub type Boolean        = bool;
pub type ShortShortInt  = i8;
pub type ShortShortUInt = u8;
pub type ShortInt       = i16;
pub type ShortUInt      = u16;
pub type LongInt        = i32;
pub type LongUInt       = u32;
pub type LongLongInt    = i64;
pub type LongLongUInt   = u64;
pub type Float          = f32;
pub type Double         = f64;
pub type ShortString    = String; /* TODO: don't allow size >= 255 */
pub type LongString     = String;
pub type FieldArray     = Vec<AMQPValue>;
pub type TimeStamp      = u64;
pub type FieldTable     = HashMap<String, AMQPValue>;
pub type Void           = ();

#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct DecimalValue {
    pub scale: u8,
    pub value: LongUInt,
}

#[derive(Clone, Debug, PartialEq, Serialize)]
pub enum AMQPValue {
    Boolean(Boolean),
    ShortShortInt(ShortShortInt),
    ShortShortUInt(ShortShortUInt),
    ShortInt(ShortInt),
    ShortUInt(ShortUInt),
    LongInt(LongInt),
    LongUInt(LongUInt),
    LongLongInt(LongLongInt),
    LongLongUInt(LongLongUInt),
    Float(Float),
    Double(Double),
    DecimalValue(DecimalValue),
    ShortString(ShortString),
    LongString(LongString),
    FieldArray(FieldArray),
    TimeStamp(TimeStamp),
    FieldTable(FieldTable),
    Void(Void),
}
<|endoftext|>