<commit_before>extern crate nucleotide_codons as codons;

#[test]
fn test_methionine() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("ATG"), Ok("methionine"));
}

#[test]
#[ignore]
fn test_cysteine_tgt() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("TGT"), Ok("cysteine"));
}

#[test]
#[ignore]
fn test_cysteine_tgy() { // "compressed" name for TGT and TGC
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("TGT"), info.name_for("TGY"));
    assert_eq!(info.name_for("TGC"), info.name_for("TGY"));
}

#[test]
#[ignore]
fn test_stop() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("TAA"), Ok("stop codon"));
}

#[test]
#[ignore]
fn test_valine() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("GTN"), Ok("valine"));
}

#[test]
#[ignore]
fn test_isoleucine() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("ATH"), Ok("isoleucine"));
}

#[test]
#[ignore]
fn test_arginine_name() {
    // In arginine CGA can be "compresed" both as CGN and as MGR
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("CGA"), Ok("arginine"));
    assert_eq!(info.name_for("CGN"), Ok("arginine"));
    assert_eq!(info.name_for("MGR"), Ok("arginine"));
}

#[test]
#[ignore]
fn test_invalid() {
    let info = codons::parse(make_pairs());
    assert!(info.name_for("").is_err());
    assert!(info.name_for("VWX").is_err()); // X is not a shorthand
    assert!(info.name_for("AB").is_err()); // too short
    assert!(info.name_for("ABCD").is_err()); // too long
}

// The input data constructor. Returns a list of codon, name pairs.
fn make_pairs() -> Vec<(&'static str, &'static str)> {
    let grouped = vec![
        ("isoleucine", vec!["ATT", "ATC", "ATA"]),
        ("leucine", vec!["CTT", "CTC", "CTA", "CTG", "TTA", "TTG"]),
        ("valine", vec!["GTT", "GTC", "GTA", "GTG"]),
        ("phenylalanine", vec!["TTT", "TTC"]),
        ("methionine", vec!["ATG"]),
        ("cysteine", vec!["TGT", "TGC"]),
        ("alanine", vec!["GCT", "GCC", "GCA", "GCG"]),
        ("glycine", vec!["GGT", "GGC", "GGA", "GGG"]),
        ("proline", vec!["CCT", "CCC", "CCA", "CCG"]),
        ("threonine", vec!["ACT", "ACC", "ACA", "ACG"]),
        ("serine", vec!["TCT", "TCC", "TCA", "TCG", "AGT", "AGC"]),
        ("tyrosine", vec!["TAT", "TAC"]),
        ("tryptophan", vec!["TGG"]),
        ("glutamine", vec!["CAA", "CAG"]),
        ("asparagine", vec!["AAT", "AAC"]),
        ("histidine", vec!["CAT", "CAC"]),
        ("glutamic acid", vec!["GAA", "GAG"]),
        ("aspartic acid", vec!["GAT", "GAC"]),
        ("lysine", vec!["AAA", "AAG"]),
        ("arginine", vec!["CGT", "CGC", "CGA", "CGG", "AGA", "AGG"]),
        ("stop codon", vec!["TAA", "TAG", "TGA"])];
    let mut pairs = Vec::<(&'static str, &'static str)>::new();
    for (name, codons) in grouped.into_iter() {
        for codon in codons {
            pairs.push((codon, name));
        }
    };
    pairs.sort_by(|&(_, a), &(_, b)| a.cmp(b));
    return pairs
}
<commit_msg>nucleotide-codons: Separate invalid tests<commit_after>extern crate nucleotide_codons as codons;

#[test]
fn test_methionine() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("ATG"), Ok("methionine"));
}

#[test]
#[ignore]
fn test_cysteine_tgt() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("TGT"), Ok("cysteine"));
}

#[test]
#[ignore]
fn test_cysteine_tgy() { // "compressed" name for TGT and TGC
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("TGT"), info.name_for("TGY"));
    assert_eq!(info.name_for("TGC"), info.name_for("TGY"));
}

#[test]
#[ignore]
fn test_stop() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("TAA"), Ok("stop codon"));
}

#[test]
#[ignore]
fn test_valine() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("GTN"), Ok("valine"));
}

#[test]
#[ignore]
fn test_isoleucine() {
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("ATH"), Ok("isoleucine"));
}

#[test]
#[ignore]
fn test_arginine_name() {
    // In arginine CGA can be "compresed" both as CGN and as MGR
    let info = codons::parse(make_pairs());
    assert_eq!(info.name_for("CGA"), Ok("arginine"));
    assert_eq!(info.name_for("CGN"), Ok("arginine"));
    assert_eq!(info.name_for("MGR"), Ok("arginine"));
}

#[test]
#[ignore]
fn empty_is_invalid() {
    let info = codons::parse(make_pairs());
    assert!(info.name_for("").is_err());
}

#[test]
#[ignore]
fn x_is_not_shorthand_so_is_invalid() {
    let info = codons::parse(make_pairs());
    assert!(info.name_for("VWX").is_err());
}

#[test]
#[ignore]
fn too_short_is_invalid() {
    let info = codons::parse(make_pairs());
    assert!(info.name_for("AT").is_err());
}

#[test]
#[ignore]
fn too_long_is_invalid() {
    let info = codons::parse(make_pairs());
    assert!(info.name_for("ATTA").is_err());
}

// The input data constructor. Returns a list of codon, name pairs.
fn make_pairs() -> Vec<(&'static str, &'static str)> {
    let grouped = vec![
        ("isoleucine", vec!["ATT", "ATC", "ATA"]),
        ("leucine", vec!["CTT", "CTC", "CTA", "CTG", "TTA", "TTG"]),
        ("valine", vec!["GTT", "GTC", "GTA", "GTG"]),
        ("phenylalanine", vec!["TTT", "TTC"]),
        ("methionine", vec!["ATG"]),
        ("cysteine", vec!["TGT", "TGC"]),
        ("alanine", vec!["GCT", "GCC", "GCA", "GCG"]),
        ("glycine", vec!["GGT", "GGC", "GGA", "GGG"]),
        ("proline", vec!["CCT", "CCC", "CCA", "CCG"]),
        ("threonine", vec!["ACT", "ACC", "ACA", "ACG"]),
        ("serine", vec!["TCT", "TCC", "TCA", "TCG", "AGT", "AGC"]),
        ("tyrosine", vec!["TAT", "TAC"]),
        ("tryptophan", vec!["TGG"]),
        ("glutamine", vec!["CAA", "CAG"]),
        ("asparagine", vec!["AAT", "AAC"]),
        ("histidine", vec!["CAT", "CAC"]),
        ("glutamic acid", vec!["GAA", "GAG"]),
        ("aspartic acid", vec!["GAT", "GAC"]),
        ("lysine", vec!["AAA", "AAG"]),
        ("arginine", vec!["CGT", "CGC", "CGA", "CGG", "AGA", "AGG"]),
        ("stop codon", vec!["TAA", "TAG", "TGA"])];
    let mut pairs = Vec::<(&'static str, &'static str)>::new();
    for (name, codons) in grouped.into_iter() {
        for codon in codons {
            pairs.push((codon, name));
        }
    };
    pairs.sort_by(|&(_, a), &(_, b)| a.cmp(b));
    return pairs
}
<|endoftext|>


<commit_before>#[test]
fn test_methionine() {
    let info = nucleotide_codons::parse(make_pairs());
    assert_eq!(info.name_for("ATG"), Ok("methionine"));
}

#[test]
#[ignore]
fn test_cysteine_tgt() {
    let info = nucleotide_codons::parse(make_pairs());
    assert_eq!(info.name_for("TGT"), Ok("cysteine"));
}

#[test]
#[ignore]
fn test_cysteine_tgy() {
    // "compressed" name for TGT and TGC
    let info = nucleotide_codons::parse(make_pairs());
    assert_eq!(info.name_for("TGT"), info.name_for("TGY"));
    assert_eq!(info.name_for("TGC"), info.name_for("TGY"));
}

#[test]
#[ignore]
fn test_stop() {
    let info = nucleotide_codons::parse(make_pairs());
    assert_eq!(info.name_for("TAA"), Ok("stop codon"));
}

#[test]
#[ignore]
fn test_valine() {
    let info = nucleotide_codons::parse(make_pairs());
    assert_eq!(info.name_for("GTN"), Ok("valine"));
}

#[test]
#[ignore]
fn test_isoleucine() {
    let info = nucleotide_codons::parse(make_pairs());
    assert_eq!(info.name_for("ATH"), Ok("isoleucine"));
}

#[test]
#[ignore]
fn test_arginine_name() {
    // In arginine CGA can be "compressed" both as CGN and as MGR
    let info = nucleotide_codons::parse(make_pairs());
    assert_eq!(info.name_for("CGA"), Ok("arginine"));
    assert_eq!(info.name_for("CGN"), Ok("arginine"));
    assert_eq!(info.name_for("MGR"), Ok("arginine"));
}

#[test]
#[ignore]
fn empty_is_invalid() {
    let info = nucleotide_codons::parse(make_pairs());
    assert!(info.name_for("").is_err());
}

#[test]
#[ignore]
fn x_is_not_shorthand_so_is_invalid() {
    let info = nucleotide_codons::parse(make_pairs());
    assert!(info.name_for("VWX").is_err());
}

#[test]
#[ignore]
fn too_short_is_invalid() {
    let info = nucleotide_codons::parse(make_pairs());
    assert!(info.name_for("AT").is_err());
}

#[test]
#[ignore]
fn too_long_is_invalid() {
    let info = nucleotide_codons::parse(make_pairs());
    assert!(info.name_for("ATTA").is_err());
}

