<commit_before>use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::ty::query::Providers;
use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::symbol::Symbol;

// When adding features to the below lists
// check whether they're named already elsewhere in rust
// e.g. in stdarch and whether the given name matches LLVM's
// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted

const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
    ("aclass", Some(sym::arm_target_feature)),
    ("mclass", Some(sym::arm_target_feature)),
    ("rclass", Some(sym::arm_target_feature)),
    ("dsp", Some(sym::arm_target_feature)),
    ("neon", Some(sym::arm_target_feature)),
    ("crc", Some(sym::arm_target_feature)),
    ("crypto", Some(sym::arm_target_feature)),
    ("aes", Some(sym::arm_target_feature)),
    ("sha2", Some(sym::arm_target_feature)),
    ("i8mm", Some(sym::arm_target_feature)),
    ("v5te", Some(sym::arm_target_feature)),
    ("v6", Some(sym::arm_target_feature)),
    ("v6k", Some(sym::arm_target_feature)),
    ("v6t2", Some(sym::arm_target_feature)),
    ("v7", Some(sym::arm_target_feature)),
    ("v8", Some(sym::arm_target_feature)),
    ("vfp2", Some(sym::arm_target_feature)),
    ("vfp3", Some(sym::arm_target_feature)),
    ("vfp4", Some(sym::arm_target_feature)),
    ("fp-armv8", Some(sym::arm_target_feature)),
    // This is needed for inline assembly, but shouldn't be stabilized as-is
    // since it should be enabled per-function using #[instruction_set], not
    // #[target_feature].
    ("thumb-mode", Some(sym::arm_target_feature)),
];

const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
    // FEAT_AdvSimd
    ("neon", Some(sym::aarch64_target_feature)),
    // FEAT_FP
    ("fp", Some(sym::aarch64_target_feature)),
    // FEAT_FP16
    ("fp16", Some(sym::aarch64_target_feature)),
    // FEAT_SVE
    ("sve", Some(sym::aarch64_target_feature)),
    // FEAT_CRC
    ("crc", Some(sym::aarch64_target_feature)),
    // FEAT_RAS
    ("ras", Some(sym::aarch64_target_feature)),
    // FEAT_LSE
    ("lse", Some(sym::aarch64_target_feature)),
    // FEAT_RDM
    ("rdm", Some(sym::aarch64_target_feature)),
    // FEAT_RCPC
    ("rcpc", Some(sym::aarch64_target_feature)),
    // FEAT_RCPC2
    ("rcpc2", Some(sym::aarch64_target_feature)),
    // FEAT_DotProd
    ("dotprod", Some(sym::aarch64_target_feature)),
    // FEAT_TME
    ("tme", Some(sym::aarch64_target_feature)),
    // FEAT_FHM
    ("fhm", Some(sym::aarch64_target_feature)),
    // FEAT_DIT
    ("dit", Some(sym::aarch64_target_feature)),
    // FEAT_FLAGM
    ("flagm", Some(sym::aarch64_target_feature)),
    // FEAT_SSBS
    ("ssbs", Some(sym::aarch64_target_feature)),
    // FEAT_SB
    ("sb", Some(sym::aarch64_target_feature)),
    // FEAT_PAUTH
    ("pauth", Some(sym::aarch64_target_feature)),
    // FEAT_DPB
    ("dpb", Some(sym::aarch64_target_feature)),
    // FEAT_DPB2
    ("dpb2", Some(sym::aarch64_target_feature)),
    // FEAT_SVE2
    ("sve2", Some(sym::aarch64_target_feature)),
    // FEAT_SVE2_AES
    ("sve2-aes", Some(sym::aarch64_target_feature)),
    // FEAT_SVE2_SM4
    ("sve2-sm4", Some(sym::aarch64_target_feature)),
    // FEAT_SVE2_SHA3
    ("sve2-sha3", Some(sym::aarch64_target_feature)),
    // FEAT_SVE2_BitPerm
    ("sve2-bitperm", Some(sym::aarch64_target_feature)),
    // FEAT_FRINTTS
    ("frintts", Some(sym::aarch64_target_feature)),
    // FEAT_I8MM
    ("i8mm", Some(sym::aarch64_target_feature)),
    // FEAT_F32MM
    ("f32mm", Some(sym::aarch64_target_feature)),
    // FEAT_F64MM
    ("f64mm", Some(sym::aarch64_target_feature)),
    // FEAT_BF16
    ("bf16", Some(sym::aarch64_target_feature)),
    // FEAT_RAND
    ("rand", Some(sym::aarch64_target_feature)),
    // FEAT_BTI
    ("bti", Some(sym::aarch64_target_feature)),
    // FEAT_MTE
    ("mte", Some(sym::aarch64_target_feature)),
    // FEAT_JSCVT
    ("jsconv", Some(sym::aarch64_target_feature)),
    // FEAT_FCMA
    ("fcma", Some(sym::aarch64_target_feature)),
    // FEAT_AES
    ("aes", Some(sym::aarch64_target_feature)),
    // FEAT_SHA1 & FEAT_SHA256
    ("sha2", Some(sym::aarch64_target_feature)),
    // FEAT_SHA512 & FEAT_SHA3
    ("sha3", Some(sym::aarch64_target_feature)),
    // FEAT_SM3 & FEAT_SM4
    ("sm4", Some(sym::aarch64_target_feature)),
    // FEAT_PAN
    ("pan", Some(sym::aarch64_target_feature)),
    // FEAT_LOR
    ("lor", Some(sym::aarch64_target_feature)),
    // FEAT_VHE
    ("vh", Some(sym::aarch64_target_feature)),
    // FEAT_PMUv3
    ("pmuv3", Some(sym::aarch64_target_feature)),
    // FEAT_SPE
    ("spe", Some(sym::aarch64_target_feature)),
    ("v8.1a", Some(sym::aarch64_target_feature)),
    ("v8.2a", Some(sym::aarch64_target_feature)),
    ("v8.3a", Some(sym::aarch64_target_feature)),
    ("v8.4a", Some(sym::aarch64_target_feature)),
    ("v8.5a", Some(sym::aarch64_target_feature)),
    ("v8.6a", Some(sym::aarch64_target_feature)),
    ("v8.7a", Some(sym::aarch64_target_feature)),
];

const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
    ("adx", Some(sym::adx_target_feature)),
    ("aes", None),
    ("avx", None),
    ("avx2", None),
    ("avx512bf16", Some(sym::avx512_target_feature)),
    ("avx512bitalg", Some(sym::avx512_target_feature)),
    ("avx512bw", Some(sym::avx512_target_feature)),
    ("avx512cd", Some(sym::avx512_target_feature)),
    ("avx512dq", Some(sym::avx512_target_feature)),
    ("avx512er", Some(sym::avx512_target_feature)),
    ("avx512f", Some(sym::avx512_target_feature)),
    ("avx512gfni", Some(sym::avx512_target_feature)),
    ("avx512ifma", Some(sym::avx512_target_feature)),
    ("avx512pf", Some(sym::avx512_target_feature)),
    ("avx512vaes", Some(sym::avx512_target_feature)),
    ("avx512vbmi", Some(sym::avx512_target_feature)),
    ("avx512vbmi2", Some(sym::avx512_target_feature)),
    ("avx512vl", Some(sym::avx512_target_feature)),
    ("avx512vnni", Some(sym::avx512_target_feature)),
    ("avx512vp2intersect", Some(sym::avx512_target_feature)),
    ("avx512vpclmulqdq", Some(sym::avx512_target_feature)),
    ("avx512vpopcntdq", Some(sym::avx512_target_feature)),
    ("bmi1", None),
    ("bmi2", None),
    ("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)),
    ("ermsb", Some(sym::ermsb_target_feature)),
    ("f16c", Some(sym::f16c_target_feature)),
    ("fma", None),
    ("fxsr", None),
    ("lzcnt", None),
    ("movbe", Some(sym::movbe_target_feature)),
    ("pclmulqdq", None),
    ("popcnt", None),
    ("rdrand", None),
    ("rdseed", None),
    ("rtm", Some(sym::rtm_target_feature)),
    ("sha", None),
    ("sse", None),
    ("sse2", None),
    ("sse3", None),
    ("sse4.1", None),
    ("sse4.2", None),
    ("sse4a", Some(sym::sse4a_target_feature)),
    ("ssse3", None),
    ("tbm", Some(sym::tbm_target_feature)),
    ("xsave", None),
    ("xsavec", None),
    ("xsaveopt", None),
    ("xsaves", None),
];

const HEXAGON_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
    ("hvx", Some(sym::hexagon_target_feature)),
    ("hvx-length128b", Some(sym::hexagon_target_feature)),
];

const POWERPC_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
    ("altivec", Some(sym::powerpc_target_feature)),
    ("power8-altivec", Some(sym::powerpc_target_feature)),
    ("power9-altivec", Some(sym::powerpc_target_feature)),
    ("power8-vector", Some(sym::powerpc_target_feature)),
    ("power9-vector", Some(sym::powerpc_target_feature)),
    ("vsx", Some(sym::powerpc_target_feature)),
];

const MIPS_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] =
    &[("fp64", Some(sym::mips_target_feature)), ("msa", Some(sym::mips_target_feature))];

const RISCV_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
    ("m", Some(sym::riscv_target_feature)),
    ("a", Some(sym::riscv_target_feature)),
    ("c", Some(sym::riscv_target_feature)),
    ("f", Some(sym::riscv_target_feature)),
    ("d", Some(sym::riscv_target_feature)),
    ("e", Some(sym::riscv_target_feature)),
];

const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
    ("simd128", None),
    ("atomics", Some(sym::wasm_target_feature)),
    ("nontrapping-fptoint", Some(sym::wasm_target_feature)),
];

const BPF_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[("alu32", Some(sym::bpf_target_feature))];

/// When rustdoc is running, provide a list of all known features so that all their respective
/// primitives may be documented.
///
/// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator!
pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol>)> {
    std::iter::empty()
        .chain(ARM_ALLOWED_FEATURES.iter())
        .chain(AARCH64_ALLOWED_FEATURES.iter())
        .chain(X86_ALLOWED_FEATURES.iter())
        .chain(HEXAGON_ALLOWED_FEATURES.iter())
        .chain(POWERPC_ALLOWED_FEATURES.iter())
        .chain(MIPS_ALLOWED_FEATURES.iter())
        .chain(RISCV_ALLOWED_FEATURES.iter())
        .chain(WASM_ALLOWED_FEATURES.iter())
        .chain(BPF_ALLOWED_FEATURES.iter())
        .cloned()
}

pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Option<Symbol>)] {
    match &*sess.target.arch {
        "arm" => ARM_ALLOWED_FEATURES,
        "aarch64" => AARCH64_ALLOWED_FEATURES,
        "x86" | "x86_64" => X86_ALLOWED_FEATURES,
        "hexagon" => HEXAGON_ALLOWED_FEATURES,
        "mips" | "mips64" => MIPS_ALLOWED_FEATURES,
        "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES,
        "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES,
        "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES,
        "bpf" => BPF_ALLOWED_FEATURES,
        _ => &[],
    }
}

pub(crate) fn provide(providers: &mut Providers) {
    providers.supported_target_features = |tcx, cnum| {
        assert_eq!(cnum, LOCAL_CRATE);
        if tcx.sess.opts.actually_rustdoc {
            // rustdoc needs to be able to document functions that use all the features, so
            // whitelist them all
            all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
        } else {
            supported_target_features(tcx.sess).iter().map(|&(a, b)| (a.to_string(), b)).collect()
        }
    };
}
<commit_msg>Rollup merge of #90688 - SparrowLii:dotprod, r=Amanieu<commit_after>use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::ty::query::Providers;
use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::symbol::Symbol;

// When adding features to the below lists
// check whether they're named already elsewhere in rust
// e.g. in stdarch and whether the given name matches LLVM's
// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted

const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
    ("aclass", Some(sym::arm_target_feature)),
    ("mclass", Some(sym::arm_target_feature)),
    ("rclass", Some(sym::arm_target_feature)),
    ("dsp", Some(sym::arm_target_feature)),
    ("neon", Some(sym::arm_target_feature)),
    ("crc", Some(sym::arm_target_feature)),
    ("crypto", Some(sym::arm_target_feature)),
    ("aes", Some(sym::arm_target_feature)),
    ("sha2", Some(sym::arm_target_feature)),
    ("i8mm", Some(sym::arm_target_feature)),
    ("dotprod", Some(sym::arm_target_feature)),
    ("v5te", Some(sym::arm_target_feature)),
    ("v6", Some(sym::arm_target_feature)),
    ("v6k", Some(sym::arm_target_feature)),
    ("v6t2", Some(sym::arm_target_feature)),
    ("v7", Some(sym::arm_target_feature)),
    ("v8", Some(sym::arm_target_feature)),
    ("vfp2", Some(sym::arm_target_feature)),
    ("vfp3", Some(sym::arm_target_feature)),
    ("vfp4", Some(sym::arm_target_feature)),
    ("fp-armv8", Some(sym::arm_target_feature)),
    // This is needed for inline assembly, but shouldn't be stabilized as-is
    // since it should be enabled per-function using #[instruction_set], not
    // #[target_feature].
    ("thumb-mode", Some(sym::arm_target_feature)),
];

const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
    // FEAT_AdvSimd
    ("neon", Some(sym::aarch64_target_feature)),
    // FEAT_FP
    ("fp", Some(sym::aarch64_target_feature)),
    // FEAT_FP16
    ("fp16", Some(sym::aarch64_target_feature)),
    // FEAT_SVE
    ("sve", Some(sym::aarch64_target_feature)),
    // FEAT_CRC
    ("crc", Some(sym::aarch64_target_feature)),
    // FEAT_RAS
    ("ras", Some(sym::aarch64_target_feature)),
    // FEAT_LSE
    ("lse", Some(sym::aarch64_target_feature)),
    // FEAT_RDM
    ("rdm", Some(sym::aarch64_target_feature)),
    // FEAT_RCPC
    ("rcpc", Some(sym::aarch64_target_feature)),
    // FEAT_RCPC2
    ("rcpc2", Some(sym::aarch64_target_feature)),
    // FEAT_DotProd
    ("dotprod", Some(sym::aarch64_target_feature)),
    // FEAT_TME
    ("tme", Some(sym::aarch64_target_feature)),
    // FEAT_FHM
    ("fhm", Some(sym::aarch64_target_feature)),
    // FEAT_DIT
    ("dit", Some(sym::aarch64_target_feature)),
    // FEAT_FLAGM
    ("flagm", Some(sym::aarch64_target_feature)),
    // FEAT_SSBS
    ("ssbs", Some(sym::aarch64_target_feature)),
    // FEAT_SB
    ("sb", Some(sym::aarch64_target_feature)),
    // FEAT_PAUTH
    ("pauth", Some(sym::aarch64_target_feature)),
    // FEAT_DPB
    ("dpb", Some(sym::aarch64_target_feature)),
    // FEAT_DPB2
    ("dpb2", Some(sym::aarch64_target_feature)),
    // FEAT_SVE2
    ("sve2", Some(sym::aarch64_target_feature)),
    // FEAT_SVE2_AES
    ("sve2-aes", Some(sym::aarch64_target_feature)),
    // FEAT_SVE2_SM4
    ("sve2-sm4", Some(sym::aarch64_target_feature)),
    // FEAT_SVE2_SHA3
    ("sve2-sha3", Some(sym::aarch64_target_feature)),
    // FEAT_SVE2_BitPerm
    ("sve2-bitperm", Some(sym::aarch64_target_feature)),
    // FEAT_FRINTTS
    ("frintts", Some(sym::aarch64_target_feature)),
    // FEAT_I8MM
    ("i8mm", Some(sym::aarch64_target_feature)),
    // FEAT_F32MM
    ("f32mm", Some(sym::aarch64_target_feature)),
    // FEAT_F64MM
    ("f64mm", Some(sym::aarch64_target_feature)),
    // FEAT_BF16
    ("bf16", Some(sym::aarch64_target_feature)),
    // FEAT_RAND
    ("rand", Some(sym::aarch64_target_feature)),
    // FEAT_BTI
    ("bti", Some(sym::aarch64_target_feature)),
    // FEAT_MTE
    ("mte", Some(sym::aarch64_target_feature)),
    // FEAT_JSCVT
    ("jsconv", Some(sym::aarch64_target_feature)),
    // FEAT_FCMA
    ("fcma", Some(sym::aarch64_target_feature)),
    // FEAT_AES
    ("aes", Some(sym::aarch64_target_feature)),
    // FEAT_SHA1 & FEAT_SHA256
    ("sha2", Some(sym::aarch64_target_feature)),
    // FEAT_SHA512 & FEAT_SHA3
    ("sha3", Some(sym::aarch64_target_feature)),
    // FEAT_SM3 & FEAT_SM4
    ("sm4", Some(sym::aarch64_target_feature)),
    // FEAT_PAN
    ("pan", Some(sym::aarch64_target_feature)),
    // FEAT_LOR
    ("lor", Some(sym::aarch64_target_feature)),
    // FEAT_VHE
    ("vh", Some(sym::aarch64_target_feature)),
    // FEAT_PMUv3
    ("pmuv3", Some(sym::aarch64_target_feature)),
    // FEAT_SPE
    ("spe", Some(sym::aarch64_target_feature)),
    ("v8.1a", Some(sym::aarch64_target_feature)),
    ("v8.2a", Some(sym::aarch64_target_feature)),
    ("v8.3a", Some(sym::aarch64_target_feature)),
    ("v8.4a", Some(sym::aarch64_target_feature)),
    ("v8.5a", Some(sym::aarch64_target_feature)),
    ("v8.6a", Some(sym::aarch64_target_feature)),
    ("v8.7a", Some(sym::aarch64_target_feature)),
];

const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
    ("adx", Some(sym::adx_target_feature)),
    ("aes", None),
    ("avx", None),
    ("avx2", None),
    ("avx512bf16", Some(sym::avx512_target_feature)),
    ("avx512bitalg", Some(sym::avx512_target_feature)),
    ("avx512bw", Some(sym::avx512_target_feature)),
    ("avx512cd", Some(sym::avx512_target_feature)),
    ("avx512dq", Some(sym::avx512_target_feature)),
    ("avx512er", Some(sym::avx512_target_feature)),
    ("avx512f", Some(sym::avx512_target_feature)),
    ("avx512gfni", Some(sym::avx512_target_feature)),
    ("avx512ifma", Some(sym::avx512_target_feature)),
    ("avx512pf", Some(sym::avx512_target_feature)),
    ("avx512vaes", Some(sym::avx512_target_feature)),
    ("avx512vbmi", Some(sym::avx512_target_feature)),
    ("avx512vbmi2", Some(sym::avx512_target_feature)),
    ("avx512vl", Some(sym::avx512_target_feature)),
    ("avx512vnni", Some(sym::avx512_target_feature)),
    ("avx512vp2intersect", Some(sym::avx512_target_feature)),
    ("avx512vpclmulqdq", Some(sym::avx512_target_feature)),
    ("avx512vpopcntdq", Some(sym::avx512_target_feature)),
    ("bmi1", None),
    ("bmi2", None),
    ("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)),
    ("ermsb", Some(sym::ermsb_target_feature)),
    ("f16c", Some(sym::f16c_target_feature)),
    ("fma", None),
    ("fxsr", None),
    ("lzcnt", None),
    ("movbe", Some(sym::movbe_target_feature)),
    ("pclmulqdq", None),
    ("popcnt", None),
    ("rdrand", None),
    ("rdseed", None),
    ("rtm", Some(sym::rtm_target_feature)),
    ("sha", None),
    ("sse", None),
    ("sse2", None),
    ("sse3", None),
    ("sse4.1", None),
    ("sse4.2", None),
    ("sse4a", Some(sym::sse4a_target_feature)),
    ("ssse3", None),
    ("tbm", Some(sym::tbm_target_feature)),
    ("xsave", None),
    ("xsavec", None),
    ("xsaveopt", None),
    ("xsaves", None),
];

const HEXAGON_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
    ("hvx", Some(sym::hexagon_target_feature)),
    ("hvx-length128b", Some(sym::hexagon_target_feature)),
];

const POWERPC_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
    ("altivec", Some(sym::powerpc_target_feature)),
    ("power8-altivec", Some(sym::powerpc_target_feature)),
    ("power9-altivec", Some(sym::powerpc_target_feature)),
    ("power8-vector", Some(sym::powerpc_target_feature)),
    ("power9-vector", Some(sym::powerpc_target_feature)),
    ("vsx", Some(sym::powerpc_target_feature)),
];

const MIPS_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] =
    &[("fp64", Some(sym::mips_target_feature)), ("msa", Some(sym::mips_target_feature))];

const RISCV_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
    ("m", Some(sym::riscv_target_feature)),
    ("a", Some(sym::riscv_target_feature)),
    ("c", Some(sym::riscv_target_feature)),
    ("f", Some(sym::riscv_target_feature)),
    ("d", Some(sym::riscv_target_feature)),
    ("e", Some(sym::riscv_target_feature)),
];

const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
    ("simd128", None),
    ("atomics", Some(sym::wasm_target_feature)),
    ("nontrapping-fptoint", Some(sym::wasm_target_feature)),
];

const BPF_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[("alu32", Some(sym::bpf_target_feature))];

/// When rustdoc is running, provide a list of all known features so that all their respective
/// primitives may be documented.
///
/// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator!
pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol>)> {
    std::iter::empty()
        .chain(ARM_ALLOWED_FEATURES.iter())
        .chain(AARCH64_ALLOWED_FEATURES.iter())
        .chain(X86_ALLOWED_FEATURES.iter())
        .chain(HEXAGON_ALLOWED_FEATURES.iter())
        .chain(POWERPC_ALLOWED_FEATURES.iter())
        .chain(MIPS_ALLOWED_FEATURES.iter())
        .chain(RISCV_ALLOWED_FEATURES.iter())
        .chain(WASM_ALLOWED_FEATURES.iter())
        .chain(BPF_ALLOWED_FEATURES.iter())
        .cloned()
}

pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Option<Symbol>)] {
    match &*sess.target.arch {
        "arm" => ARM_ALLOWED_FEATURES,
        "aarch64" => AARCH64_ALLOWED_FEATURES,
        "x86" | "x86_64" => X86_ALLOWED_FEATURES,
        "hexagon" => HEXAGON_ALLOWED_FEATURES,
        "mips" | "mips64" => MIPS_ALLOWED_FEATURES,
        "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES,
        "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES,
        "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES,
        "bpf" => BPF_ALLOWED_FEATURES,
        _ => &[],
    }
}