// The input data constructor. Returns a list of codon, name pairs.
fn make_pairs() -> Vec<(&'static str, &'static str)> {
    let grouped = vec![
        ("isoleucine", vec!["ATT", "ATC", "ATA"]),
        ("leucine", vec!["CTT", "CTC", "CTA", "CTG", "TTA", "TTG"]),
        ("valine", vec!["GTT", "GTC", "GTA", "GTG"]),
        ("phenylalanine", vec!["TTT", "TTC"]),
        ("methionine", vec!["ATG"]),
        ("cysteine", vec!["TGT", "TGC"]),
        ("alanine", vec!["GCT", "GCC", "GCA", "GCG"]),
        ("glycine", vec!["GGT", "GGC", "GGA", "GGG"]),
        ("proline", vec!["CCT", "CCC", "CCA", "CCG"]),
        ("threonine", vec!["ACT", "ACC", "ACA", "ACG"]),
        ("serine", vec!["TCT", "TCC", "TCA", "TCG", "AGT", "AGC"]),
        ("tyrosine", vec!["TAT", "TAC"]),
        ("tryptophan", vec!["TGG"]),
        ("glutamine", vec!["CAA", "CAG"]),
        ("asparagine", vec!["AAT", "AAC"]),
        ("histidine", vec!["CAT", "CAC"]),
        ("glutamic acid", vec!["GAA", "GAG"]),
        ("aspartic acid", vec!["GAT", "GAC"]),
        ("lysine", vec!["AAA", "AAG"]),
        ("arginine", vec!["CGT", "CGC", "CGA", "CGG", "AGA", "AGG"]),
        ("stop codon", vec!["TAA", "TAG", "TGA"]),
    ];
    let mut pairs = Vec::<(&'static str, &'static str)>::new();
    for (name, codons) in grouped.into_iter() {
        for codon in codons {
            pairs.push((codon, name));
        }
    }
    pairs.sort_by(|&(_, a), &(_, b)| a.cmp(b));
    return pairs;
}
<commit_msg>nucleotide-codons: rm unneeded return (#1003)<commit_after>#[test]
fn test_methionine() {
    let info = nucleotide_codons::parse(make_pairs());
    assert_eq!(info.name_for("ATG"), Ok("methionine"));
}

#[test]
#[ignore]
fn test_cysteine_tgt() {
    let info = nucleotide_codons::parse(make_pairs());
    assert_eq!(info.name_for("TGT"), Ok("cysteine"));
}

#[test]
#[ignore]
fn test_cysteine_tgy() {
    // "compressed" name for TGT and TGC
    let info = nucleotide_codons::parse(make_pairs());
    assert_eq!(info.name_for("TGT"), info.name_for("TGY"));
    assert_eq!(info.name_for("TGC"), info.name_for("TGY"));
}

#[test]
#[ignore]
fn test_stop() {
    let info = nucleotide_codons::parse(make_pairs());
    assert_eq!(info.name_for("TAA"), Ok("stop codon"));
}

#[test]
#[ignore]
fn test_valine() {
    let info = nucleotide_codons::parse(make_pairs());
    assert_eq!(info.name_for("GTN"), Ok("valine"));
}

#[test]
#[ignore]
fn test_isoleucine() {
    let info = nucleotide_codons::parse(make_pairs());
    assert_eq!(info.name_for("ATH"), Ok("isoleucine"));
}

#[test]
#[ignore]
fn test_arginine_name() {
    // In arginine CGA can be "compressed" both as CGN and as MGR
    let info = nucleotide_codons::parse(make_pairs());
    assert_eq!(info.name_for("CGA"), Ok("arginine"));
    assert_eq!(info.name_for("CGN"), Ok("arginine"));
    assert_eq!(info.name_for("MGR"), Ok("arginine"));
}

#[test]
#[ignore]
fn empty_is_invalid() {
    let info = nucleotide_codons::parse(make_pairs());
    assert!(info.name_for("").is_err());
}

#[test]
#[ignore]
fn x_is_not_shorthand_so_is_invalid() {
    let info = nucleotide_codons::parse(make_pairs());
    assert!(info.name_for("VWX").is_err());
}

#[test]
#[ignore]
fn too_short_is_invalid() {
    let info = nucleotide_codons::parse(make_pairs());
    assert!(info.name_for("AT").is_err());
}

#[test]
#[ignore]
fn too_long_is_invalid() {
    let info = nucleotide_codons::parse(make_pairs());
    assert!(info.name_for("ATTA").is_err());
}

// The input data constructor. Returns a list of codon, name pairs.
fn make_pairs() -> Vec<(&'static str, &'static str)> {
    let grouped = vec![
        ("isoleucine", vec!["ATT", "ATC", "ATA"]),
        ("leucine", vec!["CTT", "CTC", "CTA", "CTG", "TTA", "TTG"]),
        ("valine", vec!["GTT", "GTC", "GTA", "GTG"]),
        ("phenylalanine", vec!["TTT", "TTC"]),
        ("methionine", vec!["ATG"]),
        ("cysteine", vec!["TGT", "TGC"]),
        ("alanine", vec!["GCT", "GCC", "GCA", "GCG"]),
        ("glycine", vec!["GGT", "GGC", "GGA", "GGG"]),
        ("proline", vec!["CCT", "CCC", "CCA", "CCG"]),
        ("threonine", vec!["ACT", "ACC", "ACA", "ACG"]),
        ("serine", vec!["TCT", "TCC", "TCA", "TCG", "AGT", "AGC"]),
        ("tyrosine", vec!["TAT", "TAC"]),
        ("tryptophan", vec!["TGG"]),
        ("glutamine", vec!["CAA", "CAG"]),
        ("asparagine", vec!["AAT", "AAC"]),
        ("histidine", vec!["CAT", "CAC"]),
        ("glutamic acid", vec!["GAA", "GAG"]),
        ("aspartic acid", vec!["GAT", "GAC"]),
        ("lysine", vec!["AAA", "AAG"]),
        ("arginine", vec!["CGT", "CGC", "CGA", "CGG", "AGA", "AGG"]),
        ("stop codon", vec!["TAA", "TAG", "TGA"]),
    ];
    let mut pairs = Vec::<(&'static str, &'static str)>::new();
    for (name, codons) in grouped.into_iter() {
        for codon in codons {
            pairs.push((codon, name));
        }
    }
    pairs.sort_by(|&(_, a), &(_, b)| a.cmp(b));
    pairs
}
<|endoftext|>


<commit_before>// Reference: Section 5.4.4 "LDREX / STREX" of ACLE

/// Removes the exclusive lock created by LDREX
// Supported: v6, v6K, v7-M, v7-A, v7-R
// Not supported: v5, v6-M
#[cfg(any(
    all(target_feature = "v6", not(target_feature = "mclass")), // excludes v6-M
    all(target_feature = "v7", target_feature = "mclass"), // v7-M
))]
pub unsafe fn __clrex() {
    extern "C" {
        #[link_name = "llvm.arm.clrex"]
        fn clrex();
    }

    clrex()
}

/// Executes a exclusive LDR instruction for 8 bit value.
// Supported: v6K, v7-M, v7-A, v7-R
// Not supported: v5, v6, v6-M
#[cfg(
    target_feature = "v6k", // includes v7-M but excludes v6-M
)]
pub unsafe fn __ldrexb(p: *const u8) -> u8 {
    extern "C" {
        #[link_name = "llvm.arm.ldrex.p0i8"]
        fn ldrex8(p: *const u8) -> u32;
    }

    ldrex8(p) as u8
}

/// Executes a exclusive LDR instruction for 16 bit value.
// Supported: v6K, v7-M, v7-A, v7-R, v8
// Not supported: v5, v6, v6-M
#[cfg(
    target_feature = "v6k", // includes v7-M but excludes v6-M
)]
pub unsafe fn __ldrexh(p: *const u16) -> u16 {
    extern "C" {
        #[link_name = "llvm.arm.ldrex.p0i16"]
        fn ldrex16(p: *const u16) -> u32;
    }

    ldrex16(p) as u16
}

/// Executes a exclusive LDR instruction for 32 bit value.
// Supported: v6, v7-M, v6K, v7-A, v7-R, v8
// Not supported: v5, v6-M
#[cfg(any(
    all(target_feature = "v6", not(target_feature = "mclass")), // excludes v6-M
    all(target_feature = "v7", target_feature = "mclass"), // v7-M
))]
pub unsafe fn __ldrex(p: *const u32) -> u32 {
    extern "C" {
        #[link_name = "llvm.arm.ldrex.p0i32"]
        fn ldrex32(p: *const u32) -> u32;
    }

    ldrex32(p)
}

/// Executes a exclusive STR instruction for 8 bit values
///
/// Returns `0` if the operation succeeded, or `1` if it failed
// supported: v6K, v7-M, v7-A, v7-R
// Not supported: v5, v6, v6-M
#[cfg(
    target_feature = "v6k", // includes v7-M but excludes v6-M
)]
pub unsafe fn __strexb(value: u32, addr: *mut u8) -> u32 {
    extern "C" {
        #[link_name = "llvm.arm.strex.p0i8"]
        fn strex8(value: u32, addr: *mut u8) -> u32;
    }

    strex8(value, addr)
}

/// Executes a exclusive STR instruction for 16 bit values
///
/// Returns `0` if the operation succeeded, or `1` if it failed
// Supported: v6K, v7-M, v7-A, v7-R, v8
// Not supported: v5, v6, v6-M
#[cfg(
    target_feature = "v6k", // includes v7-M but excludes v6-M
)]
pub unsafe fn __strexh(value: u16, addr: *mut u16) -> u32 {
    extern "C" {
        #[link_name = "llvm.arm.strex.p0i16"]
        fn strex16(value: u32, addr: *mut u16) -> u32;
    }

    strex16(value as u32, addr)
}

/// Executes a exclusive STR instruction for 32 bit values
///
/// Returns `0` if the operation succeeded, or `1` if it failed
// Supported: v6, v7-M, v6K, v7-A, v7-R, v8
// Not supported: v5, v6-M
#[cfg(any(
    all(target_feature = "v6", not(target_feature = "mclass")), // excludes v6-M
    all(target_feature = "v7", target_feature = "mclass"), // v7-M
))]
pub unsafe fn __strex(value: u32, addr: *mut u32) -> u32 {
    extern "C" {
        #[link_name = "llvm.arm.strex.p0i32"]
        fn strex32(value: u32, addr: *mut u32) -> u32;
    }

    strex32(value, addr)
}
<commit_msg>acle/ex: CLREX requires v6k<commit_after>// Reference: Section 5.4.4 "LDREX / STREX" of ACLE

/// Removes the exclusive lock created by LDREX
// Supported: v6, v6K, v7-M, v7-A, v7-R
// Not supported: v5, v6-M
// NOTE: there's no dedicated CLREX instruction in v6 (<v6k); to clear the exclusive monitor users
// have to do a dummy STREX operation
#[cfg(any(
    all(target_feature = "v6k", not(target_feature = "mclass")), // excludes v6-M
    all(target_feature = "v7", target_feature = "mclass"), // v7-M
))]
pub unsafe fn __clrex() {
    extern "C" {
        #[link_name = "llvm.arm.clrex"]
        fn clrex();
    }

    clrex()
}

/// Executes a exclusive LDR instruction for 8 bit value.
// Supported: v6K, v7-M, v7-A, v7-R
// Not supported: v5, v6, v6-M
#[cfg(
    target_feature = "v6k", // includes v7-M but excludes v6-M
)]
pub unsafe fn __ldrexb(p: *const u8) -> u8 {
    extern "C" {
        #[link_name = "llvm.arm.ldrex.p0i8"]
        fn ldrex8(p: *const u8) -> u32;
    }

    ldrex8(p) as u8
}