pub(crate) fn provide(providers: &mut Providers) {
    providers.supported_target_features = |tcx, cnum| {
        assert_eq!(cnum, LOCAL_CRATE);
        if tcx.sess.opts.actually_rustdoc {
            // rustdoc needs to be able to document functions that use all the features, so
            // whitelist them all
            all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
        } else {
            supported_target_features(tcx.sess).iter().map(|&(a, b)| (a.to_string(), b)).collect()
        }
    };
}
<|endoftext|>


<commit_before>use ui;
use ui::ncurses::*;
use ui::{CMD_ENTRY_HEIGHT, Window, Size, Position};
use std::cmp;

pub struct CommandEntry {
    parent: Window,
    child:  Window,
}

impl CommandEntry {
    pub fn new(size: Size) -> CommandEntry {
        let parent = newwin(CMD_ENTRY_HEIGHT,
                            size.width,
                            size.height - CMD_ENTRY_HEIGHT,
                            0);
        box_(parent, 0, 0);
        wrefresh(parent);

        let child = derwin(parent,
                           CMD_ENTRY_HEIGHT - 2,
                           size.width - 2,
                           1,
                           1);
        scrollok(child, true);
        keypad(child, true);

        CommandEntry {
            parent: Window::new(parent),
            child:  Window::new(child),
        }
    }

    pub fn read_input_char(&self) -> Option<char> {
        match wgetch(self.child.id) {
            -1 => None,
            i  => ::std::char::from_u32(i as u32),
        }
    }

    fn move_cursor(&self, x_pos: i32) {
        wmove(self.child.id, 0, cmp::max(x_pos, 0));
        wrefresh(self.child.id);
    }

    pub fn process_char(&self, ch: char) {
        match ch as i32 {
            KEY_BACKSPACE => self.backspace_key(),
            KEY_HOME      => self.move_cursor(0),
            KEY_DC        => self.delete_key(),
            KEY_UP | KEY_DOWN => (),
            _ => { wechochar(self.child.id, ch as u32); },
        }
    }

    fn delete_char_at(&self, index: i32) {
        self.move_cursor(index);

        wdelch(self.child.id);
        wrefresh(self.child.id);
    }

    fn backspace_key(&self) {
        let Position { x, .. } = ui::get_cursor_pos(self.child.id);
        self.delete_char_at(x - 1);
    }

    fn delete_key(&self) {
        let Position { x, .. } = ui::get_cursor_pos(self.child.id);
        self.delete_char_at(x);
    }
}<commit_msg>Block non-handled control characters from printing Fix backspace behaving like delete in certain situations<commit_after>use ui;
use ui::ncurses::*;
use ui::{CMD_ENTRY_HEIGHT, Window, Size, Position};
use std::cmp;

pub struct CommandEntry {
    parent: Window,
    child:  Window,
}

// char::is_control() checks for escape sequences,
// so we need to use our own version that works with ncurse's keypad() function
fn is_control_char(ch: char) -> bool {
    let ch = ch as i32;
    ch >= KEY_MIN && ch <= KEY_MAX
}

impl CommandEntry {
    pub fn new(size: Size) -> CommandEntry {
        let parent = newwin(CMD_ENTRY_HEIGHT,
                            size.width,
                            size.height - CMD_ENTRY_HEIGHT,
                            0);
        box_(parent, 0, 0);
        wrefresh(parent);

        let child = derwin(parent,
                           CMD_ENTRY_HEIGHT - 2,
                           size.width - 2,
                           1,
                           1);
        scrollok(child, true);
        keypad(child, true);

        CommandEntry {
            parent: Window::new(parent),
            child:  Window::new(child),
        }
    }

    pub fn read_input_char(&self) -> Option<char> {
        match wgetch(self.child.id) {
            -1 => None,
            i  => ::std::char::from_u32(i as u32),
        }
    }

    fn move_cursor(&self, x_pos: i32) {
        wmove(self.child.id, 0, cmp::max(x_pos, 0));
        wrefresh(self.child.id);
    }

    pub fn process_char(&self, ch: char) {
        if is_control_char(ch) {
            match ch as i32 {
                KEY_BACKSPACE => self.backspace_key(),
                KEY_HOME      => self.move_cursor(0),
                KEY_DC        => self.delete_key(),
                _             => (),
            }
        } else {
            wechochar(self.child.id, ch as u32);
        }
    }

    fn delete_char_at(&self, index: i32) {
        self.move_cursor(index);

        wdelch(self.child.id);
        wrefresh(self.child.id);
    }

    fn backspace_key(&self) {
        let Position { x, .. } = ui::get_cursor_pos(self.child.id);

        if x > 0 {
            self.delete_char_at(x - 1);
        }
    }

    fn delete_key(&self) {
        let Position { x, .. } = ui::get_cursor_pos(self.child.id);
        self.delete_char_at(x);
    }
}<|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/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<%helpers:shorthand name="overflow" sub_properties="overflow-x overflow-y"
                    spec="https://drafts.csswg.org/css-overflow/#propdef-overflow">
    use properties::longhands::{overflow_x, overflow_y};

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let overflow = try!(overflow_x::parse(context, input));
        Ok(Longhands {
            overflow_x: Some(overflow),
            overflow_y: Some(overflow_y::SpecifiedValue(overflow)),
        })
    }

    impl<'a> LonghandsToSerialize<'a>  {
        fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            let x_and_y_equal = match (self.overflow_x, self.overflow_y) {
                (&DeclaredValue::Value(ref x_value), &DeclaredValue::Value(ref y_container)) => {
                    *x_value == y_container.0
                },
                (&DeclaredValue::WithVariables { .. }, &DeclaredValue::WithVariables { .. }) => true,
                (&DeclaredValue::Initial, &DeclaredValue::Initial) => true,
                (&DeclaredValue::Inherit, &DeclaredValue::Inherit) => true,
                (&DeclaredValue::Unset, &DeclaredValue::Unset) => true,
                _ => false
            };

            if x_and_y_equal {
                try!(self.overflow_x.to_css(dest));
            }
            Ok(())
        }

        // Overflow does not behave like a normal shorthand. When overflow-x and overflow-y are not of equal
        // values, they no longer use the shared property name "overflow".
        // Other shorthands do not include their name in the to_css method
        pub fn to_css_declared_with_name<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            let x_and_y_equal = match (self.overflow_x, self.overflow_y) {
                (&DeclaredValue::Value(ref x_value), &DeclaredValue::Value(ref y_container)) => {
                    *x_value == y_container.0
                },
                (_, &DeclaredValue::WithVariables { .. }) |
                (&DeclaredValue::WithVariables { .. }, _) => {
                    // We don't serialize shorthands with variables
                    return dest.write_str("");
                },
                (&DeclaredValue::Initial, &DeclaredValue::Initial) => true,
                (&DeclaredValue::Inherit, &DeclaredValue::Inherit) => true,
                (&DeclaredValue::Unset, &DeclaredValue::Unset) => true,
                _ => false
            };

            if x_and_y_equal {
                try!(write!(dest, "overflow"));
                try!(write!(dest, ": "));
                try!(self.overflow_x.to_css(dest));
            } else {
                try!(write!(dest, "overflow-x"));
                try!(write!(dest, ": "));
                try!(self.overflow_x.to_css(dest));
                try!(write!(dest, "; "));

                try!(write!(dest, "overflow-y: "));
                try!(self.overflow_y.to_css(dest));
            }

            write!(dest, ";")
        }
    }
</%helpers:shorthand>

macro_rules! try_parse_one {
    ($input: expr, $var: ident, $prop_module: ident) => {
        if $var.is_none() {
            if let Ok(value) = $input.try($prop_module::SingleSpecifiedValue::parse) {
                $var = Some(value);
                continue;
            }
        }
    };
    ($context: expr, $input: expr, $var: ident, $prop_module: ident) => {
        if $var.is_none() {
            if let Ok(value) = $input.try(|i| {
                $prop_module::SingleSpecifiedValue::parse($context, i)
            }) {
                $var = Some(value);
                continue;
            }
        }
    };
}

<%helpers:shorthand name="transition" extra_prefixes="moz webkit"
                    sub_properties="transition-property transition-duration
                                    transition-timing-function
                                    transition-delay"
                    spec="https://drafts.csswg.org/css-transitions/#propdef-transition">
    use parser::Parse;
    use properties::longhands::{transition_delay, transition_duration, transition_property};
    use properties::longhands::{transition_timing_function};

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        struct SingleTransition {
            transition_property: transition_property::SingleSpecifiedValue,
            transition_duration: transition_duration::SingleSpecifiedValue,
            transition_timing_function: transition_timing_function::SingleSpecifiedValue,
            transition_delay: transition_delay::SingleSpecifiedValue,
        }

        fn parse_one_transition(context: &ParserContext, input: &mut Parser) -> Result<SingleTransition,()> {
            let (mut property, mut duration) = (None, None);
            let (mut timing_function, mut delay) = (None, None);
            loop {
                try_parse_one!(input, property, transition_property);
                try_parse_one!(context, input, duration, transition_duration);
                try_parse_one!(context, input, timing_function, transition_timing_function);
                try_parse_one!(context, input, delay, transition_delay);

                break
            }

            if let Some(property) = property {
                Ok(SingleTransition {
                    transition_property: property,
                    transition_duration:
                        duration.unwrap_or_else(transition_duration::single_value::get_initial_value),
                    transition_timing_function:
                        timing_function.unwrap_or_else(transition_timing_function::single_value
                                                                                ::get_initial_specified_value),
                    transition_delay:
                        delay.unwrap_or_else(transition_delay::single_value::get_initial_value),
                })
            } else {
                Err(())
            }
        }

        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
            return Ok(Longhands {
                transition_property: None,
                transition_duration: None,
                transition_timing_function: None,
                transition_delay: None,
            })
        }

        let results = try!(input.parse_comma_separated(|i| parse_one_transition(context, i)));
        let (mut properties, mut durations) = (Vec::new(), Vec::new());
        let (mut timing_functions, mut delays) = (Vec::new(), Vec::new());
        for result in results {
            properties.push(result.transition_property);
            durations.push(result.transition_duration);
            timing_functions.push(result.transition_timing_function);
            delays.push(result.transition_delay);
        }

        Ok(Longhands {
            transition_property: Some(transition_property::SpecifiedValue(properties)),
            transition_duration: Some(transition_duration::SpecifiedValue(durations)),
            transition_timing_function:
                Some(transition_timing_function::SpecifiedValue(timing_functions)),
            transition_delay: Some(transition_delay::SpecifiedValue(delays)),
        })
    }

    impl<'a> LonghandsToSerialize<'a>  {
        fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            try!(self.transition_property.to_css(dest));
            try!(write!(dest, " "));

            try!(self.transition_duration.to_css(dest));
            try!(write!(dest, " "));

            try!(self.transition_timing_function.to_css(dest));
            try!(write!(dest, " "));

            self.transition_delay.to_css(dest)
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="animation" extra_prefixes="moz webkit"
                    sub_properties="animation-name animation-duration
                                    animation-timing-function animation-delay
                                    animation-iteration-count animation-direction
                                    animation-fill-mode animation-play-state"
                    allowed_in_keyframe_block="False"
                    spec="https://drafts.csswg.org/css-animations/#propdef-animation">
    use parser::Parse;
    use properties::longhands::{animation_name, animation_duration, animation_timing_function};
    use properties::longhands::{animation_delay, animation_iteration_count, animation_direction};
    use properties::longhands::{animation_fill_mode, animation_play_state};

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        struct SingleAnimation {
            animation_name: animation_name::SingleSpecifiedValue,
            animation_duration: animation_duration::SingleSpecifiedValue,
            animation_timing_function: animation_timing_function::SingleSpecifiedValue,
            animation_delay: animation_delay::SingleSpecifiedValue,
            animation_iteration_count: animation_iteration_count::SingleSpecifiedValue,
            animation_direction: animation_direction::SingleSpecifiedValue,
            animation_fill_mode: animation_fill_mode::SingleSpecifiedValue,
            animation_play_state: animation_play_state::SingleSpecifiedValue,
        }

        fn parse_one_animation(context: &ParserContext, input: &mut Parser) -> Result<SingleAnimation,()> {
            let mut duration = None;
            let mut timing_function = None;
            let mut delay = None;
            let mut iteration_count = None;
            let mut direction = None;
            let mut fill_mode = None;
            let mut play_state = None;
            let mut name = None;

            // NB: Name must be the last one here so that keywords valid for other
            // longhands are not interpreted as names.
            //
            // Also, duration must be before delay, see
            // https://drafts.csswg.org/css-animations/#typedef-single-animation
            loop {
                try_parse_one!(context, input, duration, animation_duration);
                try_parse_one!(context, input, timing_function, animation_timing_function);
                try_parse_one!(context, input, delay, animation_delay);
                try_parse_one!(context, input, iteration_count, animation_iteration_count);
                try_parse_one!(input, direction, animation_direction);
                try_parse_one!(input, fill_mode, animation_fill_mode);
                try_parse_one!(input, play_state, animation_play_state);
                try_parse_one!(context, input, name, animation_name);

                break
            }

            if let Some(name) = name {
                Ok(SingleAnimation {
                    animation_name: name,
                    animation_duration:
                        duration.unwrap_or_else(animation_duration::single_value::get_initial_value),
                    animation_timing_function:
                        timing_function.unwrap_or_else(animation_timing_function::single_value
                                                                                ::get_initial_specified_value),
                    animation_delay:
                        delay.unwrap_or_else(animation_delay::single_value::get_initial_value),
                    animation_iteration_count:
                        iteration_count.unwrap_or_else(animation_iteration_count::single_value::get_initial_value),
                    animation_direction:
                        direction.unwrap_or_else(animation_direction::single_value::get_initial_value),
                    animation_fill_mode:
                        fill_mode.unwrap_or_else(animation_fill_mode::single_value::get_initial_value),
                    animation_play_state:
                        play_state.unwrap_or_else(animation_play_state::single_value::get_initial_value),
                })
            } else {
                Err(())
            }
        }

        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
            return Ok(Longhands {
                animation_name: None,
                animation_duration: None,
                animation_timing_function: None,
                animation_delay: None,
                animation_iteration_count: None,
                animation_direction: None,
                animation_fill_mode: None,
                animation_play_state: None,
            })
        }

        let results = try!(input.parse_comma_separated(|i| parse_one_animation(context, i)));

        let mut names = vec![];
        let mut durations = vec![];
        let mut timing_functions = vec![];
        let mut delays = vec![];
        let mut iteration_counts = vec![];
        let mut directions = vec![];
        let mut fill_modes = vec![];
        let mut play_states = vec![];

        for result in results.into_iter() {
            names.push(result.animation_name);
            durations.push(result.animation_duration);
            timing_functions.push(result.animation_timing_function);
            delays.push(result.animation_delay);
            iteration_counts.push(result.animation_iteration_count);
            directions.push(result.animation_direction);
            fill_modes.push(result.animation_fill_mode);
            play_states.push(result.animation_play_state);
        }

        Ok(Longhands {
            animation_name: Some(animation_name::SpecifiedValue(names)),
            animation_duration: Some(animation_duration::SpecifiedValue(durations)),
            animation_timing_function: Some(animation_timing_function::SpecifiedValue(timing_functions)),
            animation_delay: Some(animation_delay::SpecifiedValue(delays)),
            animation_iteration_count: Some(animation_iteration_count::SpecifiedValue(iteration_counts)),
            animation_direction: Some(animation_direction::SpecifiedValue(directions)),
            animation_fill_mode: Some(animation_fill_mode::SpecifiedValue(fill_modes)),
            animation_play_state: Some(animation_play_state::SpecifiedValue(play_states)),
        })
    }

    impl<'a> LonghandsToSerialize<'a>  {
        fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            try!(self.animation_duration.to_css(dest));
            try!(write!(dest, " "));

            // FIXME: timing function is displaying the actual mathematical name "cubic-bezier(0.25, 0.1, 0.25, 1)"
            // instead of the common name "ease"
            try!(self.animation_timing_function.to_css(dest));
            try!(write!(dest, " "));

            try!(self.animation_delay.to_css(dest));
            try!(write!(dest, " "));

            try!(self.animation_direction.to_css(dest));
            try!(write!(dest, " "));

            try!(self.animation_fill_mode.to_css(dest));
            try!(write!(dest, " "));

            try!(self.animation_iteration_count.to_css(dest));
            try!(write!(dest, " "));

            try!(self.animation_play_state.to_css(dest));
            try!(write!(dest, " "));

            self.animation_name.to_css(dest)
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="scroll-snap-type" products="gecko"
                    sub_properties="scroll-snap-type-x scroll-snap-type-y"
                    spec="https://drafts.csswg.org/css-scroll-snap/#propdef-scroll-snap-type">
    use properties::longhands::scroll_snap_type_x;

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let result = try!(scroll_snap_type_x::parse(context, input));
        Ok(Longhands {
            scroll_snap_type_x: Some(result),
            scroll_snap_type_y: Some(result),
        })
    }

    impl<'a> LonghandsToSerialize<'a>  {
        // Serializes into the single keyword value if both scroll-snap-type and scroll-snap-type-y are same.
        // Otherwise into an empty string. This is done to match Gecko's behaviour.
        fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            let x_and_y_equal = match (self.scroll_snap_type_x, self.scroll_snap_type_y) {
                (&DeclaredValue::Value(ref x_value), &DeclaredValue::Value(ref y_value)) => {
                    *x_value == *y_value
                },
                (&DeclaredValue::Initial, &DeclaredValue::Initial) => true,
                (&DeclaredValue::Inherit, &DeclaredValue::Inherit) => true,
                (&DeclaredValue::Unset, &DeclaredValue::Unset) => true,
                (x, y) => { *x == *y },
            };

            if x_and_y_equal {
                self.scroll_snap_type_x.to_css(dest)
            } else {
                Ok(())
            }
        }
    }
</%helpers:shorthand>
<commit_msg>Auto merge of #15429 - z1mvader:master, r=jdm<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/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<%helpers:shorthand name="overflow" sub_properties="overflow-x overflow-y"
                    spec="https://drafts.csswg.org/css-overflow/#propdef-overflow">
    use properties::longhands::{overflow_x, overflow_y};

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let overflow = try!(overflow_x::parse(context, input));
        Ok(Longhands {
            overflow_x: Some(overflow),
            overflow_y: Some(overflow_y::SpecifiedValue(overflow)),
        })
    }

    impl<'a> LonghandsToSerialize<'a>  {
        fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            let x_and_y_equal = match (self.overflow_x, self.overflow_y) {
                (&DeclaredValue::Value(ref x_value), &DeclaredValue::Value(ref y_container)) => {
                    *x_value == y_container.0
                },
                (&DeclaredValue::WithVariables { .. }, &DeclaredValue::WithVariables { .. }) => true,
                (&DeclaredValue::Initial, &DeclaredValue::Initial) => true,
                (&DeclaredValue::Inherit, &DeclaredValue::Inherit) => true,
                (&DeclaredValue::Unset, &DeclaredValue::Unset) => true,
                _ => false
            };

            if x_and_y_equal {
                try!(self.overflow_x.to_css(dest));
            }
            Ok(())
        }

        // Overflow does not behave like a normal shorthand. When overflow-x and overflow-y are not of equal
        // values, they no longer use the shared property name "overflow".
        // Other shorthands do not include their name in the to_css method
        pub fn to_css_declared_with_name<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            let x_and_y_equal = match (self.overflow_x, self.overflow_y) {
                (&DeclaredValue::Value(ref x_value), &DeclaredValue::Value(ref y_container)) => {
                    *x_value == y_container.0
                },
                (_, &DeclaredValue::WithVariables { .. }) |
                (&DeclaredValue::WithVariables { .. }, _) => {
                    // We don't serialize shorthands with variables
                    return dest.write_str("");
                },
                (&DeclaredValue::Initial, &DeclaredValue::Initial) => true,
                (&DeclaredValue::Inherit, &DeclaredValue::Inherit) => true,
                (&DeclaredValue::Unset, &DeclaredValue::Unset) => true,
                _ => false
            };

            if x_and_y_equal {
                try!(write!(dest, "overflow"));
                try!(write!(dest, ": "));
                try!(self.overflow_x.to_css(dest));
            } else {
                try!(write!(dest, "overflow-x"));
                try!(write!(dest, ": "));
                try!(self.overflow_x.to_css(dest));
                try!(write!(dest, "; "));

                try!(write!(dest, "overflow-y: "));
                try!(self.overflow_y.to_css(dest));
            }

            write!(dest, ";")
        }
    }
</%helpers:shorthand>

macro_rules! try_parse_one {
    ($input: expr, $var: ident, $prop_module: ident) => {
        if $var.is_none() {
            if let Ok(value) = $input.try($prop_module::SingleSpecifiedValue::parse) {
                $var = Some(value);
                continue;
            }
        }
    };
    ($context: expr, $input: expr, $var: ident, $prop_module: ident) => {
        if $var.is_none() {
            if let Ok(value) = $input.try(|i| {
                $prop_module::SingleSpecifiedValue::parse($context, i)
            }) {
                $var = Some(value);
                continue;
            }
        }
    };
}