/// Executes a exclusive LDR instruction for 16 bit value.
// Supported: v6K, v7-M, v7-A, v7-R, v8
// Not supported: v5, v6, v6-M
#[cfg(
    target_feature = "v6k", // includes v7-M but excludes v6-M
)]
pub unsafe fn __ldrexh(p: *const u16) -> u16 {
    extern "C" {
        #[link_name = "llvm.arm.ldrex.p0i16"]
        fn ldrex16(p: *const u16) -> u32;
    }

    ldrex16(p) as u16
}

/// Executes a exclusive LDR instruction for 32 bit value.
// Supported: v6, v7-M, v6K, v7-A, v7-R, v8
// Not supported: v5, v6-M
#[cfg(any(
    all(target_feature = "v6", not(target_feature = "mclass")), // excludes v6-M
    all(target_feature = "v7", target_feature = "mclass"), // v7-M
))]
pub unsafe fn __ldrex(p: *const u32) -> u32 {
    extern "C" {
        #[link_name = "llvm.arm.ldrex.p0i32"]
        fn ldrex32(p: *const u32) -> u32;
    }

    ldrex32(p)
}

/// Executes a exclusive STR instruction for 8 bit values
///
/// Returns `0` if the operation succeeded, or `1` if it failed
// supported: v6K, v7-M, v7-A, v7-R
// Not supported: v5, v6, v6-M
#[cfg(
    target_feature = "v6k", // includes v7-M but excludes v6-M
)]
pub unsafe fn __strexb(value: u32, addr: *mut u8) -> u32 {
    extern "C" {
        #[link_name = "llvm.arm.strex.p0i8"]
        fn strex8(value: u32, addr: *mut u8) -> u32;
    }

    strex8(value, addr)
}

/// Executes a exclusive STR instruction for 16 bit values
///
/// Returns `0` if the operation succeeded, or `1` if it failed
// Supported: v6K, v7-M, v7-A, v7-R, v8
// Not supported: v5, v6, v6-M
#[cfg(
    target_feature = "v6k", // includes v7-M but excludes v6-M
)]
pub unsafe fn __strexh(value: u16, addr: *mut u16) -> u32 {
    extern "C" {
        #[link_name = "llvm.arm.strex.p0i16"]
        fn strex16(value: u32, addr: *mut u16) -> u32;
    }

    strex16(value as u32, addr)
}

/// Executes a exclusive STR instruction for 32 bit values
///
/// Returns `0` if the operation succeeded, or `1` if it failed
// Supported: v6, v7-M, v6K, v7-A, v7-R, v8
// Not supported: v5, v6-M
#[cfg(any(
    all(target_feature = "v6", not(target_feature = "mclass")), // excludes v6-M
    all(target_feature = "v7", target_feature = "mclass"), // v7-M
))]
pub unsafe fn __strex(value: u32, addr: *mut u32) -> u32 {
    extern "C" {
        #[link_name = "llvm.arm.strex.p0i32"]
        fn strex32(value: u32, addr: *mut u32) -> u32;
    }

    strex32(value, addr)
}
<|endoftext|>


<commit_before>use std::io::{Read, Write};

use super::*;

pub(crate) fn read_blob(
    blob_ptr: Lsn,
    config: &Config,
) -> Result<Vec<u8>, ()> {
    let path = config.blob_path(blob_ptr);
    let mut f = std::fs::OpenOptions::new().read(true).open(&path)?;

    let mut crc_expected_bytes = [0u8; BLOB_INLINE_LEN];
    f.read_exact(&mut crc_expected_bytes)?;
    let crc_expected = arr_to_u64(crc_expected_bytes);

    let mut buf = vec![];
    f.read_to_end(&mut buf)?;

    let crc_actual = crc64(&*buf);

    if crc_expected != crc_actual {
        warn!("blob {} failed crc check!", blob_ptr);

        Err(Error::Corruption {
            // FIXME Corruption pointer below should not have 0 as its LogId
            at: DiskPtr::Blob(0, blob_ptr),
        })
    } else {
        Ok(buf)
    }
}

pub(crate) fn write_blob(
    config: &Config,
    id: Lsn,
    data: Vec<u8>,
) -> Result<(), ()> {
    let path = config.blob_path(id);
    let mut f = std::fs::OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(&path)?;

    let crc = u64_to_arr(crc64(&*data));

    f.write_all(&crc)
        .and_then(|_| f.write_all(&data))
        .map(|r| {
            trace!("successfully wrote blob at {:?}", path);
            r
        })
        .map_err(|e| e.into())
}

pub(crate) fn gc_blobs(
    config: &Config,
    stable_lsn: Lsn,
) -> Result<(), ()> {
    let stable = config.blob_path(stable_lsn);
    let blob_dir = stable.parent().unwrap();
    let blobs = std::fs::read_dir(blob_dir)?;

    debug!(
        "gc_blobs removing any blob with an lsn above {}",
        stable_lsn
    );

    for blob in blobs {
        let path = blob?.path();
        let lsn_str = path.file_name().unwrap().to_str().unwrap();
        let lsn_res: std::result::Result<Lsn, _> = lsn_str.parse();

        if let Err(e) = lsn_res {
            return Err(Error::Unsupported(format!(
                "blobs directory contains \
                 unparsable path ({:?}): {}",
                path, e
            )));
        }

        let lsn = lsn_res.unwrap();

        if lsn > stable_lsn {
            warn!(
                "removing blob {:?} that has \
                 a higher lsn than our stable log: {:?}",
                path, stable
            );
            std::fs::remove_file(&path)?;
        }
    }

    Ok(())
}

pub(crate) fn remove_blob(
    id: Lsn,
    config: &Config,
) -> Result<(), ()> {
    let path = config.blob_path(id);

    if let Err(e) = std::fs::remove_file(&path) {
        debug!("removing blob at {:?} failed: {}", path, e);
    } else {
        trace!("successfully removed blob at {:?}", path);
    }

    // TODO return a future
    Ok(())
}
<commit_msg>Add better logging around blob read failures<commit_after>use std::io::{Read, Write};

use super::*;

pub(crate) fn read_blob(
    blob_ptr: Lsn,
    config: &Config,
) -> Result<Vec<u8>, ()> {
    let path = config.blob_path(blob_ptr);
    let f_res = std::fs::OpenOptions::new().read(true).open(&path);

    if let Err(e) = &f_res {
        debug!(
            "failed to open file for blob read at {}: {:?}",
            blob_ptr, e
        );
    }

    let mut f = f_res?;

    let mut crc_expected_bytes = [0u8; BLOB_INLINE_LEN];

    if let Err(e) = f.read_exact(&mut crc_expected_bytes) {
        debug!(
            "failed to read the initial CRC bytes in the blob at {}: {:?}",
            blob_ptr,
            e,
        );
        return Err(e.into());
    }

    let crc_expected = arr_to_u64(crc_expected_bytes);

    let mut buf = vec![];
    if let Err(e) = f.read_to_end(&mut buf) {
        debug!(
            "failed to read data after the CRC bytes in blob at {}: {:?}",
            blob_ptr,
            e,
        );
        return Err(e.into());
    }

    let crc_actual = crc64(&*buf);

    if crc_expected != crc_actual {
        warn!("blob {} failed crc check!", blob_ptr);

        Err(Error::Corruption {
            // FIXME Corruption pointer below should not have 0 as its LogId
            at: DiskPtr::Blob(0, blob_ptr),
        })
    } else {
        Ok(buf)
    }
}

pub(crate) fn write_blob(
    config: &Config,
    id: Lsn,
    data: Vec<u8>,
) -> Result<(), ()> {
    let path = config.blob_path(id);
    let mut f = std::fs::OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(&path)?;

    let crc = u64_to_arr(crc64(&*data));

    f.write_all(&crc)
        .and_then(|_| f.write_all(&data))
        .map(|r| {
            trace!("successfully wrote blob at {:?}", path);
            r
        })
        .map_err(|e| e.into())
}

pub(crate) fn gc_blobs(
    config: &Config,
    stable_lsn: Lsn,
) -> Result<(), ()> {
    let stable = config.blob_path(stable_lsn);
    let blob_dir = stable.parent().unwrap();
    let blobs = std::fs::read_dir(blob_dir)?;

    debug!(
        "gc_blobs removing any blob with an lsn above {}",
        stable_lsn
    );

    for blob in blobs {
        let path = blob?.path();
        let lsn_str = path.file_name().unwrap().to_str().unwrap();
        let lsn_res: std::result::Result<Lsn, _> = lsn_str.parse();

        if let Err(e) = lsn_res {
            return Err(Error::Unsupported(format!(
                "blobs directory contains \
                 unparsable path ({:?}): {}",
                path, e
            )));
        }

        let lsn = lsn_res.unwrap();

        if lsn > stable_lsn {
            warn!(
                "removing blob {:?} that has \
                 a higher lsn than our stable log: {:?}",
                path, stable
            );
            std::fs::remove_file(&path)?;
        }
    }

    Ok(())
}