<%helpers:shorthand name="transition" extra_prefixes="moz webkit"
                    sub_properties="transition-property transition-duration
                                    transition-timing-function
                                    transition-delay"
                    spec="https://drafts.csswg.org/css-transitions/#propdef-transition">
    use parser::Parse;
    use properties::longhands::{transition_delay, transition_duration, transition_property};
    use properties::longhands::{transition_timing_function};

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        struct SingleTransition {
            transition_property: transition_property::SingleSpecifiedValue,
            transition_duration: transition_duration::SingleSpecifiedValue,
            transition_timing_function: transition_timing_function::SingleSpecifiedValue,
            transition_delay: transition_delay::SingleSpecifiedValue,
        }

        fn parse_one_transition(context: &ParserContext, input: &mut Parser) -> Result<SingleTransition,()> {
            let (mut property, mut duration) = (None, None);
            let (mut timing_function, mut delay) = (None, None);
            loop {
                try_parse_one!(input, property, transition_property);
                try_parse_one!(context, input, duration, transition_duration);
                try_parse_one!(context, input, timing_function, transition_timing_function);
                try_parse_one!(context, input, delay, transition_delay);

                break
            }

            if let Some(property) = property {
                Ok(SingleTransition {
                    transition_property: property,
                    transition_duration:
                        duration.unwrap_or_else(transition_duration::single_value::get_initial_value),
                    transition_timing_function:
                        timing_function.unwrap_or_else(transition_timing_function::single_value
                                                                                ::get_initial_specified_value),
                    transition_delay:
                        delay.unwrap_or_else(transition_delay::single_value::get_initial_value),
                })
            } else {
                Err(())
            }
        }

        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
            return Ok(Longhands {
                transition_property: None,
                transition_duration: None,
                transition_timing_function: None,
                transition_delay: None,
            })
        }

        let results = try!(input.parse_comma_separated(|i| parse_one_transition(context, i)));
        let (mut properties, mut durations) = (Vec::new(), Vec::new());
        let (mut timing_functions, mut delays) = (Vec::new(), Vec::new());
        for result in results {
            properties.push(result.transition_property);
            durations.push(result.transition_duration);
            timing_functions.push(result.transition_timing_function);
            delays.push(result.transition_delay);
        }

        Ok(Longhands {
            transition_property: Some(transition_property::SpecifiedValue(properties)),
            transition_duration: Some(transition_duration::SpecifiedValue(durations)),
            transition_timing_function:
                Some(transition_timing_function::SpecifiedValue(timing_functions)),
            transition_delay: Some(transition_delay::SpecifiedValue(delays)),
        })
    }

    impl<'a> LonghandsToSerialize<'a>  {
        fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            try!(self.transition_property.to_css(dest));
            try!(write!(dest, " "));

            try!(self.transition_duration.to_css(dest));
            try!(write!(dest, " "));

            try!(self.transition_timing_function.to_css(dest));
            try!(write!(dest, " "));

            self.transition_delay.to_css(dest)
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="animation" extra_prefixes="moz webkit"
                    sub_properties="animation-name animation-duration
                                    animation-timing-function animation-delay
                                    animation-iteration-count animation-direction
                                    animation-fill-mode animation-play-state"
                    allowed_in_keyframe_block="False"
                    spec="https://drafts.csswg.org/css-animations/#propdef-animation">
    use parser::Parse;
    use properties::longhands::{animation_name, animation_duration, animation_timing_function};
    use properties::longhands::{animation_delay, animation_iteration_count, animation_direction};
    use properties::longhands::{animation_fill_mode, animation_play_state};

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        struct SingleAnimation {
            animation_name: animation_name::SingleSpecifiedValue,
            animation_duration: animation_duration::SingleSpecifiedValue,
            animation_timing_function: animation_timing_function::SingleSpecifiedValue,
            animation_delay: animation_delay::SingleSpecifiedValue,
            animation_iteration_count: animation_iteration_count::SingleSpecifiedValue,
            animation_direction: animation_direction::SingleSpecifiedValue,
            animation_fill_mode: animation_fill_mode::SingleSpecifiedValue,
            animation_play_state: animation_play_state::SingleSpecifiedValue,
        }

        fn parse_one_animation(context: &ParserContext, input: &mut Parser) -> Result<SingleAnimation,()> {
            let mut duration = None;
            let mut timing_function = None;
            let mut delay = None;
            let mut iteration_count = None;
            let mut direction = None;
            let mut fill_mode = None;
            let mut play_state = None;
            let mut name = None;

            // NB: Name must be the last one here so that keywords valid for other
            // longhands are not interpreted as names.
            //
            // Also, duration must be before delay, see
            // https://drafts.csswg.org/css-animations/#typedef-single-animation
            loop {
                try_parse_one!(context, input, duration, animation_duration);
                try_parse_one!(context, input, timing_function, animation_timing_function);
                try_parse_one!(context, input, delay, animation_delay);
                try_parse_one!(context, input, iteration_count, animation_iteration_count);
                try_parse_one!(input, direction, animation_direction);
                try_parse_one!(input, fill_mode, animation_fill_mode);
                try_parse_one!(input, play_state, animation_play_state);
                try_parse_one!(context, input, name, animation_name);

                break
            }

            if let Some(name) = name {
                Ok(SingleAnimation {
                    animation_name: name,
                    animation_duration:
                        duration.unwrap_or_else(animation_duration::single_value::get_initial_value),
                    animation_timing_function:
                        timing_function.unwrap_or_else(animation_timing_function::single_value
                                                                                ::get_initial_specified_value),
                    animation_delay:
                        delay.unwrap_or_else(animation_delay::single_value::get_initial_value),
                    animation_iteration_count:
                        iteration_count.unwrap_or_else(animation_iteration_count::single_value::get_initial_value),
                    animation_direction:
                        direction.unwrap_or_else(animation_direction::single_value::get_initial_value),
                    animation_fill_mode:
                        fill_mode.unwrap_or_else(animation_fill_mode::single_value::get_initial_value),
                    animation_play_state:
                        play_state.unwrap_or_else(animation_play_state::single_value::get_initial_value),
                })
            } else {
                Err(())
            }
        }

        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
            return Ok(Longhands {
                animation_name: None,
                animation_duration: None,
                animation_timing_function: None,
                animation_delay: None,
                animation_iteration_count: None,
                animation_direction: None,
                animation_fill_mode: None,
                animation_play_state: None,
            })
        }

        let results = try!(input.parse_comma_separated(|i| parse_one_animation(context, i)));

        let mut names = vec![];
        let mut durations = vec![];
        let mut timing_functions = vec![];
        let mut delays = vec![];
        let mut iteration_counts = vec![];
        let mut directions = vec![];
        let mut fill_modes = vec![];
        let mut play_states = vec![];

        for result in results.into_iter() {
            names.push(result.animation_name);
            durations.push(result.animation_duration);
            timing_functions.push(result.animation_timing_function);
            delays.push(result.animation_delay);
            iteration_counts.push(result.animation_iteration_count);
            directions.push(result.animation_direction);
            fill_modes.push(result.animation_fill_mode);
            play_states.push(result.animation_play_state);
        }

        Ok(Longhands {
            animation_name: Some(animation_name::SpecifiedValue(names)),
            animation_duration: Some(animation_duration::SpecifiedValue(durations)),
            animation_timing_function: Some(animation_timing_function::SpecifiedValue(timing_functions)),
            animation_delay: Some(animation_delay::SpecifiedValue(delays)),
            animation_iteration_count: Some(animation_iteration_count::SpecifiedValue(iteration_counts)),
            animation_direction: Some(animation_direction::SpecifiedValue(directions)),
            animation_fill_mode: Some(animation_fill_mode::SpecifiedValue(fill_modes)),
            animation_play_state: Some(animation_play_state::SpecifiedValue(play_states)),
        })
    }

    impl<'a> LonghandsToSerialize<'a>  {
        fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            try!(self.animation_duration.to_css(dest));
            try!(write!(dest, " "));

            try!(self.animation_timing_function.to_css(dest));
            try!(write!(dest, " "));

            try!(self.animation_delay.to_css(dest));
            try!(write!(dest, " "));

            try!(self.animation_direction.to_css(dest));
            try!(write!(dest, " "));

            try!(self.animation_fill_mode.to_css(dest));
            try!(write!(dest, " "));

            try!(self.animation_iteration_count.to_css(dest));
            try!(write!(dest, " "));

            try!(self.animation_play_state.to_css(dest));
            try!(write!(dest, " "));

            self.animation_name.to_css(dest)
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="scroll-snap-type" products="gecko"
                    sub_properties="scroll-snap-type-x scroll-snap-type-y"
                    spec="https://drafts.csswg.org/css-scroll-snap/#propdef-scroll-snap-type">
    use properties::longhands::scroll_snap_type_x;

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let result = try!(scroll_snap_type_x::parse(context, input));
        Ok(Longhands {
            scroll_snap_type_x: Some(result),
            scroll_snap_type_y: Some(result),
        })
    }

    impl<'a> LonghandsToSerialize<'a>  {
        // Serializes into the single keyword value if both scroll-snap-type and scroll-snap-type-y are same.
        // Otherwise into an empty string. This is done to match Gecko's behaviour.
        fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            let x_and_y_equal = match (self.scroll_snap_type_x, self.scroll_snap_type_y) {
                (&DeclaredValue::Value(ref x_value), &DeclaredValue::Value(ref y_value)) => {
                    *x_value == *y_value
                },
                (&DeclaredValue::Initial, &DeclaredValue::Initial) => true,
                (&DeclaredValue::Inherit, &DeclaredValue::Inherit) => true,
                (&DeclaredValue::Unset, &DeclaredValue::Unset) => true,
                (x, y) => { *x == *y },
            };

            if x_and_y_equal {
                self.scroll_snap_type_x.to_css(dest)
            } else {
                Ok(())
            }
        }
    }
</%helpers:shorthand>
<|endoftext|>


<commit_before>// Copyright 2014 Dmitry "Divius" Tantsur <divius.inside@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//

use std::from_str::FromStr;
use std::io::net::ip;
use std::sync;

use num;
use serialize;

/// Trait representing table with known nodes.
///
/// Keeps some reasonable subset of known nodes passed to `update`.
#[unstable]
pub trait GenericNodeTable : Send + Sync {
    /// Generate suitable random ID.
    #[experimental]
    fn random_id(&self) -> num::BigUint;
    /// Store or update node in the table.
    fn update(&mut self, node: &Node) -> bool;
    /// Find given number of node, closest to given ID.
    fn find(&self, id: &num::BigUint, count: uint) -> Vec<Node>;
    /// Pop expired or the oldest nodes from table for inspection.
    fn pop_oldest(&mut self) -> Vec<Node>;
}

/// Trait representing DHT implementation.
///
/// This is a minimal set of functions expected on any DHT.
#[experimental]
pub trait GenericService : Send + Sync {
    /// Ping a node, returning true if node seems reachable.
    fn ping(&self, node: &Node) -> sync::Future<bool>;
    /// Find a node with given ID.
    fn find_node(&self, id: &num::BigUint) -> sync::Future<Option<Node>>;
}

/// Structure representing a node in system.
///
/// Every node has an address (IP and port) and a numeric ID, which is
/// used to calculate metrics and look up data.
#[deriving(Clone, Show)]
#[unstable]
pub struct Node {
    /// Network address of the node.
    pub address: ip::SocketAddr,
    /// ID of the node.
    pub id: num::BigUint
}

impl<E, S:serialize::Encoder<E>> serialize::Encodable<S, E> for Node {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_struct("Node", 2, |s| {
            try!(s.emit_struct_field("address", 0, |s2| {
                let addr = format!("{}", self.address);
                addr.encode(s2)
            }));

            try!(s.emit_struct_field("id", 1, |s2| {
                let id = format!("{}", self.id);
                id.encode(s2)
            }));

            Ok(())
        })
    }
}

impl<E, D:serialize::Decoder<E>> serialize::Decodable<D, E> for Node {
    fn decode(d: &mut D) -> Result<Node, E> {
        d.read_struct("Node", 2, |d| {
            let addr = try!(d.read_struct_field("address", 0, |d2| {
                let s = try!(d2.read_str());
                match FromStr::from_str(s.as_slice()) {
                    Some(addr) => Ok(addr),
                    None => {
                        let err = format!("Expected socket address, got {}", s);
                        Err(d2.error(err.as_slice()))
                    }
                }
            }));

            let id = try!(d.read_struct_field("id", 1, |d2| {
                let s = try!(d2.read_str());
                match FromStr::from_str(s.as_slice()) {
                    Some(id) => Ok(id),
                    None => {
                        let err = format!("Expected ID, got {}", s);
                        Err(d2.error(err.as_slice()))
                    }
                }
            }));

            Ok(Node { address: addr, id: id })
        })
    }
}

#[cfg(test)]
mod test {
    use serialize::json;

    use super::Node;

    use super::super::utils::test;

    #[deriving(Show, Clone, Encodable, Decodable)]
    struct SimplifiedNode {
        address: String,
        id: String
    }

    #[test]
    fn test_node_encode() {
        let n = test::new_node(42);
        let j = json::encode(&n);
        let m: SimplifiedNode = json::decode(j.as_slice()).unwrap();
        assert_eq!(test::ADDR, m.address.as_slice());
        assert_eq!("42", m.id.as_slice());
    }

    #[test]
    fn test_node_decode() {
        let sn = SimplifiedNode {
            address: "127.0.0.1:80".to_string(),
            id: "42".to_string()
        };
        let j = json::encode(&sn);
        let n: Node = json::decode(j.as_slice()).unwrap();
        assert_eq!(42, n.id.to_uint().unwrap());
    }

    #[test]
    fn test_node_decode_bad_address() {
        let sn = SimplifiedNode {
            address: "127.0.0.1".to_string(),
            id: "42".to_string()
        };
        let j = json::encode(&sn);
        assert!(json::decode::<Node>(j.as_slice()).is_err());
    }

    #[test]
    fn test_node_decode_bad_id() {
        let sn = SimplifiedNode {
            address: "127.0.0.1:80".to_string(),
            id: "x42".to_string()
        };
        let j = json::encode(&sn);
        assert!(json::decode::<Node>(j.as_slice()).is_err());
    }

    #[test]
    fn test_node_encode_decode() {
        let n = test::new_node(42);
        let j = json::encode(&n);
        let n2 = json::decode::<Node>(j.as_slice()).unwrap();
        assert_eq!(n.id, n2.id);
        assert_eq!(n.address, n2.address);
    }
}
<commit_msg>Remainings for refactoring<commit_after>// Copyright 2014 Dmitry "Divius" Tantsur <divius.inside@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//

use std::from_str::FromStr;
use std::io::net::ip;

use num;
use serialize;

/// Trait representing table with known nodes.
///
/// Keeps some reasonable subset of known nodes passed to `update`.
#[unstable]
pub trait GenericNodeTable : Send + Sync {
    /// Generate suitable random ID.
    #[experimental]
    fn random_id(&self) -> num::BigUint;
    /// Store or update node in the table.
    fn update(&mut self, node: &Node) -> bool;
    /// Find given number of node, closest to given ID.
    fn find(&self, id: &num::BigUint, count: uint) -> Vec<Node>;
    /// Pop expired or the oldest nodes from table for inspection.
    fn pop_oldest(&mut self) -> Vec<Node>;
}

/// Structure representing a node in system.
///
/// Every node has an address (IP and port) and a numeric ID, which is
/// used to calculate metrics and look up data.
#[deriving(Clone, Show)]
#[unstable]
pub struct Node {
    /// Network address of the node.
    pub address: ip::SocketAddr,
    /// ID of the node.
    pub id: num::BigUint
}

impl<E, S:serialize::Encoder<E>> serialize::Encodable<S, E> for Node {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_struct("Node", 2, |s| {
            try!(s.emit_struct_field("address", 0, |s2| {
                let addr = format!("{}", self.address);
                addr.encode(s2)
            }));

            try!(s.emit_struct_field("id", 1, |s2| {
                let id = format!("{}", self.id);
                id.encode(s2)
            }));

            Ok(())
        })
    }
}

impl<E, D:serialize::Decoder<E>> serialize::Decodable<D, E> for Node {
    fn decode(d: &mut D) -> Result<Node, E> {
        d.read_struct("Node", 2, |d| {
            let addr = try!(d.read_struct_field("address", 0, |d2| {
                let s = try!(d2.read_str());
                match FromStr::from_str(s.as_slice()) {
                    Some(addr) => Ok(addr),
                    None => {
                        let err = format!("Expected socket address, got {}", s);
                        Err(d2.error(err.as_slice()))
                    }
                }
            }));

            let id = try!(d.read_struct_field("id", 1, |d2| {
                let s = try!(d2.read_str());
                match FromStr::from_str(s.as_slice()) {
                    Some(id) => Ok(id),
                    None => {
                        let err = format!("Expected ID, got {}", s);
                        Err(d2.error(err.as_slice()))
                    }
                }
            }));

            Ok(Node { address: addr, id: id })
        })
    }
}

#[cfg(test)]
mod test {
    use serialize::json;

    use super::Node;

    use super::super::utils::test;

    #[deriving(Show, Clone, Encodable, Decodable)]
    struct SimplifiedNode {
        address: String,
        id: String
    }

    #[test]
    fn test_node_encode() {
        let n = test::new_node(42);
        let j = json::encode(&n);
        let m: SimplifiedNode = json::decode(j.as_slice()).unwrap();
        assert_eq!(test::ADDR, m.address.as_slice());
        assert_eq!("42", m.id.as_slice());
    }

    #[test]
    fn test_node_decode() {
        let sn = SimplifiedNode {
            address: "127.0.0.1:80".to_string(),
            id: "42".to_string()
        };
        let j = json::encode(&sn);
        let n: Node = json::decode(j.as_slice()).unwrap();
        assert_eq!(42, n.id.to_uint().unwrap());
    }

    #[test]
    fn test_node_decode_bad_address() {
        let sn = SimplifiedNode {
            address: "127.0.0.1".to_string(),
            id: "42".to_string()
        };
        let j = json::encode(&sn);
        assert!(json::decode::<Node>(j.as_slice()).is_err());
    }

    #[test]
    fn test_node_decode_bad_id() {
        let sn = SimplifiedNode {
            address: "127.0.0.1:80".to_string(),
            id: "x42".to_string()
        };
        let j = json::encode(&sn);
        assert!(json::decode::<Node>(j.as_slice()).is_err());
    }

    #[test]
    fn test_node_encode_decode() {
        let n = test::new_node(42);
        let j = json::encode(&n);
        let n2 = json::decode::<Node>(j.as_slice()).unwrap();
        assert_eq!(n.id, n2.id);
        assert_eq!(n.address, n2.address);
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 Luis de Bethencourt <luis@debethencourt.com>
// Copyright 2013 The Rust Project Developers
// http://rust-lang.org

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

/*!
 * Gregorian Calendar module for the datetime library of the Rust programming
 * language
 *
 * Implements a hybrid calendar that supports both the Julian and Gregorian
 * calendar systems.
 *
 * http://en.wikipedia.org/wiki/Gregorian_calendar
 * http://en.wikipedia.org/wiki/Julian_calendar
 */

static YEAR_BASE: int = 1900;
static DAYSPERLYEAR: uint = 366;
static DAYSPERNYEAR: uint = 365;
static DAYSPERWEEK: uint = 7;

pub fn is_leap_year(year: uint) -> bool {
    (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))
}

pub fn year_size(year: uint) -> uint {
    if is_leap_year(year) { DAYSPERLYEAR } else { DAYSPERNYEAR }
}

pub struct GCalendar {
    /*
     * Calendar object with date and time.
     */
    sec: uint,         /* Seconds       [0-59]  */
    min: uint,         /* Minutes       [0-59]  */
    hour: uint,        /* Hours         [0-23]  */
    mday: uint,        /* Day           [0-30]  */
    month: uint,       /* Month         [0-11]  */
    year: uint,        /* Year - 1900           */
    wday: uint,        /* Day of week   [0-6]   */
    yday: uint         /* Days in year  [0-365] */
}

impl GCalendar {
    /**
    * Allocates a GCalendar object at epoch.
    */
    pub fn new_at_epoch() -> GCalendar {
        GCalendar {
            sec: 0,
            min: 0,
            hour: 0,
            mday: 0,
            month: 0,
            year: 0,
            wday: 0,
            yday: 0,
        }
    }

    /**
    * Allocates a GCalendar object at the given date and time.
    */
    pub fn new(sec: uint, min: uint, hour: uint, mday: uint, month: uint,
            year: uint, wday: uint, yday: uint) -> GCalendar {
        GCalendar {
            sec: sec,
            min: min,
            hour: hour,
            mday: mday,
            month: month,
            year: year,
            wday: wday,
            yday: yday,
        }
    }

    /**
    * Allocates a GCalendar object from the milliseconds elapsed since epoch.
    */
    pub fn new_from_epoch(since_epoch: uint) -> GCalendar {
        let epoch_year = 1970;
        let mut year = epoch_year;

        let millisecs_day = 86400000;

        let mut dayclock = since_epoch % millisecs_day;
        let mut dayno = since_epoch / millisecs_day;

        let hour = dayclock / 3600000;
        dayclock = dayclock - (hour * 3600000);

        let min = dayclock / 60000;
        dayclock = dayclock - (min * 60000);

        let sec = dayclock / 1000;

        while (dayno >= year_size(year)) {
            dayno -= year_size(year);
            year += 1;
        }
        let year = year;

        GCalendar {
            sec: sec,
            min: min,
            hour: hour,
            mday: 0,
            month: 0,
            year: year,
            wday: 0,
            yday: dayno,
        }
    }

    pub fn get_sec(&self) -> uint {
        self.sec
    }

    pub fn get_min(&self) -> uint {
        self.min
    }

    pub fn get_hour(&self) -> uint {
        self.hour
    }

    pub fn get_year(&self) -> uint {
        self.year
    }

    pub fn get_day_of_year(&self) -> uint {
        self.yday
    }

    pub fn get_date(&self) -> ~str {
        // ToDo
        ~""
    }
}

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

    #[test]
    fn new() {
        let gc = GCalendar::new(21, 0, 12, 23, 9, 1983, 5, 265);
        assert_eq!(gc.get_sec(), 21);
        assert_eq!(gc.get_min(), 0);
        assert_eq!(gc.get_hour(), 12);
        assert_eq!(gc.get_year(), 1983);
        assert_eq!(gc.get_day_of_year(), 265);
    }

    fn new_from_epoch() {
        let gc = GCalendar::new_from_epoch(433166421023);
        assert_eq!(gc.get_sec(), 21);
        assert_eq!(gc.get_min(), 0);
        assert_eq!(gc.get_hour(), 12);
        assert_eq!(gc.get_year(), 1983);
        assert_eq!(gc.get_day_of_year(), 265);
    }
}
<commit_msg>gcalendar.rs: complete date from epoch<commit_after>// Copyright 2013 Luis de Bethencourt <luis@debethencourt.com>
// Copyright 2013 The Rust Project Developers
// http://rust-lang.org

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

/*!
 * Gregorian Calendar module for the datetime library of the Rust programming
 * language
 *
 * Implements a hybrid calendar that supports both the Julian and Gregorian
 * calendar systems.
 *
 * http://en.wikipedia.org/wiki/Gregorian_calendar
 * http://en.wikipedia.org/wiki/Julian_calendar
 */

static YEARBASE: int = 1900;
static DAYSPERLYEAR: uint = 366;
static DAYSPERNYEAR: uint = 365;
static DAYSPERWEEK: uint = 7;
//static DAYSBEFOREMONTH: ~[~[uint]] = [
static DAYSBEFOREMONTH: [[uint, ..13], ..2] = [
    /* Normal years */
    [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365],
    /* Leap years */
    [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]
];