pub(crate) fn remove_blob(
    id: Lsn,
    config: &Config,
) -> Result<(), ()> {
    let path = config.blob_path(id);

    if let Err(e) = std::fs::remove_file(&path) {
        debug!("removing blob at {:?} failed: {}", path, e);
    } else {
        trace!("successfully removed blob at {:?}", path);
    }

    // TODO return a future
    Ok(())
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::path::PathBuf;

fn main() {
    if let Err(e) = doit() {
        eprintln!("error: {}", e);
        std::process::exit(1);
    }
}

fn doit() -> Result<(), Box<dyn Error>> {
    let mut args = std::env::args().skip(1);
    let mut src_path = None;
    let mut out_path = None;
    let mut rustc_path = None;
    let mut rustc_target = None;
    let mut verbose = false;
    let mut validate = false;
    while let Some(arg) = args.next() {
        match arg.as_str() {
            "--src" => {
                src_path = match args.next() {
                    Some(s) => Some(PathBuf::from(s)),
                    None => return Err("--src requires a value".into()),
                };
            }
            "--out" => {
                out_path = match args.next() {
                    Some(s) => Some(PathBuf::from(s)),
                    None => return Err("--out requires a value".into()),
                };
            }
            "--rustc" => {
                rustc_path = match args.next() {
                    Some(s) => Some(PathBuf::from(s)),
                    None => return Err("--rustc requires a value".into()),
                };
            }
            "--rustc-target" => {
                rustc_target = match args.next() {
                    Some(s) => Some(s),
                    None => return Err("--rustc-target requires a value".into()),
                };
            }
            "-v" | "--verbose" => verbose = true,
            "--validate" => validate = true,
            s => return Err(format!("unexpected argument `{}`", s).into()),
        }
    }
    if src_path.is_none() {
        return Err("--src must be specified to the directory with the compiler source".into());
    }
    if out_path.is_none() {
        return Err("--out must be specified to the directory with the lint listing docs".into());
    }
    if rustc_path.is_none() {
        return Err("--rustc must be specified to the path of rustc".into());
    }
    if rustc_target.is_none() {
        return Err("--rustc-target must be specified to the rustc target".into());
    }
    let le = lint_docs::LintExtractor {
        src_path: &src_path.unwrap(),
        out_path: &out_path.unwrap(),
        rustc_path: &rustc_path.unwrap(),
        rustc_target: &rustc_target.unwrap(),
        verbose,
        validate,
    };
    le.extract_lint_docs()
}
<commit_msg>lint-docs: Add some extra detail to the error message.<commit_after>use std::error::Error;
use std::path::PathBuf;

fn main() {
    if let Err(e) = doit() {
        eprintln!("error: {}", e);
        eprintln!(
            "
This error was generated by the lint-docs tool.
This tool extracts documentation for lints from the source code and places
them in the rustc book. See the declare_lint! documentation
https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/macro.declare_lint.html
for an example of the format of documentation this tool expects.

To re-run these tests, run: ./x.py test --keep-stage=0 src/tools/lint-docs
The --keep-stage flag should be used if you have already built the compiler
and are only modifying the doc comments to avoid rebuilding the compiler.
"
        );
        std::process::exit(1);
    }
}

fn doit() -> Result<(), Box<dyn Error>> {
    let mut args = std::env::args().skip(1);
    let mut src_path = None;
    let mut out_path = None;
    let mut rustc_path = None;
    let mut rustc_target = None;
    let mut verbose = false;
    let mut validate = false;
    while let Some(arg) = args.next() {
        match arg.as_str() {
            "--src" => {
                src_path = match args.next() {
                    Some(s) => Some(PathBuf::from(s)),
                    None => return Err("--src requires a value".into()),
                };
            }
            "--out" => {
                out_path = match args.next() {
                    Some(s) => Some(PathBuf::from(s)),
                    None => return Err("--out requires a value".into()),
                };
            }
            "--rustc" => {
                rustc_path = match args.next() {
                    Some(s) => Some(PathBuf::from(s)),
                    None => return Err("--rustc requires a value".into()),
                };
            }
            "--rustc-target" => {
                rustc_target = match args.next() {
                    Some(s) => Some(s),
                    None => return Err("--rustc-target requires a value".into()),
                };
            }
            "-v" | "--verbose" => verbose = true,
            "--validate" => validate = true,
            s => return Err(format!("unexpected argument `{}`", s).into()),
        }
    }
    if src_path.is_none() {
        return Err("--src must be specified to the directory with the compiler source".into());
    }
    if out_path.is_none() {
        return Err("--out must be specified to the directory with the lint listing docs".into());
    }
    if rustc_path.is_none() {
        return Err("--rustc must be specified to the path of rustc".into());
    }
    if rustc_target.is_none() {
        return Err("--rustc-target must be specified to the rustc target".into());
    }
    let le = lint_docs::LintExtractor {
        src_path: &src_path.unwrap(),
        out_path: &out_path.unwrap(),
        rustc_path: &rustc_path.unwrap(),
        rustc_target: &rustc_target.unwrap(),
        verbose,
        validate,
    };
    le.extract_lint_docs()
}
<|endoftext|>


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

use app_units::Au;
use core_graphics::base::kCGImageAlphaPremultipliedLast;
use core_graphics::color_space::CGColorSpace;
use core_graphics::context::CGContext;
use core_graphics::data_provider::CGDataProvider;
use core_graphics::font::{CGFont, CGGlyph};
use core_graphics::geometry::CGPoint;
use core_text::font::CTFont;
use core_text::font_descriptor::kCTFontDefaultOrientation;
use core_text;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use webrender_traits::FontKey;

pub type NativeFontHandle = CGFont;

pub struct FontContext {
    cg_fonts: HashMap<FontKey, CGFont>,
    ct_fonts: HashMap<(FontKey, Au), CTFont>,
}

pub struct RasterizedGlyph {
    pub left: i32,
    pub top: i32,
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

impl RasterizedGlyph {
    pub fn blank() -> RasterizedGlyph {
        RasterizedGlyph {
            left: 0,
            top: 0,
            width: 0,
            height: 0,
            bytes: vec![],
        }
    }
}

impl FontContext {
    pub fn new() -> FontContext {
        FontContext {
            cg_fonts: HashMap::new(),
            ct_fonts: HashMap::new(),
        }
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8]) {
        if self.cg_fonts.contains_key(font_key) {
            return
        }

        let data_provider = CGDataProvider::from_buffer(bytes);
        let cg_font = match CGFont::from_data_provider(data_provider) {
            Err(_) => return,
            Ok(cg_font) => cg_font,
        };
        self.cg_fonts.insert((*font_key).clone(), cg_font);
    }

    pub fn add_native_font(&mut self, font_key: &FontKey, native_font_handle: CGFont) {
        if self.cg_fonts.contains_key(font_key) {
            return
        }

        self.cg_fonts.insert((*font_key).clone(), native_font_handle);
    }

    pub fn get_glyph(&mut self,
                     font_key: FontKey,
                     size: Au,
                     character: u32,
                     device_pixel_ratio: f32,
                     enable_aa: bool)
                     -> Option<RasterizedGlyph> {
        let ct_font = match self.ct_fonts.entry(((font_key).clone(), size)) {
            Entry::Occupied(entry) => (*entry.get()).clone(),
            Entry::Vacant(entry) => {
                let cg_font = match self.cg_fonts.get(&font_key) {
                    None => return Some(RasterizedGlyph::blank()),
                    Some(cg_font) => cg_font,
                };
                let ct_font = core_text::font::new_from_CGFont(
                        cg_font,
                        size.to_f64_px() * (device_pixel_ratio as f64));
                entry.insert(ct_font.clone());
                ct_font
            }
        };

        let glyph = character as CGGlyph;
        let bounds = ct_font.get_bounding_rects_for_glyphs(kCTFontDefaultOrientation, &[glyph]);

        let rasterized_left = bounds.origin.x.floor() as i32;
        let rasterized_width =
            (bounds.origin.x - (rasterized_left as f64) + bounds.size.width).ceil() as u32;
        let rasterized_descent = (-bounds.origin.y).ceil() as i32;
        let rasterized_ascent = (bounds.size.height + bounds.origin.y).ceil() as i32;
        let rasterized_height = (rasterized_descent + rasterized_ascent) as u32;
        if rasterized_width == 0 || rasterized_height == 0 {
            return Some(RasterizedGlyph::blank())
        }

        let mut cg_context = CGContext::create_bitmap_context(rasterized_width as usize,
                                                              rasterized_height as usize,
                                                              8,
                                                              rasterized_width as usize * 4,
                                                              &CGColorSpace::create_device_rgb(),
                                                              kCGImageAlphaPremultipliedLast);
        cg_context.set_allows_font_smoothing(enable_aa);
        cg_context.set_should_smooth_fonts(enable_aa);
        cg_context.set_allows_antialiasing(enable_aa);
        cg_context.set_should_antialias(enable_aa);
        cg_context.set_rgb_fill_color(1.0, 1.0, 1.0, 1.0);

        let rasterization_origin = CGPoint {
            x: -rasterized_left as f64,
            y: rasterized_descent as f64,
        };
        ct_font.draw_glyphs(&[glyph], &[rasterization_origin], cg_context.clone());

        let rasterized_area = (rasterized_width * rasterized_height) as usize;
        let mut rasterized_pixels = cg_context.data().to_vec();
        for i in 0..rasterized_area {
            let alpha = (rasterized_pixels[i * 4 + 3] as f32) / 255.0;
            for j in 0..3 {
                rasterized_pixels[i * 4 + j] =
                    ((rasterized_pixels[i * 4 + j] as f32) / alpha) as u8;
            }
        }

        Some(RasterizedGlyph {
            left: rasterized_left,
            top: (bounds.size.height + bounds.origin.y).ceil() as i32,
            width: rasterized_width,
            height: rasterized_height,
            bytes: rasterized_pixels,
        })
    }
}

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

use app_units::Au;
use core_graphics::base::kCGImageAlphaPremultipliedLast;
use core_graphics::color_space::CGColorSpace;
use core_graphics::context::CGContext;
use core_graphics::data_provider::CGDataProvider;
use core_graphics::font::{CGFont, CGGlyph};
use core_graphics::geometry::CGPoint;
use core_text::font::CTFont;
use core_text::font_descriptor::kCTFontDefaultOrientation;
use core_text;
use internal_types::FontRenderMode;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use webrender_traits::FontKey;

pub type NativeFontHandle = CGFont;

pub struct FontContext {
    cg_fonts: HashMap<FontKey, CGFont>,
    ct_fonts: HashMap<(FontKey, Au), CTFont>,
}

pub struct RasterizedGlyph {
    pub left: i32,
    pub top: i32,
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

impl RasterizedGlyph {
    pub fn blank() -> RasterizedGlyph {
        RasterizedGlyph {
            left: 0,
            top: 0,
            width: 0,
            height: 0,
            bytes: vec![],
        }
    }
}

impl FontContext {
    pub fn new() -> FontContext {
        FontContext {
            cg_fonts: HashMap::new(),
            ct_fonts: HashMap::new(),
        }
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8]) {
        if self.cg_fonts.contains_key(font_key) {
            return
        }

        let data_provider = CGDataProvider::from_buffer(bytes);
        let cg_font = match CGFont::from_data_provider(data_provider) {
            Err(_) => return,
            Ok(cg_font) => cg_font,
        };
        self.cg_fonts.insert((*font_key).clone(), cg_font);
    }

    pub fn add_native_font(&mut self, font_key: &FontKey, native_font_handle: CGFont) {
        if self.cg_fonts.contains_key(font_key) {
            return
        }

        self.cg_fonts.insert((*font_key).clone(), native_font_handle);
    }

    pub fn get_glyph(&mut self,
                     font_key: FontKey,
                     size: Au,
                     character: u32,
                     device_pixel_ratio: f32,
                     render_mode: FontRenderMode)
                     -> Option<RasterizedGlyph> {
        let ct_font = match self.ct_fonts.entry(((font_key).clone(), size)) {
            Entry::Occupied(entry) => (*entry.get()).clone(),
            Entry::Vacant(entry) => {
                let cg_font = match self.cg_fonts.get(&font_key) {
                    None => return Some(RasterizedGlyph::blank()),
                    Some(cg_font) => cg_font,
                };
                let ct_font = core_text::font::new_from_CGFont(
                        cg_font,
                        size.to_f64_px() * (device_pixel_ratio as f64));
                entry.insert(ct_font.clone());
                ct_font
            }
        };

        let glyph = character as CGGlyph;
        let bounds = ct_font.get_bounding_rects_for_glyphs(kCTFontDefaultOrientation, &[glyph]);

        let rasterized_left = bounds.origin.x.floor() as i32;
        let rasterized_width =
            (bounds.origin.x - (rasterized_left as f64) + bounds.size.width).ceil() as u32;
        let rasterized_descent = (-bounds.origin.y).ceil() as i32;
        let rasterized_ascent = (bounds.size.height + bounds.origin.y).ceil() as i32;
        let rasterized_height = (rasterized_descent + rasterized_ascent) as u32;
        if rasterized_width == 0 || rasterized_height == 0 {
            return Some(RasterizedGlyph::blank())
        }

        let mut cg_context = CGContext::create_bitmap_context(rasterized_width as usize,
                                                              rasterized_height as usize,
                                                              8,
                                                              rasterized_width as usize * 4,
                                                              &CGColorSpace::create_device_rgb(),
                                                              kCGImageAlphaPremultipliedLast);
        // TODO(gw): Add subpixel render mode support on mac.
        let enable_aa = render_mode != FontRenderMode::Mono;
        cg_context.set_allows_font_smoothing(enable_aa);
        cg_context.set_should_smooth_fonts(enable_aa);
        cg_context.set_allows_antialiasing(enable_aa);
        cg_context.set_should_antialias(enable_aa);
        cg_context.set_rgb_fill_color(1.0, 1.0, 1.0, 1.0);

        let rasterization_origin = CGPoint {
            x: -rasterized_left as f64,
            y: rasterized_descent as f64,
        };
        ct_font.draw_glyphs(&[glyph], &[rasterization_origin], cg_context.clone());

        let rasterized_area = (rasterized_width * rasterized_height) as usize;
        let mut rasterized_pixels = cg_context.data().to_vec();
        for i in 0..rasterized_area {
            let alpha = (rasterized_pixels[i * 4 + 3] as f32) / 255.0;
            for j in 0..3 {
                rasterized_pixels[i * 4 + j] =
                    ((rasterized_pixels[i * 4 + j] as f32) / alpha) as u8;
            }
        }

        Some(RasterizedGlyph {
            left: rasterized_left,
            top: (bounds.size.height + bounds.origin.y).ceil() as i32,
            width: rasterized_width,
            height: rasterized_height,
            bytes: rasterized_pixels,
        })
    }
}

<|endoftext|>


<commit_before>extern crate pty;
extern crate libc;

use self::pty::prelude::*;

use std::ffi::CString;

use std::io::prelude::*;
use std::process::{Command, Stdio};
use std::ptr;
use std::string::String;

fn main() {
    let fork = Fork::from_ptmx().unwrap();

    if let Some(mut master) = fork.is_parent().ok() {
        let mut string = String::new();

        master.read_to_string(&mut string).unwrap_or_else(|e| panic!(e));

        let output = Command::new("tty")
            .stdin(Stdio::inherit())
            .output()
            .unwrap()
            .stdout;

        let parent_tty = String::from_utf8_lossy(&output);
        let child_tty = string.trim();

        println!("child_tty(\"{}\")[{}] != \"{}\" => {}", child_tty, child_tty.len(), "", child_tty != "");
        assert!(child_tty != "");
        assert!(child_tty != parent_tty);

        let mut parent_tty_dir: Vec<&str> = parent_tty.split("/").collect();
        let mut child_tty_dir: Vec<&str> = child_tty.split("/").collect();

        parent_tty_dir.pop();
        child_tty_dir.pop();

        assert_eq!(parent_tty_dir, child_tty_dir);
    } else {
        let mut ptrs = [CString::new("tty").unwrap().as_ptr(), ptr::null()];
        let _ = unsafe { libc::execvp(*ptrs.as_ptr(), ptrs.as_mut_ptr()) };
    }
}
<commit_msg>fix feeing of memory problem in example 'new.rs'<commit_after>extern crate pty;
extern crate libc;

use self::pty::prelude::*;

use std::io::prelude::*;
use std::process::{Command, Stdio};

fn main() {
    let fork = Fork::from_ptmx().unwrap();

    if let Some(mut master) = fork.is_parent().ok() {
        let mut string = String::new();

        master.read_to_string(&mut string).unwrap_or_else(|e| panic!(e));

        let output = Command::new("tty")
            .stdin(Stdio::inherit())
            .output()
            .unwrap()
            .stdout;
        let output_str = String::from_utf8_lossy(&output);

        let parent_tty = output_str.trim();
        let child_tty = string.trim();

        println!("child_tty(\"{}\")[{}] != \"{}\" => {}", child_tty, child_tty.len(), "", child_tty != "");
        assert!(child_tty != "");
        assert!(child_tty != parent_tty);

        let mut parent_tty_dir: Vec<&str> = parent_tty.split("/").collect();
        let mut child_tty_dir: Vec<&str> = child_tty.split("/").collect();

        parent_tty_dir.pop();
        child_tty_dir.pop();

        assert_eq!(parent_tty_dir, child_tty_dir);
    } else {
        let _ = Command::new("tty").status();
    }
}
<|endoftext|>


<commit_before>//! The thread-local state.

use std::{mem, thread};
use std::cell::RefCell;
use {global, hazard, guard};
use garbage::Garbage;

thread_local! {
    /// The state of this thread.
    static STATE: RefCell<State> = RefCell::new(State::default());
}

/// Add new garbage to be deleted.
///
/// This garbage is pushed to a thread-local queue. When enough garbage is accumulated in the
/// thread, it is exported to the global state.
pub fn add_garbage(garbage: Garbage) {
    // Since this function can trigger a GC, it must not be called inside a guard constructor.
    guard::debug_assert_no_create();

    if STATE.state() == thread::LocalKeyState::Destroyed {
        // The state was deinitialized, so we must rely on the global state for queueing garbage.
        global::export_garbage(vec![garbage]);
    } else {
        // Add the garbage.
        if STATE.with(|s| s.borrow_mut().add_garbage(garbage)) {
            // The local state exported garbage to the global state, hence we must tick in order to
            // ensure that the garbage is periodically collected.
            global::tick();
        }
    }
}

/// Get a blocked hazard.
///
/// If possible, this will simply pop one of the thread-local cache of hazards. Otherwise, one must
/// be registered in the global state.
///
/// # Fence
///
/// This does not fence, and you must thus be careful with updating the value afterwards, as
/// reordering can happen, meaning that the hazard has not been blocked yet.
pub fn get_hazard() -> hazard::Writer {
    if STATE.state() == thread::LocalKeyState::Destroyed {
        // The state was deinitialized, so we must rely on the global state for creating new
        // hazards.
        global::create_hazard()
    } else {
        STATE.with(|s| s.borrow_mut().get_hazard())
    }
}

/// Free a hazard.
///
/// This frees a hazard to the thread-local cache of hazards.
///
/// It is important that the hazard is **not** in blocked state, as such thing can cause infinite
/// looping.
///
/// # Panics
///
/// This might panic in debug mode if the hazard given is in blocked state.
pub fn free_hazard(hazard: hazard::Writer) {
    // Since this function can trigger a GC, it must not be called inside a guard constructor.
    guard::debug_assert_no_create();

    debug_assert!(!hazard.is_blocked(), "Freeing a blocked hazards. See docs.");

    if STATE.state() == thread::LocalKeyState::Destroyed {
        // Since the state was deinitialized, we cannot store it for later reuse, so we are forced
        // to simply kill the hazard.
        hazard.kill();
    } else {
        STATE.with(|s| s.borrow_mut().free_hazard(hazard));
    }
}

/// Export the garbage of this thread to the global state.
///
/// This is useful for propagating accumulated garbage such that it can be destroyed by the next
/// garbage collection.
pub fn export_garbage() {
    // Since this function can trigger a GC, it must not be called inside a guard constructor.
    guard::debug_assert_no_create();

    // We can only export when the TLS variable isn't destroyed. Otherwise, there would be nothing
    // to export!
    if STATE.state() != thread::LocalKeyState::Destroyed {
        STATE.with(|s| s.borrow_mut().export_garbage());
        // We tick after the state is no longer reserved, as the tick could potentially call
        // destructor that access the TLS variable.
        global::tick();
    }
}

/// A thread-local state.
#[derive(Default)]
struct State {
    /// The cached garbage waiting to be exported to the global state.
    garbage: Vec<Garbage>,
    /// The cache of currently available hazards.
    ///
    /// We maintain this cache to avoid the performance hit of creating new hazards.
    ///
    /// The hazards in this vector are not necessarily in state "free". Only when a sufficient
    /// amount of available hazards has accumulated, they will be set to free. This means that we
    /// don't have to reset the state of a hazard after usage, giving a quite significant speed-up.
    available_hazards: Vec<hazard::Writer>,
    /// The hazards in the cache before this index are free.
    ///
    /// This number keeps track what hazards in `self.available_hazard` are set to state "free".
    /// Before this index, every hazard must be set to "free".
    ///
    /// It is useful for knowing when to free the hazards to allow garbage collection.
    available_hazards_free_before: usize,
}

impl State {
    /// Get the number of hazards in the cache which are not in state "free".
    fn non_free_hazards(&self) -> usize {
        self.available_hazards.len() - self.available_hazards_free_before
    }

    /// See `get_hazard()`.
    fn get_hazard(&mut self) -> hazard::Writer {
        // Check if there is hazards in the cache.
        if let Some(hazard) = self.available_hazards.pop() {
            // There is; we don't need to create a new hazard.

            // Since the hazard popped from the cache is not blocked, we must block the hazard to
            // satisfy the requirements of this function.
            hazard.block();
            hazard
        } else {
            // There is not; we must create a new hazard.
            global::create_hazard()
        }
    }

    /// See `free_hazard()`.
    fn free_hazard(&mut self, hazard: hazard::Writer) {
        /// The maximal amount of hazards before cleaning up.
        ///
        /// With "cleaning up" we mean setting the state of the hazards to "free" in order to allow
        /// garbage collection of the object it is currently protecting.
        const MAX_NON_FREE_HAZARDS: usize = 128;

        // Push the given hazard to the cache.
        self.available_hazards.push(hazard);

        // Check if we exceeded the limit.
        if self.non_free_hazards() > MAX_NON_FREE_HAZARDS {
            // We did; we must now set the non-free hazards to "free".
            for i in &self.available_hazards[self.available_hazards_free_before..] {
                i.set(hazard::State::Free);
            }

            // Update the counter such that we mark the new hazards set to "free".
            self.available_hazards_free_before = self.available_hazards.len();
        }
    }

    /// Queues garbage to destroy.
    ///
    /// Eventually the added garbage will be exported to the global state through
    /// `global::add_garbage()`.
    ///
    /// See `add_garbage` for more information.
    ///
    /// When this happens (i.e. the global state gets the garbage), it returns `true`. Otherwise,
    /// it returns `false`.
    fn add_garbage(&mut self, garbage: Garbage) -> bool {
        /// The maximal amount of garbage before exportation to the global state.
        const MAX_GARBAGE: usize = 128;

        // Push the garbage to the cache of garbage.
        self.garbage.push(garbage);

        // Export the garbage if it exceeds the limit.
        // TODO: use memory instead of items as a metric.
        if self.garbage.len() > MAX_GARBAGE {
            self.export_garbage();
            true
        } else { false }
    }

    /// See `export_garbage()` for more information.
    fn export_garbage(&mut self) {
        // Clear the vector and export the garbage.
        global::export_garbage(mem::replace(&mut self.garbage, Vec::new()));
    }
}

impl Drop for State {
    fn drop(&mut self) {
        // Clear every hazard to "dead" state.
        for hazard in self.available_hazards.drain(..) {
            hazard.kill();
        }

        // The thread is exiting, thus we must export the garbage to the global state to avoid
        // memory leaks. It is very important that this does indeed not tick, as causing garbage
        // collection means accessing RNG state, a TLS variable, which cannot be done when, we are
        // here, after it has deinitialized.
        // TODO: Figure out a way we can tick anyway.
        self.export_garbage();
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use garbage::Garbage;
    use hazard;
    use std::thread;

    #[test]
    fn dtor_runs() {
        fn dtor(x: *const u8) {
            unsafe {
                *(x as *mut u8) = 1;
            }
        }

        for _ in 0..1000 {
            let b = Box::new(0);
            let h = get_hazard();
            h.set(hazard::State::Protect(&*b));
            add_garbage(Garbage::new(&*b, dtor));
            ::gc();
            assert_eq!(*b, 0);
            ::gc();
            h.set(hazard::State::Free);
            ::gc();
            assert_eq!(*b, 1);
        }
    }

    #[test]
    fn dtor_runs_cross_thread() {
        fn dtor(x: *const u8) {
            unsafe {
                *(x as *mut u8) = 1;
            }
        }

        for _ in 0..1000 {
            let b = Box::new(0);
            let bptr = &*b as *const _ as usize;
            let h = thread::spawn(move || {
                let h = get_hazard();
                h.set(hazard::State::Protect(bptr as *const u8));
                h
            }).join().unwrap();
            add_garbage(Garbage::new(&*b, dtor));
            ::gc();
            assert_eq!(*b, 0);
            ::gc();
            h.set(hazard::State::Free);
            ::gc();
            assert_eq!(*b, 1);
        }
    }

    #[test]
    fn kill_hazards() {
        fn dtor(x: *const u8) {
            unsafe {
                *(x as *mut u8) = 1;
            }
        }

        for _ in 0..1000 {
            let b = thread::spawn(move || {
                let b = Box::new(0);
                let h = get_hazard();
                h.set(hazard::State::Protect(&*b));
                add_garbage(Garbage::new(&*b, dtor));
                ::gc();
                assert_eq!(*b, 0);
                b
            }).join().unwrap();
            ::gc();
            assert_eq!(*b, 1);
        }
    }

    #[cfg(debug_assertions)]
    #[test]
    #[should_panic]
    fn debug_free_blocked() {
        use std::mem;

        let (writer, reader) = hazard::create();
        mem::forget(reader);

        free_hazard(writer);
    }
}
<commit_msg>Set down `MAX_NON_FREE_HAZARDS` in `conc::local` to avoid unnecessarily high memory usage.<commit_after>//! The thread-local state.

use std::{mem, thread};
use std::cell::RefCell;
use {global, hazard, guard};
use garbage::Garbage;

thread_local! {
    /// The state of this thread.
    static STATE: RefCell<State> = RefCell::new(State::default());
}

/// Add new garbage to be deleted.
///
/// This garbage is pushed to a thread-local queue. When enough garbage is accumulated in the
/// thread, it is exported to the global state.
pub fn add_garbage(garbage: Garbage) {
    // Since this function can trigger a GC, it must not be called inside a guard constructor.
    guard::debug_assert_no_create();

    if STATE.state() == thread::LocalKeyState::Destroyed {
        // The state was deinitialized, so we must rely on the global state for queueing garbage.
        global::export_garbage(vec![garbage]);
    } else {
        // Add the garbage.
        if STATE.with(|s| s.borrow_mut().add_garbage(garbage)) {
            // The local state exported garbage to the global state, hence we must tick in order to
            // ensure that the garbage is periodically collected.
            global::tick();
        }
    }
}

/// Get a blocked hazard.
///
/// If possible, this will simply pop one of the thread-local cache of hazards. Otherwise, one must
/// be registered in the global state.
///
/// # Fence
///
/// This does not fence, and you must thus be careful with updating the value afterwards, as
/// reordering can happen, meaning that the hazard has not been blocked yet.
pub fn get_hazard() -> hazard::Writer {
    if STATE.state() == thread::LocalKeyState::Destroyed {
        // The state was deinitialized, so we must rely on the global state for creating new
        // hazards.
        global::create_hazard()
    } else {
        STATE.with(|s| s.borrow_mut().get_hazard())
    }
}

/// Free a hazard.
///
/// This frees a hazard to the thread-local cache of hazards.
///
/// It is important that the hazard is **not** in blocked state, as such thing can cause infinite
/// looping.
///
/// # Panics
///
/// This might panic in debug mode if the hazard given is in blocked state.
pub fn free_hazard(hazard: hazard::Writer) {
    // Since this function can trigger a GC, it must not be called inside a guard constructor.
    guard::debug_assert_no_create();

    debug_assert!(!hazard.is_blocked(), "Freeing a blocked hazards. See docs.");

    if STATE.state() == thread::LocalKeyState::Destroyed {
        // Since the state was deinitialized, we cannot store it for later reuse, so we are forced
        // to simply kill the hazard.
        hazard.kill();
    } else {
        STATE.with(|s| s.borrow_mut().free_hazard(hazard));
    }
}

/// Export the garbage of this thread to the global state.
///
/// This is useful for propagating accumulated garbage such that it can be destroyed by the next
/// garbage collection.
pub fn export_garbage() {
    // Since this function can trigger a GC, it must not be called inside a guard constructor.
    guard::debug_assert_no_create();

    // We can only export when the TLS variable isn't destroyed. Otherwise, there would be nothing
    // to export!
    if STATE.state() != thread::LocalKeyState::Destroyed {
        STATE.with(|s| s.borrow_mut().export_garbage());
        // We tick after the state is no longer reserved, as the tick could potentially call
        // destructor that access the TLS variable.
        global::tick();
    }
}

/// A thread-local state.
#[derive(Default)]
struct State {
    /// The cached garbage waiting to be exported to the global state.
    garbage: Vec<Garbage>,
    /// The cache of currently available hazards.
    ///
    /// We maintain this cache to avoid the performance hit of creating new hazards.
    ///
    /// The hazards in this vector are not necessarily in state "free". Only when a sufficient
    /// amount of available hazards has accumulated, they will be set to free. This means that we
    /// don't have to reset the state of a hazard after usage, giving a quite significant speed-up.
    available_hazards: Vec<hazard::Writer>,
    /// The hazards in the cache before this index are free.
    ///
    /// This number keeps track what hazards in `self.available_hazard` are set to state "free".
    /// Before this index, every hazard must be set to "free".
    ///
    /// It is useful for knowing when to free the hazards to allow garbage collection.
    available_hazards_free_before: usize,
}

impl State {
    /// Get the number of hazards in the cache which are not in state "free".
    fn non_free_hazards(&self) -> usize {
        self.available_hazards.len() - self.available_hazards_free_before
    }

    /// See `get_hazard()`.
    fn get_hazard(&mut self) -> hazard::Writer {
        // Check if there is hazards in the cache.
        if let Some(hazard) = self.available_hazards.pop() {
            // There is; we don't need to create a new hazard.

            // Since the hazard popped from the cache is not blocked, we must block the hazard to
            // satisfy the requirements of this function.
            hazard.block();
            hazard
        } else {
            // There is not; we must create a new hazard.
            global::create_hazard()
        }
    }

    /// See `free_hazard()`.
    fn free_hazard(&mut self, hazard: hazard::Writer) {
        /// The maximal amount of hazards before cleaning up.
        ///
        /// With "cleaning up" we mean setting the state of the hazards to "free" in order to allow
        /// garbage collection of the object it is currently protecting.
        const MAX_NON_FREE_HAZARDS: usize = 16;

        // Push the given hazard to the cache.
        self.available_hazards.push(hazard);

        // Check if we exceeded the limit.
        if self.non_free_hazards() > MAX_NON_FREE_HAZARDS {
            // We did; we must now set the non-free hazards to "free".
            for i in &self.available_hazards[self.available_hazards_free_before..] {
                i.set(hazard::State::Free);
            }

            // Update the counter such that we mark the new hazards set to "free".
            self.available_hazards_free_before = self.available_hazards.len();
        }
    }

    /// Queues garbage to destroy.
    ///
    /// Eventually the added garbage will be exported to the global state through
    /// `global::add_garbage()`.
    ///
    /// See `add_garbage` for more information.
    ///
    /// When this happens (i.e. the global state gets the garbage), it returns `true`. Otherwise,
    /// it returns `false`.
    fn add_garbage(&mut self, garbage: Garbage) -> bool {
        /// The maximal amount of garbage before exportation to the global state.
        const MAX_GARBAGE: usize = 128;

        // Push the garbage to the cache of garbage.
        self.garbage.push(garbage);

        // Export the garbage if it exceeds the limit.
        // TODO: use memory instead of items as a metric.
        if self.garbage.len() > MAX_GARBAGE {
            self.export_garbage();
            true
        } else { false }
    }

    /// See `export_garbage()` for more information.
    fn export_garbage(&mut self) {
        // Clear the vector and export the garbage.
        global::export_garbage(mem::replace(&mut self.garbage, Vec::new()));
    }
}

impl Drop for State {
    fn drop(&mut self) {
        // Clear every hazard to "dead" state.
        for hazard in self.available_hazards.drain(..) {
            hazard.kill();
        }

        // The thread is exiting, thus we must export the garbage to the global state to avoid
        // memory leaks. It is very important that this does indeed not tick, as causing garbage
        // collection means accessing RNG state, a TLS variable, which cannot be done when, we are
        // here, after it has deinitialized.
        // TODO: Figure out a way we can tick anyway.
        self.export_garbage();
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use garbage::Garbage;
    use hazard;
    use std::thread;

    #[test]
    fn dtor_runs() {
        fn dtor(x: *const u8) {
            unsafe {
                *(x as *mut u8) = 1;
            }
        }

        for _ in 0..1000 {
            let b = Box::new(0);
            let h = get_hazard();
            h.set(hazard::State::Protect(&*b));
            add_garbage(Garbage::new(&*b, dtor));
            ::gc();
            assert_eq!(*b, 0);
            ::gc();
            h.set(hazard::State::Free);
            ::gc();
            assert_eq!(*b, 1);
        }
    }

    #[test]
    fn dtor_runs_cross_thread() {
        fn dtor(x: *const u8) {
            unsafe {
                *(x as *mut u8) = 1;
            }
        }

        for _ in 0..1000 {
            let b = Box::new(0);
            let bptr = &*b as *const _ as usize;
            let h = thread::spawn(move || {
                let h = get_hazard();
                h.set(hazard::State::Protect(bptr as *const u8));
                h
            }).join().unwrap();
            add_garbage(Garbage::new(&*b, dtor));
            ::gc();
            assert_eq!(*b, 0);
            ::gc();
            h.set(hazard::State::Free);
            ::gc();
            assert_eq!(*b, 1);
        }
    }

    #[test]
    fn kill_hazards() {
        fn dtor(x: *const u8) {
            unsafe {
                *(x as *mut u8) = 1;
            }
        }

        for _ in 0..1000 {
            let b = thread::spawn(move || {
                let b = Box::new(0);
                let h = get_hazard();
                h.set(hazard::State::Protect(&*b));
                add_garbage(Garbage::new(&*b, dtor));
                ::gc();
                assert_eq!(*b, 0);
                b
            }).join().unwrap();
            ::gc();
            assert_eq!(*b, 1);
        }
    }

    #[cfg(debug_assertions)]
    #[test]
    #[should_panic]
    fn debug_free_blocked() {
        use std::mem;

        let (writer, reader) = hazard::create();
        mem::forget(reader);

        free_hazard(writer);
    }
}
<|endoftext|>


<commit_before>use std::{mem, time::Duration};
use tokio::{
    fs,
    io::{AsyncReadExt, AsyncWriteExt},
    process, time,
};
use tokio_serial::SerialPortBuilderExt;

struct SocatFixture {
    process: process::Child,
    port_a: String,
    port_b: String,
}

cfg_if::cfg_if! {
    if #[cfg(unix)] {
        const DEFAULT_TEST_PORT_NAMES: &str = "/dev/ttyUSB0;/dev/ttyUSB1";
    }
    else {
        const DEFAULT_TEST_PORT_NAMES: &str = "COM10;COM11";
    }
}

impl Drop for SocatFixture {
    fn drop(&mut self) {
        if let Some(id) = self.process.id() {
            log::trace!("stopping socat process (id: {})...", id);
            self.process.start_kill().ok();
            std::thread::sleep(Duration::from_millis(250));
            log::trace!("removing link: {}", self.port_a.as_str());
            std::fs::remove_file(self.port_a.as_str()).ok();
            log::trace!("removing link: {}", self.port_b.as_str());
            std::fs::remove_file(self.port_b.as_str()).ok();
        }
    }
}

impl SocatFixture {
    pub async fn new(port_a: &str, port_b: &str) -> Self {
        let args = [
            format!("PTY,link={}", port_a),
            format!("PTY,link={}", port_b),
        ];
        log::trace!("starting process: socat {} {}", args[0], args[1]);

        let child = process::Command::new("socat")
            .args(&args)
            .spawn()
            .expect("unable to spawn socat process");
        log::trace!(".... done! (pid: {:?})", child.id().unwrap());

        time::sleep(Duration::from_millis(500)).await;

        Self {
            process: child,
            port_a: port_a.to_owned(),
            port_b: port_b.to_owned(),
        }
    }
}

#[tokio::test]
async fn send_recv() {
    env_logger::init();

    let port_names: Vec<&str> = std::option_env!("TEST_PORT_NAMES")
        .unwrap_or(DEFAULT_TEST_PORT_NAMES)
        .split(';')
        .collect();

    let port_a = port_names[0];
    let port_b = port_names[1];

    assert_eq!(port_names.len(), 2, "expected two port names");

    #[cfg(unix)]
    let fixture = SocatFixture::new(port_a, port_b).await;

    let mut sender = tokio_serial::new(port_a, 9600)
        .open_native_async()
        .expect("unable to open serial port");
    let mut receiver = tokio_serial::new(port_b, 9600)
        .open_native_async()
        .expect("unable to open serial port");

    log::trace!("sending test message");
    let message = b"This is a test message";
    sender
        .write(message)
        .await
        .expect("unable to write test message");

    log::trace!("receiving test message");
    let mut buf = [0u8; 32];
    let n = receiver
        .read(&mut buf[..])
        .await
        .expect("unable to read test message");

    log::trace!("checking test message");
    assert_eq!(&buf[..n], message);
}
<commit_msg>use write_all and read_exact instead of write and read for test<commit_after>use std::time::Duration;
use tokio::{
    io::{AsyncReadExt, AsyncWriteExt},
    process, time,
};
use tokio_serial::SerialPortBuilderExt;

struct SocatFixture {
    process: process::Child,
    port_a: String,
    port_b: String,
}

cfg_if::cfg_if! {
    if #[cfg(unix)] {
        const DEFAULT_TEST_PORT_NAMES: &str = "/dev/ttyUSB0;/dev/ttyUSB1";
    }
    else {
        const DEFAULT_TEST_PORT_NAMES: &str = "COM10;COM11";
    }
}

impl Drop for SocatFixture {
    fn drop(&mut self) {
        if let Some(id) = self.process.id() {
            log::trace!("stopping socat process (id: {})...", id);
            self.process.start_kill().ok();
            std::thread::sleep(Duration::from_millis(250));
            log::trace!("removing link: {}", self.port_a.as_str());
            std::fs::remove_file(self.port_a.as_str()).ok();
            log::trace!("removing link: {}", self.port_b.as_str());
            std::fs::remove_file(self.port_b.as_str()).ok();
        }
    }
}

impl SocatFixture {
    pub async fn new(port_a: &str, port_b: &str) -> Self {
        let args = [
            format!("PTY,link={}", port_a),
            format!("PTY,link={}", port_b),
        ];
        log::trace!("starting process: socat {} {}", args[0], args[1]);

        let child = process::Command::new("socat")
            .args(&args)
            .spawn()
            .expect("unable to spawn socat process");
        log::trace!(".... done! (pid: {:?})", child.id().unwrap());

        time::sleep(Duration::from_millis(500)).await;

        Self {
            process: child,
            port_a: port_a.to_owned(),
            port_b: port_b.to_owned(),
        }
    }
}

#[tokio::test]
async fn send_recv() {
    env_logger::init();

    let port_names: Vec<&str> = std::option_env!("TEST_PORT_NAMES")
        .unwrap_or(DEFAULT_TEST_PORT_NAMES)
        .split(';')
        .collect();

    let port_a = port_names[0];
    let port_b = port_names[1];

    assert_eq!(port_names.len(), 2, "expected two port names");

    #[cfg(unix)]
    let _fixture = SocatFixture::new(port_a, port_b).await;

    let mut sender = tokio_serial::new(port_a, 9600)
        .open_native_async()
        .expect("unable to open serial port");
    let mut receiver = tokio_serial::new(port_b, 9600)
        .open_native_async()
        .expect("unable to open serial port");

    log::trace!("sending test message");
    let message = b"This is a test message";
    sender
        .write_all(message)
        .await
        .expect("unable to write test message");

    log::trace!("receiving test message");
    let mut buf = [0u8; 32];
    let n = receiver
        .read_exact(&mut buf[..message.len()])
        .await
        .expect("unable to read test message");

    log::trace!("checking test message");
    assert_eq!(&buf[..n], message);
}
<|endoftext|>


<commit_before>use lib::*;
use ser::{Error, Impossible, Serialize, Serializer};

impl Error for fmt::Error {
    fn custom<T: Display>(_msg: T) -> Self {
        fmt::Error
    }
}

macro_rules! fmt_primitives {
    ($($f:ident: $t:ty,)*) => {
        $(
            fn $f(self, v: $t) -> fmt::Result {
                Display::fmt(&v, self)
            }
        )*
    };
}

impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
    type Ok = ();
    type Error = fmt::Error;
    type SerializeSeq = Impossible<(), fmt::Error>;
    type SerializeTuple = Impossible<(), fmt::Error>;
    type SerializeTupleStruct = Impossible<(), fmt::Error>;
    type SerializeTupleVariant = Impossible<(), fmt::Error>;
    type SerializeMap = Impossible<(), fmt::Error>;
    type SerializeStruct = Impossible<(), fmt::Error>;
    type SerializeStructVariant = Impossible<(), fmt::Error>;

    fmt_primitives! {
        serialize_bool: bool,
        serialize_i8: i8,
        serialize_i16: i16,
        serialize_i32: i32,
        serialize_i64: i64,
        serialize_u8: u8,
        serialize_u16: u16,
        serialize_u32: u32,
        serialize_u64: u64,
        serialize_f32: f32,
        serialize_f64: f64,
        serialize_char: char,
        serialize_str: &str,
        serialize_unit_struct: &'static str,
    }

    fn serialize_unit_variant(
        self,
        _name: &'static str,
        _variant_index: u32,
        variant: &'static str,
    ) -> fmt::Result {
        Display::fmt(variant, self)
    }

    fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> fmt::Result
    where
        T: Serialize,
    {
        Serialize::serialize(value, self)
    }

    fn serialize_bytes(self, _v: &[u8]) -> fmt::Result {
        Err(fmt::Error)
    }

    fn serialize_none(self) -> fmt::Result {
        Err(fmt::Error)
    }

    fn serialize_some<T: ?Sized>(self, _value: &T) -> fmt::Result
    where
        T: Serialize,
    {
        Err(fmt::Error)
    }

    fn serialize_unit(self) -> fmt::Result {
        Err(fmt::Error)
    }

    fn serialize_newtype_variant<T: ?Sized>(
        self,
        _name: &'static str,
        _variant_index: u32,
        _variant: &'static str,
        _value: &T,
    ) -> fmt::Result
    where
        T: Serialize,
    {
        Err(fmt::Error)
    }

    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_tuple_struct(
        self,
        _name: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeTupleStruct, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_tuple_variant(
        self,
        _name: &'static str,
        _variant_index: u32,
        _variant: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeTupleVariant, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_struct(
        self,
        _name: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeStruct, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_struct_variant(
        self,
        _name: &'static str,
        _variant_index: u32,
        _variant: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeStructVariant, fmt::Error> {
        Err(fmt::Error)
    }

    fn collect_str<T: ?Sized>(self, value: &T) -> fmt::Result
    where
        T: Display,
    {
        Display::fmt(value, self)
    }
}
<commit_msg>Add 128-bit integer support for Formatter<commit_after>use lib::*;
use ser::{Error, Impossible, Serialize, Serializer};

impl Error for fmt::Error {
    fn custom<T: Display>(_msg: T) -> Self {
        fmt::Error
    }
}

macro_rules! fmt_primitives {
    ($($f:ident: $t:ty,)*) => {
        $(
            fn $f(self, v: $t) -> fmt::Result {
                Display::fmt(&v, self)
            }
        )*
    };
}

impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
    type Ok = ();
    type Error = fmt::Error;
    type SerializeSeq = Impossible<(), fmt::Error>;
    type SerializeTuple = Impossible<(), fmt::Error>;
    type SerializeTupleStruct = Impossible<(), fmt::Error>;
    type SerializeTupleVariant = Impossible<(), fmt::Error>;
    type SerializeMap = Impossible<(), fmt::Error>;
    type SerializeStruct = Impossible<(), fmt::Error>;
    type SerializeStructVariant = Impossible<(), fmt::Error>;

    fmt_primitives! {
        serialize_bool: bool,
        serialize_i8: i8,
        serialize_i16: i16,
        serialize_i32: i32,
        serialize_i64: i64,
        serialize_u8: u8,
        serialize_u16: u16,
        serialize_u32: u32,
        serialize_u64: u64,
        serialize_f32: f32,
        serialize_f64: f64,
        serialize_char: char,
        serialize_str: &str,
        serialize_unit_struct: &'static str,
    }

    serde_if_integer128! {
        fmt_primitives! {
            serialize_i128: i128,
            serialize_u128: u128,
        }
    }

    fn serialize_unit_variant(
        self,
        _name: &'static str,
        _variant_index: u32,
        variant: &'static str,
    ) -> fmt::Result {
        Display::fmt(variant, self)
    }

    fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> fmt::Result
    where
        T: Serialize,
    {
        Serialize::serialize(value, self)
    }

    fn serialize_bytes(self, _v: &[u8]) -> fmt::Result {
        Err(fmt::Error)
    }

    fn serialize_none(self) -> fmt::Result {
        Err(fmt::Error)
    }

    fn serialize_some<T: ?Sized>(self, _value: &T) -> fmt::Result
    where
        T: Serialize,
    {
        Err(fmt::Error)
    }

    fn serialize_unit(self) -> fmt::Result {
        Err(fmt::Error)
    }

    fn serialize_newtype_variant<T: ?Sized>(
        self,
        _name: &'static str,
        _variant_index: u32,
        _variant: &'static str,
        _value: &T,
    ) -> fmt::Result
    where
        T: Serialize,
    {
        Err(fmt::Error)
    }

    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_tuple_struct(
        self,
        _name: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeTupleStruct, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_tuple_variant(
        self,
        _name: &'static str,
        _variant_index: u32,
        _variant: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeTupleVariant, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_struct(
        self,
        _name: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeStruct, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_struct_variant(
        self,
        _name: &'static str,
        _variant_index: u32,
        _variant: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeStructVariant, fmt::Error> {
        Err(fmt::Error)
    }

    fn collect_str<T: ?Sized>(self, value: &T) -> fmt::Result
    where
        T: Display,
    {
        Display::fmt(value, self)
    }
}
<|endoftext|>


<commit_before>//! Tests for custom json target specifications.

use cargo_test_support::is_nightly;
use cargo_test_support::{basic_manifest, project};

#[cargo_test]
fn custom_target_minimal() {
    if !is_nightly() {
        // Requires features no_core, lang_items
        return;
    }
    let p = project()
        .file(
            "src/lib.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![no_core]

                pub fn foo() -> u32 {
                    42
                }

                #[lang = "sized"]
                pub trait Sized {
                    // Empty.
                }
                #[lang = "copy"]
                pub trait Copy {
                    // Empty.
                }
            "#,
        )
        .file(
            "custom-target.json",
            r#"
                {
                    "llvm-target": "x86_64-unknown-none-gnu",
                    "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                    "arch": "x86_64",
                    "target-endian": "little",
                    "target-pointer-width": "64",
                    "target-c-int-width": "32",
                    "os": "none",
                    "linker-flavor": "ld.lld"
                }
            "#,
        )
        .build();

    p.cargo("build --lib --target custom-target.json -v").run();
    p.cargo("build --lib --target src/../custom-target.json -v")
        .run();

    // Ensure that the correct style of flag is passed to --target with doc tests.
    p.cargo("test --doc --target src/../custom-target.json -v -Zdoctest-xcompile")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("[RUNNING] `rustdoc [..]--target [..]foo/custom-target.json[..]")
        .run();
}

#[cargo_test]
fn custom_target_dependency() {
    if !is_nightly() {
        // Requires features no_core, lang_items, optin_builtin_traits
        return;
    }
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]

                name = "foo"
                version = "0.0.1"
                authors = ["author@example.com"]

                [dependencies]
                bar = { path = "bar" }
            "#,
        )
        .file(
            "src/lib.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![feature(optin_builtin_traits)]
                #![no_core]

                extern crate bar;

                pub fn foo() -> u32 {
                    bar::bar()
                }

                #[lang = "freeze"]
                unsafe auto trait Freeze {}
            "#,
        )
        .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
        .file(
            "bar/src/lib.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![no_core]

                pub fn bar() -> u32 {
                    42
                }

                #[lang = "sized"]
                pub trait Sized {
                    // Empty.
                }
                #[lang = "copy"]
                pub trait Copy {
                    // Empty.
                }
            "#,
        )
        .file(
            "custom-target.json",
            r#"
                {
                    "llvm-target": "x86_64-unknown-none-gnu",
                    "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                    "arch": "x86_64",
                    "target-endian": "little",
                    "target-pointer-width": "64",
                    "target-c-int-width": "32",
                    "os": "none",
                    "linker-flavor": "ld.lld"
                }
            "#,
        )
        .build();

    p.cargo("build --lib --target custom-target.json -v").run();
}

#[cargo_test]
fn custom_bin_target() {
    if !is_nightly() {
        // Requires features no_core, lang_items
        return;
    }
    let p = project()
        .file(
            "src/main.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![no_core]
                #![no_main]

                #[lang = "sized"]
                pub trait Sized {
                    // Empty.
                }
                #[lang = "copy"]
                pub trait Copy {
                    // Empty.
                }
            "#,
        )
        .file(
            "custom-bin-target.json",
            r#"
                {
                    "llvm-target": "x86_64-unknown-none-gnu",
                    "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                    "arch": "x86_64",
                    "target-endian": "little",
                    "target-pointer-width": "64",
                    "target-c-int-width": "32",
                    "os": "none",
                    "linker-flavor": "ld.lld",
                    "linker": "rust-lld",
                    "executables": true
                }
            "#,
        )
        .build();

    p.cargo("build --target custom-bin-target.json -v").run();
}
<commit_msg>Auto merge of #8907 - ehuss:auto_traits, r=alexcrichton<commit_after>//! Tests for custom json target specifications.

use cargo_test_support::is_nightly;
use cargo_test_support::{basic_manifest, project};

#[cargo_test]
fn custom_target_minimal() {
    if !is_nightly() {
        // Requires features no_core, lang_items
        return;
    }
    let p = project()
        .file(
            "src/lib.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![no_core]

                pub fn foo() -> u32 {
                    42
                }

                #[lang = "sized"]
                pub trait Sized {
                    // Empty.
                }
                #[lang = "copy"]
                pub trait Copy {
                    // Empty.
                }
            "#,
        )
        .file(
            "custom-target.json",
            r#"
                {
                    "llvm-target": "x86_64-unknown-none-gnu",
                    "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                    "arch": "x86_64",
                    "target-endian": "little",
                    "target-pointer-width": "64",
                    "target-c-int-width": "32",
                    "os": "none",
                    "linker-flavor": "ld.lld"
                }
            "#,
        )
        .build();

    p.cargo("build --lib --target custom-target.json -v").run();
    p.cargo("build --lib --target src/../custom-target.json -v")
        .run();

    // Ensure that the correct style of flag is passed to --target with doc tests.
    p.cargo("test --doc --target src/../custom-target.json -v -Zdoctest-xcompile")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("[RUNNING] `rustdoc [..]--target [..]foo/custom-target.json[..]")
        .run();
}

#[cargo_test]
fn custom_target_dependency() {
    if !is_nightly() {
        // Requires features no_core, lang_items, auto_traits
        return;
    }
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]

                name = "foo"
                version = "0.0.1"
                authors = ["author@example.com"]

                [dependencies]
                bar = { path = "bar" }
            "#,
        )
        .file(
            "src/lib.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![feature(auto_traits)]
                #![no_core]

                extern crate bar;

                pub fn foo() -> u32 {
                    bar::bar()
                }

                #[lang = "freeze"]
                unsafe auto trait Freeze {}
            "#,
        )
        .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
        .file(
            "bar/src/lib.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![no_core]

                pub fn bar() -> u32 {
                    42
                }

                #[lang = "sized"]
                pub trait Sized {
                    // Empty.
                }
                #[lang = "copy"]
                pub trait Copy {
                    // Empty.
                }
            "#,
        )
        .file(
            "custom-target.json",
            r#"
                {
                    "llvm-target": "x86_64-unknown-none-gnu",
                    "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                    "arch": "x86_64",
                    "target-endian": "little",
                    "target-pointer-width": "64",
                    "target-c-int-width": "32",
                    "os": "none",
                    "linker-flavor": "ld.lld"
                }
            "#,
        )
        .build();

    p.cargo("build --lib --target custom-target.json -v").run();
}

#[cargo_test]
fn custom_bin_target() {
    if !is_nightly() {
        // Requires features no_core, lang_items
        return;
    }
    let p = project()
        .file(
            "src/main.rs",
            r#"
                #![feature(no_core)]
                #![feature(lang_items)]
                #![no_core]
                #![no_main]

                #[lang = "sized"]
                pub trait Sized {
                    // Empty.
                }
                #[lang = "copy"]
                pub trait Copy {
                    // Empty.
                }
            "#,
        )
        .file(
            "custom-bin-target.json",
            r#"
                {
                    "llvm-target": "x86_64-unknown-none-gnu",
                    "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
                    "arch": "x86_64",
                    "target-endian": "little",
                    "target-pointer-width": "64",
                    "target-c-int-width": "32",
                    "os": "none",
                    "linker-flavor": "ld.lld",
                    "linker": "rust-lld",
                    "executables": true
                }
            "#,
        )
        .build();

    p.cargo("build --target custom-bin-target.json -v").run();
}
<|endoftext|>