pub fn is_leap_year(year: uint) -> bool {
    (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))
}

pub fn year_size(year: uint) -> uint {
    if is_leap_year(year) { DAYSPERLYEAR } else { DAYSPERNYEAR }
}

pub struct GCalendar {
    /*
     * Calendar object with date and time.
     */
    sec: uint,         /* Seconds       [0-59]  */
    min: uint,         /* Minutes       [0-59]  */
    hour: uint,        /* Hours         [0-23]  */
    mday: uint,        /* Day           [0-30]  */
    month: uint,       /* Month         [0-11]  */
    year: uint,        /* Year - 1900           */
    wday: uint,        /* Day of week   [0-6]   */
    yday: uint         /* Days in year  [0-365] */
}

impl GCalendar {
    /**
    * Allocates a GCalendar object at epoch.
    */
    pub fn new_at_epoch() -> GCalendar {
        GCalendar {
            sec: 0,
            min: 0,
            hour: 0,
            mday: 0,
            month: 0,
            year: 0,
            wday: 0,
            yday: 0,
        }
    }

    /**
    * Allocates a GCalendar object at the given date and time.
    */
    pub fn new(sec: uint, min: uint, hour: uint, mday: uint, month: uint,
            year: uint, wday: uint, yday: uint) -> GCalendar {
        GCalendar {
            sec: sec,
            min: min,
            hour: hour,
            mday: mday,
            month: month,
            year: year,
            wday: wday,
            yday: yday,
        }
    }

    /**
    * Allocates a GCalendar object from the milliseconds elapsed since epoch.
    */
    pub fn new_from_epoch(since_epoch: uint) -> GCalendar {
        let epoch_year = 1970;
        let mut year = epoch_year;

        let millisecs_day = 86400000;

        let mut dayclock = since_epoch % millisecs_day;
        let mut dayno = since_epoch / millisecs_day;

        let hour = dayclock / 3600000;
        dayclock = dayclock - (hour * 3600000);
        let min = dayclock / 60000;
        dayclock = dayclock - (min * 60000);
        let sec = dayclock / 1000;
        let wday = (dayno + 4) % 7;

        while (dayno >= year_size(year)) {
            dayno -= year_size(year);
            year += 1;
        }
        let yday = dayno;

        let ip = DAYSBEFOREMONTH[if is_leap_year(year) {1} else {0}];
        let mut month = 11;
        while (dayno < ip[month]) {
            month -= 1;
        }
        dayno -= ip[month];

        GCalendar {
            sec: sec,
            min: min,
            hour: hour,
            mday: dayno + 1,
            month: month  + 1,
            year: year,
            wday: wday,
            yday: yday,
        }
    }

    pub fn get_sec(&self) -> uint {
        self.sec
    }

    pub fn get_min(&self) -> uint {
        self.min
    }

    pub fn get_hour(&self) -> uint {
        self.hour
    }

    pub fn get_day_of_month(&self) -> uint {
        self.mday
    }

    pub fn get_month(&self) -> uint {
        self.month
    }

    pub fn get_year(&self) -> uint {
        self.year
    }

    pub fn get_day_of_week(&self) -> uint {
        self.wday
    }

    pub fn get_day_of_year(&self) -> uint {
        self.yday
    }

    pub fn get_date(&self) -> ~str {
        // ToDo
        ~""
    }
}

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

    #[test]
    fn new() {
        let gc = GCalendar::new(21, 0, 12, 23, 9, 1983, 5, 265);
        assert_eq!(gc.get_sec(), 21);
        assert_eq!(gc.get_min(), 0);
        assert_eq!(gc.get_hour(), 12);
        assert_eq!(gc.get_day_of_month(), 23);
        assert_eq!(gc.get_month(), 9);
        assert_eq!(gc.get_year(), 1983);
        assert_eq!(gc.get_day_of_week(), 5);
        assert_eq!(gc.get_day_of_year(), 265);
    }

    #[test]
    fn new_from_epoch() {
        let gc = GCalendar::new_from_epoch(433166421023);
        assert_eq!(gc.get_sec(), 21);
        assert_eq!(gc.get_min(), 0);
        assert_eq!(gc.get_hour(), 12);
        assert_eq!(gc.get_day_of_month(), 23);
        assert_eq!(gc.get_month(), 9);
        assert_eq!(gc.get_year(), 1983);
        assert_eq!(gc.get_day_of_week(), 5);
        assert_eq!(gc.get_day_of_year(), 265);
    }
}
<|endoftext|>


<commit_before>#![feature(custom_derive, plugin, custom_attribute, box_syntax)]
#![plugin(docopt_macros)]
extern crate serde_json;
extern crate serde;
extern crate pbr;
extern crate regex;
extern crate curl;
extern crate docopt;
extern crate rustc_serialize;
extern crate env_logger;
#[macro_use] extern crate log;
#[macro_use] extern crate sonicd;

mod util;

use std::path::PathBuf;
use pbr::ProgressBar;
use sonicd::*;
use util::*;
use std::process;
use std::io::{Write, self};
use serde_json::Value;

docopt!(Args derive Debug, "
.
                           d8b
                           Y8P

.d8888b   .d88b.  88888b.  888  .d8888b
88K      d88\"\"88b 888 \"88b 888 d88P\"
\"Y8888b. 888  888 888  888 888 888
     X88 Y88..88P 888  888 888 Y88b.
 88888P'  \"Y88P\"  888  888 888  \"Y8888P

Usage:
  sonic <source> [-d <var>...] [options] -e <query>
  sonic <source> [-d <var>...] [options] -f <file>
  sonic -h | --help
  sonic --version

Options:
  --execute, -e         run command literal
  --file, -f            run command from file
  -c <config>           use config file (default: $HOME/.sonicrc)
  -d                    inject variable name to value (i.e. -d foo=bar)
  -r, --rows-only       print rows only
  -h, --help            show this message
  --version             show daemon and cli version
");

static VERSION: &'static str = env!("CARGO_PKG_VERSION");
static COMMIT: Option<&'static str> = option_env!("SONIC_COMMIT");

fn _main(args: Args) -> Result<Receipt> {

    let config: ClientConfig = if args.flag_c != "" {
        debug!("sourcing passed config in path '{:?}'", &args.flag_c);
        try!(read_cfg(PathBuf::from(args.flag_c.clone())))
    } else {
        debug!("sourcing default config in path '$HOME/.sonicrc'");
        try!(source_sonicrc())
    };

    let vars = try!(split_key_value(&args.arg_var));

    let query = if args.flag_file {
        try!(read_file_contents(PathBuf::from(&args.arg_file)))
    } else if args.flag_execute {
        args.arg_query.clone()
    } else {
        let daemon_v = try!(version(&config.sonicd, &config.http_port)
                            .map_err(|e| Receipt::error(format!("{}", e))));

        println!("sonic cli version {} ({}); daemon version {}",
        VERSION,
        COMMIT.unwrap_or_else(|| "unknown-commit"),
        daemon_v);
        return Ok(Receipt::success());
    };

    let injected = try!(inject_vars(&query, &vars));

    let query = try!(build(&args.arg_source, config.sources.clone(), &injected));

    let mut pb = ProgressBar::new(100);
    pb.format("╢░░_╟");

    let fn_out = |msg: SonicMessage| {
        match msg.payload {
            Some(Value::Array(d)) => {
                println!("{}", d.iter().fold(String::new(), |acc, x| {
                    format!("{}{:?}\t",acc, x)
                }).trim_right());
            }
            e => panic!("protocol error: expected array in output payload but found {:?}", e)
        }
    };

    let fn_meta = |msg: SonicMessage| {
        if !args.flag_rows_only {
            match msg.payload {
                Some(Value::Array(d)) => {
                    debug!("recv type metadata: {:?}", d);
                    println!("{}", d.iter().fold(String::new(), |acc, col| {
                        format!("{}{:?}\t", acc, col.as_array().unwrap()[0])
                    }).trim_right())
                },
                e => panic!("protocol error: expected json array in metadata payload but found {:?}", e)
            }
        }
    };

    let fn_prog = |msg: SonicMessage| {
        let fields = msg.payload.unwrap();
        fields.find("progress").and_then(|p| {
            p.as_f64().map(|pi| {
                if pi >= 99.0 {
                    pb.finish();
                } else if pi >= 1.0 {
                    pb.add(pi as usize);
                }
            })
        });
        fields.find("output")
            .and_then(|o| o.as_string().map(|os| {
                io::stderr().write(&format!("{}", os).as_bytes()).unwrap();
            }));
    };

    try!(stream(query, &config.sonicd, &config.tcp_port, fn_out, fn_prog, fn_meta)
         .map_err(|e| {
             match e {
                 Error::StreamError(rec) => rec,
                 e => Receipt::error(format!("{}", e))
             }
         }));

    Ok(Receipt::success())
}

fn main() {

    let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());

    env_logger::init().unwrap();

    debug!("Parsed args {:?}", args);

    match _main(args) {
        Ok(r) => {
            if !r.success {
                io::stderr().write(&format!("{}", r).as_bytes()).unwrap();
                process::exit(1)
            } else if r.message.is_some() {
                io::stderr().write(&format!("{}", r).as_bytes()).unwrap();
            }
        },
        Err(r) =>  {
            io::stderr().write(&format!("{}", r).as_bytes()).unwrap();
            process::exit(1)
        }
    }
}
<commit_msg>cli: added silent flag<commit_after>#![feature(custom_derive, plugin, custom_attribute, box_syntax)]
#![plugin(docopt_macros)]
extern crate serde_json;
extern crate serde;
extern crate pbr;
extern crate regex;
extern crate curl;
extern crate docopt;
extern crate rustc_serialize;
extern crate env_logger;
#[macro_use] extern crate log;
#[macro_use] extern crate sonicd;

mod util;

use std::path::PathBuf;
use pbr::ProgressBar;
use sonicd::*;
use util::*;
use std::process;
use std::io::{Write, self};
use serde_json::Value;

docopt!(Args derive Debug, "
.
                           d8b
                           Y8P

.d8888b   .d88b.  88888b.  888  .d8888b
88K      d88\"\"88b 888 \"88b 888 d88P\"
\"Y8888b. 888  888 888  888 888 888
     X88 Y88..88P 888  888 888 Y88b.
 88888P'  \"Y88P\"  888  888 888  \"Y8888P

Usage:
  sonic <source> [-d <var>...] [options] -e <query>
  sonic <source> [-d <var>...] [options] -f <file>
  sonic -h | --help
  sonic --version

Options:
  --execute, -e         run command literal
  --file, -f            run command from file
  -c <config>           use config file (default: $HOME/.sonicrc)
  -d                    inject variable name to value (i.e. -d foo=bar)
  --silent, -S          output data only
  -r, --rows-only       print rows only
  -h, --help            show this message
  --version             show daemon and cli version
");

static VERSION: &'static str = env!("CARGO_PKG_VERSION");
static COMMIT: Option<&'static str> = option_env!("SONIC_COMMIT");

fn _main(args: Args) -> Result<Receipt> {

    let config: ClientConfig = if args.flag_c != "" {
        debug!("sourcing passed config in path '{:?}'", &args.flag_c);
        try!(read_cfg(PathBuf::from(args.flag_c.clone())))
    } else {
        debug!("sourcing default config in path '$HOME/.sonicrc'");
        try!(source_sonicrc())
    };

    let vars = try!(split_key_value(&args.arg_var));

    let query = if args.flag_file {
        try!(read_file_contents(PathBuf::from(&args.arg_file)))
    } else if args.flag_execute {
        args.arg_query.clone()
    } else {
        let daemon_v = try!(version(&config.sonicd, &config.http_port)
                            .map_err(|e| Receipt::error(format!("{}", e))));

        println!("sonic cli version {} ({}); daemon version {}",
        VERSION,
        COMMIT.unwrap_or_else(|| "dev"),
        daemon_v);
        return Ok(Receipt::success());
    };

    let injected = try!(inject_vars(&query, &vars));

    let query = try!(build(&args.arg_source, config.sources.clone(), &injected));

    let mut pb = ProgressBar::new(100);
    pb.format("╢░░_╟");

    let fn_out = |msg: SonicMessage| {
        match msg.payload {
            Some(Value::Array(d)) => {
                println!("{}", d.iter().fold(String::new(), |acc, x| {
                    format!("{}{:?}\t",acc, x)
                }).trim_right());
            }
            e => panic!("protocol error: expected array in output payload but found {:?}", e)
        }
    };

    let fn_meta = |msg: SonicMessage| {
        if !args.flag_rows_only {
            match msg.payload {
                Some(Value::Array(d)) => {
                    debug!("recv type metadata: {:?}", d);
                    println!("{}", d.iter().fold(String::new(), |acc, col| {
                        format!("{}{:?}\t", acc, col.as_array().unwrap()[0])
                    }).trim_right())
                },
                e => panic!("protocol error: expected json array in metadata payload but found {:?}", e)
            }
        }
    };

    let fn_prog = |msg: SonicMessage| {
        if !args.flag_silent {
            let fields = msg.payload.unwrap();
            fields.find("progress").and_then(|p| {
                p.as_f64().map(|pi| {
                    if pi >= 99.0 {
                        pb.finish();
                    } else if pi >= 1.0 {
                        pb.add(pi as usize);
                    }
                })
            });
            fields.find("output")
                .and_then(|o| o.as_string().map(|os| {
                    io::stderr().write(&format!("{}\r", os).as_bytes()).unwrap();
                }));
        }
    };

    try!(stream(query, &config.sonicd, &config.tcp_port, fn_out, fn_prog, fn_meta)
         .map_err(|e| {
             match e {
                 Error::StreamError(rec) => rec,
                 e => Receipt::error(format!("{}", e))
             }
         }));

    Ok(Receipt::success())
}

fn main() {

    let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());

    env_logger::init().unwrap();

    debug!("Parsed args {:?}", args);

    match _main(args) {
        Ok(r) => {
            if !r.success {
                io::stderr().write(&format!("{}", r).as_bytes()).unwrap();
                process::exit(1)
            } else if r.message.is_some() {
                io::stderr().write(&format!("{}", r).as_bytes()).unwrap();
            }
        },
        Err(r) =>  {
            io::stderr().write(&format!("{}", r).as_bytes()).unwrap();
            process::exit(1)
        }
    }
}
<|endoftext|>


<commit_before>use super::error::{Error, Result};
use super::generate::parse_grammar::GrammarJSON;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::path::Path;
use std::process::Command;

pub fn get_grammar_name(src_dir: &Path) -> Result<String> {
    let grammar_json_path = src_dir.join("grammar.json");
    let grammar_json = fs::read_to_string(&grammar_json_path).map_err(Error::wrap(|| {
        format!("Failed to read grammar file {:?}", grammar_json_path)
    }))?;
    let grammar: GrammarJSON = serde_json::from_str(&grammar_json).map_err(Error::wrap(|| {
        format!("Failed to parse grammar file {:?}", grammar_json_path)
    }))?;
    Ok(grammar.name)
}

pub fn compile_language_to_wasm(language_dir: &Path, force_docker: bool) -> Result<()> {
    let src_dir = language_dir.join("src");
    let grammar_name = get_grammar_name(&src_dir)?;
    let output_filename = format!("tree-sitter-{}.wasm", grammar_name);

    let mut command;
    if !force_docker && Command::new("emcc").output().is_ok() {
        command = Command::new("emcc");
        command.current_dir(&language_dir);
    } else if Command::new("docker").output().is_ok() {
        command = Command::new("docker");
        command.args(&["run", "--rm"]);

        // Mount the parser directory as a volume
        let mut volume_string;
        if let (Some(parent), Some(filename)) = (language_dir.parent(), language_dir.file_name()) {
            volume_string = OsString::from(parent);
            volume_string.push(":/src");
            command.arg("--workdir");
            command.arg(&Path::new("/src").join(filename));
        } else {
            volume_string = OsString::from(language_dir);
            volume_string.push(":/src");
            command.args(&["--workdir", "/src"]);
        }

        command.args(&[OsStr::new("--volume"), &volume_string]);

        // Get the current user id so that files created in the docker container will have
        // the same owner.
        if cfg!(unix) {
            let user_id_output = Command::new("id")
                .arg("-u")
                .output()
                .map_err(Error::wrap(|| "Failed to get get current user id"))?;
            let user_id = String::from_utf8_lossy(&user_id_output.stdout);
            let user_id = user_id.trim();
            command.args(&["--user", user_id]);
        }

        // Run `emcc` in a container using the `emscripten-slim` image
        command.args(&["trzeci/emscripten-slim", "emcc"]);
    } else {
        return Error::err("You must have either emcc or docker on your PATH to run this command".to_string());
    }

    command.args(&[
        "-o",
        &output_filename,
        "-Os",
        "-s",
        "WASM=1",
        "-s",
        "SIDE_MODULE=1",
        "-s",
        "TOTAL_MEMORY=33554432",
        "-s",
        &format!("EXPORTED_FUNCTIONS=[\"_tree_sitter_{}\"]", grammar_name),
        "-fno-exceptions",
        "-I",
        "src",
    ]);

    // Find source files to pass to emscripten
    let src_entries = fs::read_dir(&src_dir).map_err(Error::wrap(|| {
        format!("Failed to read source directory {:?}", src_dir)
    }))?;

    for entry in src_entries {
        let entry = entry?;
        let file_name = entry.file_name();

        // Do not compile the node.js binding file.
        if file_name
            .to_str()
            .map_or(false, |s| s.starts_with("binding"))
        {
            continue;
        }

        // Compile any .c, .cc, or .cpp files
        if let Some(extension) = Path::new(&file_name).extension().and_then(|s| s.to_str()) {
            if extension == "c" || extension == "cc" || extension == "cpp" {
                command.arg(Path::new("src").join(entry.file_name()));
            }
        }
    }

    let output = command
        .output()
        .map_err(Error::wrap(|| "Failed to run emcc command"))?;
    if !output.status.success() {
        return Err(Error::from(format!(
            "emcc command failed - {}",
            String::from_utf8_lossy(&output.stderr)
        )));
    }

    // Move the created `.wasm` file into the current working directory.
    fs::rename(&language_dir.join(&output_filename), &output_filename).map_err(Error::wrap(
        || format!("Couldn't find output file {:?}", output_filename),
    ))?;

    Ok(())
}
<commit_msg>Set NODEJS_CATCH_EXIT=0 when invoking emcc<commit_after>use super::error::{Error, Result};
use super::generate::parse_grammar::GrammarJSON;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::path::Path;
use std::process::Command;

pub fn get_grammar_name(src_dir: &Path) -> Result<String> {
    let grammar_json_path = src_dir.join("grammar.json");
    let grammar_json = fs::read_to_string(&grammar_json_path).map_err(Error::wrap(|| {
        format!("Failed to read grammar file {:?}", grammar_json_path)
    }))?;
    let grammar: GrammarJSON = serde_json::from_str(&grammar_json).map_err(Error::wrap(|| {
        format!("Failed to parse grammar file {:?}", grammar_json_path)
    }))?;
    Ok(grammar.name)
}

pub fn compile_language_to_wasm(language_dir: &Path, force_docker: bool) -> Result<()> {
    let src_dir = language_dir.join("src");
    let grammar_name = get_grammar_name(&src_dir)?;
    let output_filename = format!("tree-sitter-{}.wasm", grammar_name);

    let mut command;
    if !force_docker && Command::new("emcc").output().is_ok() {
        command = Command::new("emcc");
        command.current_dir(&language_dir);
    } else if Command::new("docker").output().is_ok() {
        command = Command::new("docker");
        command.args(&["run", "--rm"]);

        // Mount the parser directory as a volume
        let mut volume_string;
        if let (Some(parent), Some(filename)) = (language_dir.parent(), language_dir.file_name()) {
            volume_string = OsString::from(parent);
            volume_string.push(":/src");
            command.arg("--workdir");
            command.arg(&Path::new("/src").join(filename));
        } else {
            volume_string = OsString::from(language_dir);
            volume_string.push(":/src");
            command.args(&["--workdir", "/src"]);
        }

        command.args(&[OsStr::new("--volume"), &volume_string]);

        // Get the current user id so that files created in the docker container will have
        // the same owner.
        if cfg!(unix) {
            let user_id_output = Command::new("id")
                .arg("-u")
                .output()
                .map_err(Error::wrap(|| "Failed to get get current user id"))?;
            let user_id = String::from_utf8_lossy(&user_id_output.stdout);
            let user_id = user_id.trim();
            command.args(&["--user", user_id]);
        }

        // Run `emcc` in a container using the `emscripten-slim` image
        command.args(&["trzeci/emscripten-slim", "emcc"]);
    } else {
        return Error::err("You must have either emcc or docker on your PATH to run this command".to_string());
    }

    command.args(&[
        "-o",
        &output_filename,
        "-Os",
        "-s",
        "WASM=1",
        "-s",
        "SIDE_MODULE=1",
        "-s",
        "TOTAL_MEMORY=33554432",
        "-s",
        "NODEJS_CATCH_EXIT=0",
        "-s",
        &format!("EXPORTED_FUNCTIONS=[\"_tree_sitter_{}\"]", grammar_name),
        "-fno-exceptions",
        "-I",
        "src",
    ]);

    // Find source files to pass to emscripten
    let src_entries = fs::read_dir(&src_dir).map_err(Error::wrap(|| {
        format!("Failed to read source directory {:?}", src_dir)
    }))?;

    for entry in src_entries {
        let entry = entry?;
        let file_name = entry.file_name();

        // Do not compile the node.js binding file.
        if file_name
            .to_str()
            .map_or(false, |s| s.starts_with("binding"))
        {
            continue;
        }

        // Compile any .c, .cc, or .cpp files
        if let Some(extension) = Path::new(&file_name).extension().and_then(|s| s.to_str()) {
            if extension == "c" || extension == "cc" || extension == "cpp" {
                command.arg(Path::new("src").join(entry.file_name()));
            }
        }
    }

    let output = command
        .output()
        .map_err(Error::wrap(|| "Failed to run emcc command"))?;
    if !output.status.success() {
        return Err(Error::from(format!(
            "emcc command failed - {}",
            String::from_utf8_lossy(&output.stderr)
        )));
    }

    // Move the created `.wasm` file into the current working directory.
    fs::rename(&language_dir.join(&output_filename), &output_filename).map_err(Error::wrap(
        || format!("Couldn't find output file {:?}", output_filename),
    ))?;

    Ok(())
}
<|endoftext|>