<commit_before>#![deny(rust_2018_idioms)]

use cargo::{
    core::{
        package::PackageSet,
        registry::PackageRegistry,
        resolver::{self, ResolveOpts},
        source::SourceMap,
        Dependency, Package, PackageId, Source, SourceId, TargetKind,
    },
    sources::RegistrySource,
    util::Config,
};
use itertools::Itertools;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use std::{
    collections::{BTreeMap, BTreeSet, HashSet},
    fs::File,
    io::{Read, Write},
};

/// The list of crates from crates.io
#[derive(Debug, Deserialize)]
struct TopCrates {
    crates: Vec<Crate>,
}

/// A single crate from crates.io
#[derive(Debug, Deserialize)]
struct OneCrate {
    #[serde(rename = "crate")]
    krate: Crate,
}

/// The shared description of a crate
#[derive(Debug, Deserialize)]
struct Crate {
    #[serde(rename = "id")]
    name: String,
}

/// A Cargo.toml file.
#[derive(Serialize)]
struct TomlManifest {
    package: TomlPackage,
    profile: Profiles,
    #[serde(serialize_with = "toml::ser::tables_last")]
    dependencies: BTreeMap<String, DependencySpec>,
}

/// Header of Cargo.toml file.
#[derive(Serialize)]
struct TomlPackage {
    name: String,
    version: String,
    authors: Vec<String>,
}

/// A mapping of a crates name to its identifier used in source code
#[derive(Debug, Serialize)]
struct CrateInformation {
    name: String,
    version: String,
    id: String,
}

/// Hand-curated changes to the crate list
#[derive(Debug, Deserialize)]
struct Modifications {
    #[serde(default)]
    blacklist: Vec<String>,
    #[serde(default)]
    additions: BTreeSet<String>,
}

/// A profile section in a Cargo.toml file
#[derive(Serialize)]
#[serde(rename_all = "kebab-case")]
struct Profile {
    codegen_units: u32,
    incremental: bool,
}

/// Available profile types
#[derive(Serialize)]
struct Profiles {
    dev: Profile,
    release: Profile,
}

#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "kebab-case")]
struct DependencySpec {
    #[serde(skip_serializing_if = "String::is_empty")]
    package: String,
    #[serde(serialize_with = "exact_version")]
    version: String,
    #[serde(skip_serializing_if = "Vec::is_empty")]
    features: Vec<String>,
    #[serde(skip_serializing_if = "is_true")]
    default_features: bool,
}

fn exact_version<S>(version: &String, serializer: S) -> Result<S::Ok, S::Error>
where
    S: serde::Serializer,
{
    format!("={}", version).serialize(serializer)
}

fn is_true(b: &bool) -> bool {
    *b
}

impl Modifications {
    fn blacklisted(&self, name: &str) -> bool {
        self.blacklist.iter().any(|n| n == name)
    }
}

lazy_static! {
    static ref MODIFICATIONS: Modifications = {
        let mut f = File::open("crate-modifications.toml")
            .expect("unable to open crate modifications file");

        let mut d = Vec::new();
        f.read_to_end(&mut d)
            .expect("unable to read crate modifications file");

        toml::from_slice(&d).expect("unable to parse crate modifications file")
    };
}

fn simple_get(url: &str) -> reqwest::Result<reqwest::blocking::Response> {
    reqwest::blocking::ClientBuilder::new()
        .user_agent("Rust Playground - Top Crates Utility")
        .build()?
        .get(url)
        .send()
}

impl TopCrates {
    /// List top 100 crates by number of downloads on crates.io.
    fn download() -> TopCrates {
        let resp =
            simple_get("https://crates.io/api/v1/crates?page=1&per_page=100&sort=downloads")
                .expect("Could not fetch top crates");
        assert!(resp.status().is_success(), "Could not download top crates; HTTP status was {}", resp.status());

        serde_json::from_reader(resp).expect("Invalid JSON")
    }

    fn add_rust_cookbook_crates(&mut self) {
        let mut resp = simple_get(
            "https://raw.githubusercontent.com/rust-lang-nursery/rust-cookbook/master/Cargo.toml",
        )
        .expect("Could not fetch cookbook manifest");
        assert!(resp.status().is_success(), "Could not download cookbook; HTTP status was {}", resp.status());

        let mut content = String::new();
        resp.read_to_string(&mut content)
            .expect("could not read cookbook manifest");

        let manifest = content
            .parse::<toml::Value>()
            .expect("could not parse cookbook manifest");

        let dependencies = manifest["dependencies"]
            .as_table()
            .expect("no dependencies found for cookbook manifest");
        self.crates.extend({
            dependencies.iter().map(|(name, _)| Crate {
                name: name.to_string(),
            })
        })
    }

    /// Add crates that have been hand-picked
    fn add_curated_crates(&mut self) {
        self.crates.extend({
            MODIFICATIONS
                .additions
                .iter()
                .cloned()
                .map(|name| Crate { name })
        });
    }
}

/// Finds the features specified by the custom metadata of `pkg`.
///
/// Our custom metadata format looks like:
///
///     [package.metadata.playground]
///     default-features = true
///     features = ["std", "extra-traits"]
///     all-features = false
///
/// All fields are optional.
fn playground_metadata_features(pkg: &Package) -> Option<(Vec<String>, bool)> {
    let custom_metadata = pkg.manifest().custom_metadata()?;
    let playground_metadata = custom_metadata.get("playground")?;

    #[derive(Deserialize)]
    #[serde(default, rename_all = "kebab-case")]
    struct Metadata {
        features: Vec<String>,
        default_features: bool,
        all_features: bool,
    }

    impl Default for Metadata {
        fn default() -> Self {
            Metadata {
                features: Vec::new(),
                default_features: true,
                all_features: false,
            }
        }
    }

    let metadata = match playground_metadata.clone().try_into::<Metadata>() {
        Ok(metadata) => metadata,
        Err(err) => {
            eprintln!(
                "Failed to parse custom metadata for {} {}: {}",
                pkg.name(),
                pkg.version(),
                err
            );
            return None;
        }
    };

    // If `all-features` is set then we ignore `features`.
    let summary = pkg.summary();
    let mut enabled_features: BTreeSet<String> = if metadata.all_features {
        summary.features().keys().map(ToString::to_string).collect()
    } else {
        metadata.features.into_iter().collect()
    };

    // If not opting out of default features, remove default features from the
    // explicit features list. This avoids ongoing spurious diffs in our
    // generated Cargo.toml as default features are added to a library.
    if metadata.default_features {
        if let Some(default_feature_names) = summary.features().get("default") {
            enabled_features.remove("default");
            for feature in default_feature_names {
                enabled_features.remove(&feature.to_string(summary));
            }
        }
    }

    if !enabled_features.is_empty() || !metadata.default_features {
        Some((
            enabled_features.into_iter().collect(),
            metadata.default_features,
        ))
    } else {
        None
    }
}

fn write_manifest(manifest: TomlManifest, path: &str) {
    let mut f = File::create(path).expect("Unable to create Cargo.toml");
    let content = toml::to_vec(&manifest).expect("Couldn't serialize TOML");
    f.write_all(&content).expect("Couldn't write Cargo.toml");
}

fn main() {
    // Setup to interact with cargo.
    let config = Config::default().expect("Unable to create default Cargo config");
    let _lock = config.acquire_package_cache_lock();
    let crates_io = SourceId::crates_io(&config).expect("Unable to create crates.io source ID");
    let mut source = RegistrySource::remote(crates_io, &HashSet::new(), &config);
    source.update().expect("Unable to update registry");

    let mut top = TopCrates::download();
    top.add_rust_cookbook_crates();
    top.add_curated_crates();

    // Find the newest (non-prerelease, non-yanked) versions of all
    // the interesting crates.
    let mut summaries = Vec::new();
    for Crate { ref name } in top.crates {
        if MODIFICATIONS.blacklisted(name) {
            continue;
        }

        // Query the registry for a summary of this crate.
        // Usefully, this doesn't seem to include yanked versions
        let dep = Dependency::parse_no_deprecated(name, None, crates_io)
            .unwrap_or_else(|e| panic!("Unable to parse dependency for {}: {}", name, e));

        let matches = source.query_vec(&dep).unwrap_or_else(|e| {
            panic!("Unable to query registry for {}: {}", name, e);
        });

        // Find the newest non-prelease version
        let summary = matches
            .into_iter()
            .filter(|summary| !summary.version().is_prerelease())
            .max_by_key(|summary| summary.version().clone())
            .unwrap_or_else(|| panic!("Registry has no viable versions of {}", name));

        // Add a dependency on this crate.
        summaries.push((
            summary,
            ResolveOpts {
                dev_deps: false,
                features: Default::default(),
                uses_default_features: true,
                all_features: false,
            },
        ));
    }

    // Resolve transitive dependencies.
    let mut registry = PackageRegistry::new(&config).expect("Unable to create package registry");
    registry.lock_patches();
    let try_to_use = HashSet::new();
    let resolve = resolver::resolve(&summaries, &[], &mut registry, &try_to_use, None, true)
        .expect("Unable to resolve dependencies");

    // Get the package information for all dependencies.
    let package_ids: Vec<_> = resolve
        .iter()
        .filter(|pkg| !MODIFICATIONS.blacklisted(pkg.name().as_str()))
        .map(|pkg| {
            PackageId::new(pkg.name(), pkg.version(), crates_io).unwrap_or_else(|e| {
                panic!(
                    "Unable to build PackageId for {} {}: {}",
                    pkg.name(),
                    pkg.version(),
                    e
                )
            })
        })
        .collect();

    let mut sources = SourceMap::new();
    sources.insert(Box::new(source));

    let package_set =
        PackageSet::new(&package_ids, sources, &config).expect("Unable to create a PackageSet");

    let mut packages = package_set
        .get_many(package_set.package_ids())
        .expect("Unable to download packages");

    // Sort all packages by name then version (descending), so that
    // when we group them we know we get all the same crates together
    // and the newest version first.
    packages.sort_by(|a, b| {
        a.name()
            .cmp(&b.name())
            .then(a.version().cmp(&b.version()).reverse())
    });

    let mut dependencies = BTreeMap::new();
    let mut infos = Vec::new();

    for (name, pkgs) in &packages.into_iter().group_by(|pkg| pkg.name()) {
        let mut first = true;

        for pkg in pkgs {
            let version = pkg.version();

            let crate_name = pkg
                .targets()
                .iter()
                .flat_map(|target| match target.kind() {
                    TargetKind::Lib(_) => Some(target.crate_name()),
                    _ => None,
                })
                .next()
                .unwrap_or_else(|| panic!("{} did not have a library", name));

            // We see the newest version first. Any subsequent
            // versions will have their version appended so that they
            // are uniquely named
            let exposed_name = if first {
                crate_name.clone()
            } else {
                format!(
                    "{}_{}_{}_{}",
                    crate_name, version.major, version.minor, version.patch
                )
            };

            let (features, default_features) =
                playground_metadata_features(&pkg).unwrap_or_else(|| (Vec::new(), true));

            dependencies.insert(
                exposed_name.clone(),
                DependencySpec {
                    package: name.to_string(),
                    version: version.to_string(),
                    features,
                    default_features,
                },
            );

            infos.push(CrateInformation {
                name: name.to_string(),
                version: version.to_string(),
                id: exposed_name,
            });

            first = false;
        }
    }

    // Construct playground's Cargo.toml.
    let manifest = TomlManifest {
        package: TomlPackage {
            name: "playground".to_owned(),
            version: "0.0.1".to_owned(),
            authors: vec!["The Rust Playground".to_owned()],
        },
        profile: Profiles {
            dev: Profile {
                codegen_units: 1,
                incremental: false,
            },
            release: Profile {
                codegen_units: 1,
                incremental: false,
            },
        },
        dependencies,
    };

    // Write manifest file.
    let cargo_toml = "../compiler/base/Cargo.toml";
    write_manifest(manifest, cargo_toml);
    println!("wrote {}", cargo_toml);

    let path = "../compiler/base/crate-information.json";
    let mut f = File::create(path).unwrap_or_else(|e| panic!("Unable to create {}: {}", path, e));
    serde_json::to_writer_pretty(&mut f, &infos)
        .unwrap_or_else(|e| panic!("Unable to write {}: {}", path, e));
    println!("Wrote {}", path);
}
<commit_msg>Simplify double creation of PackageIds<commit_after>#![deny(rust_2018_idioms)]

use cargo::{
    core::{
        package::PackageSet,
        registry::PackageRegistry,
        resolver::{self, ResolveOpts},
        source::SourceMap,
        Dependency, Package, Source, SourceId, TargetKind,
    },
    sources::RegistrySource,
    util::Config,
};
use itertools::Itertools;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use std::{
    collections::{BTreeMap, BTreeSet, HashSet},
    fs::File,
    io::{Read, Write},
};

/// The list of crates from crates.io
#[derive(Debug, Deserialize)]
struct TopCrates {
    crates: Vec<Crate>,
}

/// A single crate from crates.io
#[derive(Debug, Deserialize)]
struct OneCrate {
    #[serde(rename = "crate")]
    krate: Crate,
}

/// The shared description of a crate
#[derive(Debug, Deserialize)]
struct Crate {
    #[serde(rename = "id")]
    name: String,
}

/// A Cargo.toml file.
#[derive(Serialize)]
struct TomlManifest {
    package: TomlPackage,
    profile: Profiles,
    #[serde(serialize_with = "toml::ser::tables_last")]
    dependencies: BTreeMap<String, DependencySpec>,
}

/// Header of Cargo.toml file.
#[derive(Serialize)]
struct TomlPackage {
    name: String,
    version: String,
    authors: Vec<String>,
}

/// A mapping of a crates name to its identifier used in source code
#[derive(Debug, Serialize)]
struct CrateInformation {
    name: String,
    version: String,
    id: String,
}

/// Hand-curated changes to the crate list
#[derive(Debug, Deserialize)]
struct Modifications {
    #[serde(default)]
    blacklist: Vec<String>,
    #[serde(default)]
    additions: BTreeSet<String>,
}

/// A profile section in a Cargo.toml file
#[derive(Serialize)]
#[serde(rename_all = "kebab-case")]
struct Profile {
    codegen_units: u32,
    incremental: bool,
}

/// Available profile types
#[derive(Serialize)]
struct Profiles {
    dev: Profile,
    release: Profile,
}

#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "kebab-case")]
struct DependencySpec {
    #[serde(skip_serializing_if = "String::is_empty")]
    package: String,
    #[serde(serialize_with = "exact_version")]
    version: String,
    #[serde(skip_serializing_if = "Vec::is_empty")]
    features: Vec<String>,
    #[serde(skip_serializing_if = "is_true")]
    default_features: bool,
}

fn exact_version<S>(version: &String, serializer: S) -> Result<S::Ok, S::Error>
where
    S: serde::Serializer,
{
    format!("={}", version).serialize(serializer)
}

fn is_true(b: &bool) -> bool {
    *b
}

impl Modifications {
    fn blacklisted(&self, name: &str) -> bool {
        self.blacklist.iter().any(|n| n == name)
    }
}

lazy_static! {
    static ref MODIFICATIONS: Modifications = {
        let mut f = File::open("crate-modifications.toml")
            .expect("unable to open crate modifications file");

        let mut d = Vec::new();
        f.read_to_end(&mut d)
            .expect("unable to read crate modifications file");

        toml::from_slice(&d).expect("unable to parse crate modifications file")
    };
}

fn simple_get(url: &str) -> reqwest::Result<reqwest::blocking::Response> {
    reqwest::blocking::ClientBuilder::new()
        .user_agent("Rust Playground - Top Crates Utility")
        .build()?
        .get(url)
        .send()
}

impl TopCrates {
    /// List top 100 crates by number of downloads on crates.io.
    fn download() -> TopCrates {
        let resp =
            simple_get("https://crates.io/api/v1/crates?page=1&per_page=100&sort=downloads")
                .expect("Could not fetch top crates");
        assert!(resp.status().is_success(), "Could not download top crates; HTTP status was {}", resp.status());

        serde_json::from_reader(resp).expect("Invalid JSON")
    }

    fn add_rust_cookbook_crates(&mut self) {
        let mut resp = simple_get(
            "https://raw.githubusercontent.com/rust-lang-nursery/rust-cookbook/master/Cargo.toml",
        )
        .expect("Could not fetch cookbook manifest");
        assert!(resp.status().is_success(), "Could not download cookbook; HTTP status was {}", resp.status());

        let mut content = String::new();
        resp.read_to_string(&mut content)
            .expect("could not read cookbook manifest");

        let manifest = content
            .parse::<toml::Value>()
            .expect("could not parse cookbook manifest");

        let dependencies = manifest["dependencies"]
            .as_table()
            .expect("no dependencies found for cookbook manifest");
        self.crates.extend({
            dependencies.iter().map(|(name, _)| Crate {
                name: name.to_string(),
            })
        })
    }

    /// Add crates that have been hand-picked
    fn add_curated_crates(&mut self) {
        self.crates.extend({
            MODIFICATIONS
                .additions
                .iter()
                .cloned()
                .map(|name| Crate { name })
        });
    }
}

/// Finds the features specified by the custom metadata of `pkg`.
///
/// Our custom metadata format looks like:
///
///     [package.metadata.playground]
///     default-features = true
///     features = ["std", "extra-traits"]
///     all-features = false
///
/// All fields are optional.
fn playground_metadata_features(pkg: &Package) -> Option<(Vec<String>, bool)> {
    let custom_metadata = pkg.manifest().custom_metadata()?;
    let playground_metadata = custom_metadata.get("playground")?;

    #[derive(Deserialize)]
    #[serde(default, rename_all = "kebab-case")]
    struct Metadata {
        features: Vec<String>,
        default_features: bool,
        all_features: bool,
    }

    impl Default for Metadata {
        fn default() -> Self {
            Metadata {
                features: Vec::new(),
                default_features: true,
                all_features: false,
            }
        }
    }

    let metadata = match playground_metadata.clone().try_into::<Metadata>() {
        Ok(metadata) => metadata,
        Err(err) => {
            eprintln!(
                "Failed to parse custom metadata for {} {}: {}",
                pkg.name(),
                pkg.version(),
                err
            );
            return None;
        }
    };

    // If `all-features` is set then we ignore `features`.
    let summary = pkg.summary();
    let mut enabled_features: BTreeSet<String> = if metadata.all_features {
        summary.features().keys().map(ToString::to_string).collect()
    } else {
        metadata.features.into_iter().collect()
    };

    // If not opting out of default features, remove default features from the
    // explicit features list. This avoids ongoing spurious diffs in our
    // generated Cargo.toml as default features are added to a library.
    if metadata.default_features {
        if let Some(default_feature_names) = summary.features().get("default") {
            enabled_features.remove("default");
            for feature in default_feature_names {
                enabled_features.remove(&feature.to_string(summary));
            }
        }
    }

    if !enabled_features.is_empty() || !metadata.default_features {
        Some((
            enabled_features.into_iter().collect(),
            metadata.default_features,
        ))
    } else {
        None
    }
}

fn write_manifest(manifest: TomlManifest, path: &str) {
    let mut f = File::create(path).expect("Unable to create Cargo.toml");
    let content = toml::to_vec(&manifest).expect("Couldn't serialize TOML");
    f.write_all(&content).expect("Couldn't write Cargo.toml");
}

fn main() {
    // Setup to interact with cargo.
    let config = Config::default().expect("Unable to create default Cargo config");
    let _lock = config.acquire_package_cache_lock();
    let crates_io = SourceId::crates_io(&config).expect("Unable to create crates.io source ID");
    let mut source = RegistrySource::remote(crates_io, &HashSet::new(), &config);
    source.update().expect("Unable to update registry");

    let mut top = TopCrates::download();
    top.add_rust_cookbook_crates();
    top.add_curated_crates();

    // Find the newest (non-prerelease, non-yanked) versions of all
    // the interesting crates.
    let mut summaries = Vec::new();
    for Crate { ref name } in top.crates {
        if MODIFICATIONS.blacklisted(name) {
            continue;
        }

        // Query the registry for a summary of this crate.
        // Usefully, this doesn't seem to include yanked versions
        let dep = Dependency::parse_no_deprecated(name, None, crates_io)
            .unwrap_or_else(|e| panic!("Unable to parse dependency for {}: {}", name, e));

        let matches = source.query_vec(&dep).unwrap_or_else(|e| {
            panic!("Unable to query registry for {}: {}", name, e);
        });

        // Find the newest non-prelease version
        let summary = matches
            .into_iter()
            .filter(|summary| !summary.version().is_prerelease())
            .max_by_key(|summary| summary.version().clone())
            .unwrap_or_else(|| panic!("Registry has no viable versions of {}", name));

        // Add a dependency on this crate.
        summaries.push((
            summary,
            ResolveOpts {
                dev_deps: false,
                features: Default::default(),
                uses_default_features: true,
                all_features: false,
            },
        ));
    }

    // Resolve transitive dependencies.
    let mut registry = PackageRegistry::new(&config).expect("Unable to create package registry");
    registry.lock_patches();
    let try_to_use = HashSet::new();
    let resolve = resolver::resolve(&summaries, &[], &mut registry, &try_to_use, None, true)
        .expect("Unable to resolve dependencies");

    // Remove blacklisted packages that have been added due to resolution
    let package_ids: Vec<_> = resolve
        .iter()
        .filter(|pkg| !MODIFICATIONS.blacklisted(pkg.name().as_str()))
        .collect();

    let mut sources = SourceMap::new();
    sources.insert(Box::new(source));

    let package_set =
        PackageSet::new(&package_ids, sources, &config).expect("Unable to create a PackageSet");

    let mut packages = package_set
        .get_many(package_set.package_ids())
        .expect("Unable to download packages");

    // Sort all packages by name then version (descending), so that
    // when we group them we know we get all the same crates together
    // and the newest version first.
    packages.sort_by(|a, b| {
        a.name()
            .cmp(&b.name())
            .then(a.version().cmp(&b.version()).reverse())
    });

    let mut dependencies = BTreeMap::new();
    let mut infos = Vec::new();

    for (name, pkgs) in &packages.into_iter().group_by(|pkg| pkg.name()) {
        let mut first = true;

        for pkg in pkgs {
            let version = pkg.version();

            let crate_name = pkg
                .targets()
                .iter()
                .flat_map(|target| match target.kind() {
                    TargetKind::Lib(_) => Some(target.crate_name()),
                    _ => None,
                })
                .next()
                .unwrap_or_else(|| panic!("{} did not have a library", name));

            // We see the newest version first. Any subsequent
            // versions will have their version appended so that they
            // are uniquely named
            let exposed_name = if first {
                crate_name.clone()
            } else {
                format!(
                    "{}_{}_{}_{}",
                    crate_name, version.major, version.minor, version.patch
                )
            };

            let (features, default_features) =
                playground_metadata_features(&pkg).unwrap_or_else(|| (Vec::new(), true));

            dependencies.insert(
                exposed_name.clone(),
                DependencySpec {
                    package: name.to_string(),
                    version: version.to_string(),
                    features,
                    default_features,
                },
            );

            infos.push(CrateInformation {
                name: name.to_string(),
                version: version.to_string(),
                id: exposed_name,
            });

            first = false;
        }
    }

    // Construct playground's Cargo.toml.
    let manifest = TomlManifest {
        package: TomlPackage {
            name: "playground".to_owned(),
            version: "0.0.1".to_owned(),
            authors: vec!["The Rust Playground".to_owned()],
        },
        profile: Profiles {
            dev: Profile {
                codegen_units: 1,
                incremental: false,
            },
            release: Profile {
                codegen_units: 1,
                incremental: false,
            },
        },
        dependencies,
    };

    // Write manifest file.
    let cargo_toml = "../compiler/base/Cargo.toml";
    write_manifest(manifest, cargo_toml);
    println!("wrote {}", cargo_toml);

    let path = "../compiler/base/crate-information.json";
    let mut f = File::create(path).unwrap_or_else(|e| panic!("Unable to create {}: {}", path, e));
    serde_json::to_writer_pretty(&mut f, &infos)
        .unwrap_or_else(|e| panic!("Unable to write {}: {}", path, e));
    println!("Wrote {}", path);
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::ast::*;
use syntax::tokenstream::{ThinTokenStream, TokenStream};
use syntax::parse::{token, parser};
use crate::utils::{span_lint, span_lint_and_sugg};

/// **What it does:** This lint warns when you use `println!("")` to
/// print a newline.
///
/// **Why is this bad?** You should use `println!()`, which is simpler.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// println!("");
/// ```
declare_clippy_lint! {
    pub PRINTLN_EMPTY_STRING,
    style,
    "using `println!(\"\")` with an empty string"
}

/// **What it does:** This lint warns when you use `print!()` with a format
/// string that
/// ends in a newline.
///
/// **Why is this bad?** You should use `println!()` instead, which appends the
/// newline.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// print!("Hello {}!\n", name);
/// ```
declare_clippy_lint! {
    pub PRINT_WITH_NEWLINE,
    style,
    "using `print!()` with a format string that ends in a newline"
}

/// **What it does:** Checks for printing on *stdout*. The purpose of this lint
/// is to catch debugging remnants.
///
/// **Why is this bad?** People often print on *stdout* while debugging an
/// application and might forget to remove those prints afterward.
///
/// **Known problems:** Only catches `print!` and `println!` calls.
///
/// **Example:**
/// ```rust
/// println!("Hello world!");
/// ```
declare_clippy_lint! {
    pub PRINT_STDOUT,
    restriction,
    "printing on stdout"
}

/// **What it does:** Checks for use of `Debug` formatting. The purpose of this
/// lint is to catch debugging remnants.
///
/// **Why is this bad?** The purpose of the `Debug` trait is to facilitate
/// debugging Rust code. It should not be used in in user-facing output.
///
/// **Example:**
/// ```rust
/// println!("{:?}", foo);
/// ```
declare_clippy_lint! {
    pub USE_DEBUG,
    restriction,
    "use of `Debug`-based formatting"
}

/// **What it does:** This lint warns about the use of literals as `print!`/`println!` args.
///
/// **Why is this bad?** Using literals as `println!` args is inefficient
/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
/// (i.e., just put the literal in the format string)
///
/// **Known problems:** Will also warn with macro calls as arguments that expand to literals
/// -- e.g., `println!("{}", env!("FOO"))`.
///
/// **Example:**
/// ```rust
/// println!("{}", "foo");
/// ```
declare_clippy_lint! {
    pub PRINT_LITERAL,
    style,
    "printing a literal with a format string"
}

/// **What it does:** This lint warns when you use `writeln!(buf, "")` to
/// print a newline.
///
/// **Why is this bad?** You should use `writeln!(buf)`, which is simpler.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// writeln!("");
/// ```
declare_clippy_lint! {
    pub WRITELN_EMPTY_STRING,
    style,
    "using `writeln!(\"\")` with an empty string"
}

/// **What it does:** This lint warns when you use `write!()` with a format
/// string that
/// ends in a newline.
///
/// **Why is this bad?** You should use `writeln!()` instead, which appends the
/// newline.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// write!(buf, "Hello {}!\n", name);
/// ```
declare_clippy_lint! {
    pub WRITE_WITH_NEWLINE,
    style,
    "using `write!()` with a format string that ends in a newline"
}

/// **What it does:** This lint warns about the use of literals as `write!`/`writeln!` args.
///
/// **Why is this bad?** Using literals as `writeln!` args is inefficient
/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
/// (i.e., just put the literal in the format string)
///
/// **Known problems:** Will also warn with macro calls as arguments that expand to literals
/// -- e.g., `writeln!(buf, "{}", env!("FOO"))`.
///
/// **Example:**
/// ```rust
/// writeln!(buf, "{}", "foo");
/// ```
declare_clippy_lint! {
    pub WRITE_LITERAL,
    style,
    "writing a literal with a format string"
}

#[derive(Copy, Clone, Debug)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(
            PRINT_WITH_NEWLINE,
            PRINTLN_EMPTY_STRING,
            PRINT_STDOUT,
            USE_DEBUG,
            PRINT_LITERAL,
            WRITE_WITH_NEWLINE,
            WRITELN_EMPTY_STRING,
            WRITE_LITERAL
        )
    }
}

impl EarlyLintPass for Pass {
    fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &Mac) {
        if mac.node.path == "println" {
            span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`");
            if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false) {
                if fmtstr == "" {
                    span_lint_and_sugg(
                        cx,
                        PRINTLN_EMPTY_STRING,
                        mac.span,
                        "using `println!(\"\")`",
                        "replace it with",
                        "println!()".to_string(),
                    );
                }
            }
        } else if mac.node.path == "print" {
            span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`");
            if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false) {
                if fmtstr.ends_with("\\n") {
                    span_lint(cx, PRINT_WITH_NEWLINE, mac.span,
                            "using `print!()` with a format string that ends in a \
                            newline, consider using `println!()` instead");
                }
            }
        } else if mac.node.path == "write" {
            if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true) {
                if fmtstr.ends_with("\\n") {
                    span_lint(cx, WRITE_WITH_NEWLINE, mac.span,
                            "using `write!()` with a format string that ends in a \
                            newline, consider using `writeln!()` instead");
                }
            }
        } else if mac.node.path == "writeln" {
            if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true) {
                if fmtstr == "" {
                    span_lint_and_sugg(
                        cx,
                        WRITELN_EMPTY_STRING,
                        mac.span,
                        "using `writeln!(v, \"\")`",
                        "replace it with",
                        "writeln!(v)".to_string(),
                    );
                }
            }
        }
    }
}

fn check_tts(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> Option<String> {
    let tts = TokenStream::from(tts.clone());
    let mut parser = parser::Parser::new(
        &cx.sess.parse_sess,
        tts,
        None,
        false,
        false,
    );
    if is_write {
        // skip the initial write target
        parser.parse_expr().map_err(|mut err| err.cancel()).ok()?;
        // might be `writeln!(foo)`
        parser.expect(&token::Comma).map_err(|mut err| err.cancel()).ok()?;
    }
    let fmtstr = parser.parse_str().map_err(|mut err| err.cancel()).ok()?.0.to_string();
    use fmt_macros::*;
    let tmp = fmtstr.clone();
    let mut args = vec![];
    let mut fmt_parser = Parser::new(&tmp, None);
    while let Some(piece) = fmt_parser.next() {
        if !fmt_parser.errors.is_empty() {
            return None;
        }
        if let Piece::NextArgument(arg) = piece {
            if arg.format.ty == "?" {
                // FIXME: modify rustc's fmt string parser to give us the current span
                span_lint(cx, USE_DEBUG, parser.prev_span, "use of `Debug`-based formatting");
            }
            args.push(arg);
        }
    }
    let lint = if is_write {
        WRITE_LITERAL
    } else {
        PRINT_LITERAL
    };
    let mut idx = 0;
    loop {
        if !parser.eat(&token::Comma) {
            assert!(parser.eat(&token::Eof));
            return Some(fmtstr);
        }
        let expr = parser.parse_expr().map_err(|mut err| err.cancel()).ok()?;
        const SIMPLE: FormatSpec<'_> = FormatSpec {
            fill: None,
            align: AlignUnknown,
            flags: 0,
            precision: CountImplied,
            width: CountImplied,
            ty: "",
        };
        match &expr.node {
            ExprKind::Lit(_) => {
                let mut all_simple = true;
                let mut seen = false;
                for arg in &args {
                    match arg.position {
                        | ArgumentImplicitlyIs(n)
                        | ArgumentIs(n)
                        => if n == idx {
                            all_simple &= arg.format == SIMPLE;
                            seen = true;
                        },
                        ArgumentNamed(_) => {},
                    }
                }
                if all_simple && seen {
                    span_lint(cx, lint, expr.span, "literal with an empty format string");
                }
                idx += 1;
            },
            ExprKind::Assign(lhs, rhs) => {
                if let ExprKind::Lit(_) = rhs.node {
                    if let ExprKind::Path(_, p) = &lhs.node {
                        let mut all_simple = true;
                        let mut seen = false;
                        for arg in &args {
                            match arg.position {
                                | ArgumentImplicitlyIs(_)
                                | ArgumentIs(_)
                                => {},
                                ArgumentNamed(name) => if *p == name {
                                    seen = true;
                                    all_simple &= arg.format == SIMPLE;
                                },
                            }
                        }
                        if all_simple && seen {
                            span_lint(cx, lint, rhs.span, "literal with an empty format string");
                        }
                    }
                }
            },
            _ => idx += 1,
        }
    }
}
<commit_msg>Fix the build after https://github.com/rust-lang/rust/pull/53016<commit_after>use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::ast::*;
use syntax::tokenstream::{ThinTokenStream, TokenStream};
use syntax::parse::{token, parser};
use crate::utils::{span_lint, span_lint_and_sugg};

/// **What it does:** This lint warns when you use `println!("")` to
/// print a newline.
///
/// **Why is this bad?** You should use `println!()`, which is simpler.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// println!("");
/// ```
declare_clippy_lint! {
    pub PRINTLN_EMPTY_STRING,
    style,
    "using `println!(\"\")` with an empty string"
}

/// **What it does:** This lint warns when you use `print!()` with a format
/// string that
/// ends in a newline.
///
/// **Why is this bad?** You should use `println!()` instead, which appends the
/// newline.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// print!("Hello {}!\n", name);
/// ```
declare_clippy_lint! {
    pub PRINT_WITH_NEWLINE,
    style,
    "using `print!()` with a format string that ends in a newline"
}

/// **What it does:** Checks for printing on *stdout*. The purpose of this lint
/// is to catch debugging remnants.
///
/// **Why is this bad?** People often print on *stdout* while debugging an
/// application and might forget to remove those prints afterward.
///
/// **Known problems:** Only catches `print!` and `println!` calls.
///
/// **Example:**
/// ```rust
/// println!("Hello world!");
/// ```
declare_clippy_lint! {
    pub PRINT_STDOUT,
    restriction,
    "printing on stdout"
}

/// **What it does:** Checks for use of `Debug` formatting. The purpose of this
/// lint is to catch debugging remnants.
///
/// **Why is this bad?** The purpose of the `Debug` trait is to facilitate
/// debugging Rust code. It should not be used in in user-facing output.
///
/// **Example:**
/// ```rust
/// println!("{:?}", foo);
/// ```
declare_clippy_lint! {
    pub USE_DEBUG,
    restriction,
    "use of `Debug`-based formatting"
}

/// **What it does:** This lint warns about the use of literals as `print!`/`println!` args.
///
/// **Why is this bad?** Using literals as `println!` args is inefficient
/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
/// (i.e., just put the literal in the format string)
///
/// **Known problems:** Will also warn with macro calls as arguments that expand to literals
/// -- e.g., `println!("{}", env!("FOO"))`.
///
/// **Example:**
/// ```rust
/// println!("{}", "foo");
/// ```
declare_clippy_lint! {
    pub PRINT_LITERAL,
    style,
    "printing a literal with a format string"
}

/// **What it does:** This lint warns when you use `writeln!(buf, "")` to
/// print a newline.
///
/// **Why is this bad?** You should use `writeln!(buf)`, which is simpler.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// writeln!("");
/// ```
declare_clippy_lint! {
    pub WRITELN_EMPTY_STRING,
    style,
    "using `writeln!(\"\")` with an empty string"
}

/// **What it does:** This lint warns when you use `write!()` with a format
/// string that
/// ends in a newline.
///
/// **Why is this bad?** You should use `writeln!()` instead, which appends the
/// newline.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// write!(buf, "Hello {}!\n", name);
/// ```
declare_clippy_lint! {
    pub WRITE_WITH_NEWLINE,
    style,
    "using `write!()` with a format string that ends in a newline"
}

/// **What it does:** This lint warns about the use of literals as `write!`/`writeln!` args.
///
/// **Why is this bad?** Using literals as `writeln!` args is inefficient
/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
/// (i.e., just put the literal in the format string)
///
/// **Known problems:** Will also warn with macro calls as arguments that expand to literals
/// -- e.g., `writeln!(buf, "{}", env!("FOO"))`.
///
/// **Example:**
/// ```rust
/// writeln!(buf, "{}", "foo");
/// ```
declare_clippy_lint! {
    pub WRITE_LITERAL,
    style,
    "writing a literal with a format string"
}

#[derive(Copy, Clone, Debug)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(
            PRINT_WITH_NEWLINE,
            PRINTLN_EMPTY_STRING,
            PRINT_STDOUT,
            USE_DEBUG,
            PRINT_LITERAL,
            WRITE_WITH_NEWLINE,
            WRITELN_EMPTY_STRING,
            WRITE_LITERAL
        )
    }
}

impl EarlyLintPass for Pass {
    fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &Mac) {
        if mac.node.path == "println" {
            span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`");
            if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false) {
                if fmtstr == "" {
                    span_lint_and_sugg(
                        cx,
                        PRINTLN_EMPTY_STRING,
                        mac.span,
                        "using `println!(\"\")`",
                        "replace it with",
                        "println!()".to_string(),
                    );
                }
            }
        } else if mac.node.path == "print" {
            span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`");
            if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false) {
                if fmtstr.ends_with("\\n") {
                    span_lint(cx, PRINT_WITH_NEWLINE, mac.span,
                            "using `print!()` with a format string that ends in a \
                            newline, consider using `println!()` instead");
                }
            }
        } else if mac.node.path == "write" {
            if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true) {
                if fmtstr.ends_with("\\n") {
                    span_lint(cx, WRITE_WITH_NEWLINE, mac.span,
                            "using `write!()` with a format string that ends in a \
                            newline, consider using `writeln!()` instead");
                }
            }
        } else if mac.node.path == "writeln" {
            if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true) {
                if fmtstr == "" {
                    span_lint_and_sugg(
                        cx,
                        WRITELN_EMPTY_STRING,
                        mac.span,
                        "using `writeln!(v, \"\")`",
                        "replace it with",
                        "writeln!(v)".to_string(),
                    );
                }
            }
        }
    }
}

fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> Option<String> {
    let tts = TokenStream::from(tts.clone());
    let mut parser = parser::Parser::new(
        &cx.sess.parse_sess,
        tts,
        None,
        false,
        false,
    );
    if is_write {
        // skip the initial write target
        parser.parse_expr().map_err(|mut err| err.cancel()).ok()?;
        // might be `writeln!(foo)`
        parser.expect(&token::Comma).map_err(|mut err| err.cancel()).ok()?;
    }
    let fmtstr = parser.parse_str().map_err(|mut err| err.cancel()).ok()?.0.to_string();
    use fmt_macros::*;
    let tmp = fmtstr.clone();
    let mut args = vec![];
    let mut fmt_parser = Parser::new(&tmp, None);
    while let Some(piece) = fmt_parser.next() {
        if !fmt_parser.errors.is_empty() {
            return None;
        }
        if let Piece::NextArgument(arg) = piece {
            if arg.format.ty == "?" {
                // FIXME: modify rustc's fmt string parser to give us the current span
                span_lint(cx, USE_DEBUG, parser.prev_span, "use of `Debug`-based formatting");
            }
            args.push(arg);
        }
    }
    let lint = if is_write {
        WRITE_LITERAL
    } else {
        PRINT_LITERAL
    };
    let mut idx = 0;
    loop {
        if !parser.eat(&token::Comma) {
            assert!(parser.eat(&token::Eof));
            return Some(fmtstr);
        }
        let expr = parser.parse_expr().map_err(|mut err| err.cancel()).ok()?;
        const SIMPLE: FormatSpec<'_> = FormatSpec {
            fill: None,
            align: AlignUnknown,
            flags: 0,
            precision: CountImplied,
            width: CountImplied,
            ty: "",
        };
        match &expr.node {
            ExprKind::Lit(_) => {
                let mut all_simple = true;
                let mut seen = false;
                for arg in &args {
                    match arg.position {
                        | ArgumentImplicitlyIs(n)
                        | ArgumentIs(n)
                        => if n == idx {
                            all_simple &= arg.format == SIMPLE;
                            seen = true;
                        },
                        ArgumentNamed(_) => {},
                    }
                }
                if all_simple && seen {
                    span_lint(cx, lint, expr.span, "literal with an empty format string");
                }
                idx += 1;
            },
            ExprKind::Assign(lhs, rhs) => {
                if let ExprKind::Lit(_) = rhs.node {
                    if let ExprKind::Path(_, p) = &lhs.node {
                        let mut all_simple = true;
                        let mut seen = false;
                        for arg in &args {
                            match arg.position {
                                | ArgumentImplicitlyIs(_)
                                | ArgumentIs(_)
                                => {},
                                ArgumentNamed(name) => if *p == name {
                                    seen = true;
                                    all_simple &= arg.format == SIMPLE;
                                },
                            }
                        }
                        if all_simple && seen {
                            span_lint(cx, lint, rhs.span, "literal with an empty format string");
                        }
                    }
                }
            },
            _ => idx += 1,
        }
    }
}
<|endoftext|>


<commit_before>//! The base traits that are used for serializing and deserializing rust types.
//!
//! `BerSerialize` implements serialization, and `BerDeserialize` implements deserialization.
//! Both traits depend upon the `Asn1Info` trait being implemented, to provide
//! metadata about the type (like ASN.1 tag and ASN.1 type).
//!
//! For both traits, only the `(de)serialize_value` functions should need overridden
//! to get custom behaviour. If you need to change how tags are handled, you may need
//! to override `_serialize_enc` or `_deserialize_with_tag`.
use std::io;

use ::Asn1Info;
use tag;
use err;
use ber::enc;

/// Provides the methods required to serialize this Rust type into an ASN.1 stream.
///
/// When implementing this for a simple primitive type, implementing `serialize_value`
/// should be all that's required. For more complex, structured types you may need to
/// implement `_serialize_enc` (this is called first by `serialize_enc`).
pub trait BerSerialize: Asn1Info {
  /// Serialize a value into ASN.1 data as DER.
  fn serialize<W: io::Write>(&self, writer: &mut W) -> Result<(), err::EncodeError> {
    self.serialize_enc(enc::DER, writer)
  }

  /// Serialize a value into ASN.1 data using a specific set of encoding rules.
  fn serialize_enc<E: enc::BerEncRules, W: io::Write>
      (&self, e: E, writer: &mut W) -> Result<(), err::EncodeError> {
    debug!("Encoding the type {}", Self::asn1_type());
    if let Some(r) = self._serialize_enc(e, writer) {
      return r;
    }

    let tag = match Self::asn1_tag() {
      Some(tag) => tag,
      None => {
        debug!("Skipping encoding of empty tag");
        return self.serialize_value(e, writer);
      },
    };

    try!(tag.write_tag(writer));

    // If this is indefinite length and constructed, write the data directly.
    if E::len_rules() == enc::LenEnc::Indefinite &&
       tag.constructed {
      debug!("Using indefinite length");
      try!(tag::Len::Indef.write_len(writer));
      try!(self.serialize_value(e, writer));
      try!(tag::Len::write_indef_end(writer));
    // Otherwise write to a Vec first, so we can write the length.
    } else {
      debug!("Using definite length encoding");
      let mut bytes: Vec<u8> = Vec::new();
      try!(self.serialize_value(e, &mut bytes));
      try!(tag::Len::write_len(Some(bytes.len() as tag::LenNum).into(), writer));
      try!(writer.write_all(&bytes));
    }

    Ok(())
  }

  /// An empty method that is called first by `serialize_enc` to allow custom
  /// handling, without losing normal serialization behaviour.
  ///
  /// Return `Some(())` to indicate stop normal behaviour, or `None` to continue.
  fn _serialize_enc<E: enc::BerEncRules, W: io::Write>
      (&self, e: E, writer: &mut W) -> Option<Result<(), err::EncodeError>> {
    let _ = (e, writer);
    None
  }

  /// Serialise a value into ASN.1 data, without a tag (implicit tagging).
  fn serialize_value<E: enc::BerEncRules, W: io::Write>
    (&self, e: E, writer: &mut W) -> Result<(), err::EncodeError>;
}

/// Provides the methods required to deserialize this Rust type from an ASN.1 stream.
///
/// When implementing this for a simple primitive type, implementing `deserialize_value`
/// should be all that's required. For more complex, structued types you may need to
/// implement `_deserialize_with_tag` (this is called first by `deserialize_with_tag).
pub trait BerDeserialize: Asn1Info + Sized {
  /// Deserialize ASN.1 data into a Rust value, accepting any valid BER.
  fn deserialize<I: Iterator<Item=io::Result<u8>>>(reader: &mut I) -> Result<Self, err::DecodeError> {
    Self::deserialize_enc(enc::BER, reader)
  }

  /// Deserialize ASN.1 data into a Rust value, using a specific set of encoding rules.
  fn deserialize_enc<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
      (e: E, reader: &mut I) -> Result<Self, err::DecodeError> {
    let (tag, len) = try!(tag::read_taglen(reader));
    Self::deserialize_with_tag(e, reader, tag, len)
  }

  /// Deserialize ASN.1 data into a Rust value, using a specific set of encoding rules, and
  /// also providing the decoded tag and length.
  ///
  /// This function assumes the next bytes to decode are
  /// the BER length of this element.
  fn deserialize_with_tag<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
      (e: E, reader: &mut I, tag: tag::Tag, len: tag::Len) -> Result<Self, err::DecodeError> {
    debug!("Decoding the type {}", Self::asn1_type());
    if let Some(r) = Self::_deserialize_with_tag(e, reader, tag, len) {
      return r;
    }

    // FIXME: This is not how implicit tagging works, the tag we
    // receive may *not* match our tag. If this is implicit tagging,
    // we probably don't to error.
    if Some(tag) != Self::asn1_tag() {
      if let Some(our_tag) = Self::asn1_tag() {
        warn!("Expected tag {}, but found tag {}", our_tag, tag);
      } else {
        warn!("Expected no tag, but found tag {}", tag);
      }
      return Err(err::DecodeError::TagTypeMismatch);
    }

    // Handle any indefinite length error conditions.
    if len == tag::Len::Indef {
      // Return an error if the encoding rules only allow definite length
      // encoding.
      if E::len_rules() == enc::LenEnc::Definite {
        warn!("Encountered indefinite length encoding, but encoding rules don't allow this");
        return Err(err::DecodeError::IndefiniteLen);
      // If this element is primitve, the length isn't allowed to be indefinite length.
      } else if !tag.constructed {
        warn!("Encountered indefinite length encoding, but this is a primitive element");
        return Err(err::DecodeError::PrimIndef)
      }
    }
    // Read the main data.
    let item: Self = try!(Self::deserialize_value(e, reader, len));

    // If this is encoded with an indefinte length, try to read the end octets.
    if len == tag::Len::Indef {
      try!(tag::Len::read_indef_end(reader));
    }

    Ok(item)
  }

  /// An empty method that is called first by `deserialize_with_tag` to allow
  /// custom handling, without losing normal deserialization behaviour.
  ///
  /// Return `Some(..)` to return that value, or `None` to use normal behaviour.
  fn _deserialize_with_tag<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
      (e: E, reader: &mut I, tag: tag::Tag, len: tag::Len) -> Option<Result<Self, err::DecodeError>> {
    let _ = (e, reader, tag, len);
    None
  }

  /// Deserialize an ASN.1 value from a BER stream, after having the tag and length
  /// decoded.
  ///
  /// The data length must be explicitly passed to this function. For primitive types,
  /// an error will be returned if this length is Indefinite.
  fn deserialize_value<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
    (e: E, reader: &mut I, len: tag::Len) -> Result<Self, err::DecodeError> {
    let (_, _, _) = (e, reader, len);
    panic!("deserialize_value must be implemented for types that require it");
  }
}
<commit_msg>Fixup comments in asn1-cereal<commit_after>//! The base traits that are used for serializing and deserializing rust types.
//!
//! `BerSerialize` implements serialization, and `BerDeserialize` implements deserialization.
//! Both traits depend upon the `Asn1Info` trait being implemented, to provide
//! metadata about the type (like ASN.1 tag and ASN.1 type).
//!
//! For both traits, only the `(de)serialize_value` functions should need overridden
//! to get custom behaviour. If you need to change how tags are handled, you may need
//! to override `_serialize_enc` or `_deserialize_with_tag`.
use std::io;

use ::Asn1Info;
use tag;
use err;
use ber::enc;

/// Provides the methods required to serialize this Rust type into an ASN.1 stream.
///
/// When implementing this for a simple primitive type, implementing `serialize_value`
/// should be all that's required. For more complex, structured types you may need to
/// implement `_serialize_enc` (this is called first by `serialize_enc`).
pub trait BerSerialize: Asn1Info {
  /// Serialize a value into ASN.1 data as DER.
  fn serialize<W: io::Write>(&self, writer: &mut W) -> Result<(), err::EncodeError> {
    self.serialize_enc(enc::DER, writer)
  }

  /// Serialize a value into ASN.1 data using a specific set of encoding rules.
  fn serialize_enc<E: enc::BerEncRules, W: io::Write>
      (&self, e: E, writer: &mut W) -> Result<(), err::EncodeError> {
    debug!("Encoding the type {}", Self::asn1_type());
    if let Some(r) = self._serialize_enc(e, writer) {
      return r;
    }

    let tag = match Self::asn1_tag() {
      Some(tag) => tag,
      None => {
        debug!("Skipping encoding of empty tag");
        return self.serialize_value(e, writer);
      },
    };

    try!(tag.write_tag(writer));

    // If this is indefinite length and constructed, write the data directly.
    if E::len_rules() == enc::LenEnc::Indefinite &&
       tag.constructed {
      debug!("Using indefinite length");
      try!(tag::Len::Indef.write_len(writer));
      try!(self.serialize_value(e, writer));
      try!(tag::Len::write_indef_end(writer));
    // Otherwise write to a Vec first, so we can write the length.
    } else {
      debug!("Using definite length encoding");
      let mut bytes: Vec<u8> = Vec::new();
      try!(self.serialize_value(e, &mut bytes));
      try!(tag::Len::write_len(Some(bytes.len() as tag::LenNum).into(), writer));
      try!(writer.write_all(&bytes));
    }

    Ok(())
  }

  /// An empty method that is called first by `serialize_enc` to allow custom
  /// handling, without losing normal serialization behaviour.
  ///
  /// Return `Some(())` to indicate stop normal behaviour, or `None` to continue.
  fn _serialize_enc<E: enc::BerEncRules, W: io::Write>
      (&self, e: E, writer: &mut W) -> Option<Result<(), err::EncodeError>> {
    let _ = (e, writer);
    None
  }

  /// Serialise a value into ASN.1 data, without a tag. Will be called directly
  /// when encoding an implicit tag.
  fn serialize_value<E: enc::BerEncRules, W: io::Write>
    (&self, e: E, writer: &mut W) -> Result<(), err::EncodeError>;
}

/// Provides the methods required to deserialize this Rust type from an ASN.1 stream.
///
/// When implementing this for a simple primitive type, implementing `deserialize_value`
/// should be all that's required. For more complex, structued types you may need to
/// implement `_deserialize_with_tag` (this is called first by `deserialize_with_tag).
pub trait BerDeserialize: Asn1Info + Sized {
  /// Deserialize ASN.1 data into a Rust value, accepting any valid BER.
  fn deserialize<I: Iterator<Item=io::Result<u8>>>(reader: &mut I) -> Result<Self, err::DecodeError> {
    Self::deserialize_enc(enc::BER, reader)
  }

  /// Deserialize ASN.1 data into a Rust value, using a specific set of encoding rules.
  fn deserialize_enc<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
      (e: E, reader: &mut I) -> Result<Self, err::DecodeError> {
    let (tag, len) = try!(tag::read_taglen(reader));
    Self::deserialize_with_tag(e, reader, tag, len)
  }

  /// Deserialize ASN.1 data into a Rust value, using a specific set of encoding rules, and
  /// also providing the decoded tag and length.
  ///
  /// This function assumes the next bytes to decode are
  /// the BER length of this element.
  fn deserialize_with_tag<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
      (e: E, reader: &mut I, tag: tag::Tag, len: tag::Len) -> Result<Self, err::DecodeError> {
    debug!("Decoding the type {}", Self::asn1_type());
    if let Some(r) = Self::_deserialize_with_tag(e, reader, tag, len) {
      return r;
    }

    if Some(tag) != Self::asn1_tag() {
      if let Some(our_tag) = Self::asn1_tag() {
        warn!("Expected tag {}, but found tag {}", our_tag, tag);
      } else {
        warn!("Expected no tag, but found tag {}", tag);
      }
      return Err(err::DecodeError::TagTypeMismatch);
    }

    // Handle any indefinite length error conditions.
    if len == tag::Len::Indef {
      // Return an error if the encoding rules only allow definite length
      // encoding.
      if E::len_rules() == enc::LenEnc::Definite {
        warn!("Encountered indefinite length encoding, but encoding rules don't allow this");
        return Err(err::DecodeError::IndefiniteLen);
      // If this element is primitve, the length isn't allowed to be indefinite length.
      } else if !tag.constructed {
        warn!("Encountered indefinite length encoding, but this is a primitive element");
        return Err(err::DecodeError::PrimIndef)
      }
    }
    // Read the main data.
    let item: Self = try!(Self::deserialize_value(e, reader, len));

    // If this is encoded with an indefinte length, try to read the end octets.
    if len == tag::Len::Indef {
      try!(tag::Len::read_indef_end(reader));
    }

    Ok(item)
  }

  /// An empty method that is called first by `deserialize_with_tag` to allow
  /// custom handling, without losing normal deserialization behaviour.
  ///
  /// Return `Some(..)` to return that value, or `None` to use normal behaviour.
  fn _deserialize_with_tag<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
      (e: E, reader: &mut I, tag: tag::Tag, len: tag::Len) -> Option<Result<Self, err::DecodeError>> {
    let _ = (e, reader, tag, len);
    None
  }

  /// Deserialize an ASN.1 value from a BER stream, after having the tag and length
  /// decoded. Will be called directly when decoding an implici tag.
  ///
  /// The data length must be explicitly passed to this function. For primitive types,
  /// an error will be returned if this length is Indefinite.
  fn deserialize_value<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
    (e: E, reader: &mut I, len: tag::Len) -> Result<Self, err::DecodeError> {
    let (_, _, _) = (e, reader, len);
    panic!("deserialize_value must be implemented for types that require it");
  }
}
<|endoftext|>


<commit_before>use std;
pub fn prime_filter(iter_size: usize) -> Vec<bool>{
    if iter_size<100{
        slow_prime_filter(iter_size)
    }else{
        prime_filter_section(0, iter_size)
    }
}
fn prime_filter_section(min:usize, max: usize) -> Vec<bool>{
    //Sieve of Atkin
    assert!(min<max);
    let mut prime_filter = vec![false; max-min];
    if (min <= 2) & (max > 2) {prime_filter[2-min] = true;}
    if (min <= 3) & (max > 3) {prime_filter[3-min] = true;}
    if (min <= 5) & (max > 5) {prime_filter[5-min] = true;}

    let (mut y_sq, mut to_next_y_sq) = match min {
        0|1 => (1, 3),
        _ => (min*min, 2*min + 1),
    };
    while y_sq<max {
        if y_sq%2 == 1 {
            //n_1 = 4x^2 + y^2 === 1 (mod 4)
            let (mut n_1, mut to_next_n_1) = (y_sq, 4);
            loop{
                n_1 += to_next_n_1;
                to_next_n_1 += 8;
                match n_1%60{
                    _ if n_1 >= max => break,
                    1 | 13 | 17 | 29 | 37 | 41 | 49 | 53 => (),
                    _ => continue,
                };

                // println!("1: {}", n_1);
                prime_filter[n_1 - min] ^= true;
            };
        };
        if y_sq%3 == 1 {
            //n_2 = 3x^2 + y^2 === 1 (mod 6)
            let (mut n_2, mut to_next_n_2) = (y_sq, 3);
            loop {
                n_2 += to_next_n_2;
                to_next_n_2 += 6;
                match n_2%60{
                    _ if n_2 >= max => break,
                    7 | 19 | 31 | 43 => (),
                    _ => continue,
                };
                // println!("2: {}", n_2);
                prime_filter[n_2 - min] ^= true;
            };
            //n_3 = 3x^2 - y^2 === 11 (mod 12)
            let (mut n_3, mut to_next_n_3) = (2*y_sq, 3*to_next_y_sq);
            loop {
                n_3 += to_next_n_3;
                to_next_n_3 += 6;
                match n_3%60{
                    _ if n_3 >= max => break,
                    11 | 23 | 47 | 59 => (),
                    _ => continue,
                };
                // println!("3: {}", n_3);
                prime_filter[n_3 - min] ^= true;
            };
        };
        while{ //Do-while
            y_sq += to_next_y_sq;
            to_next_y_sq += 2;
            y_sq%6 == 0
        } {};
    };
    //Eliminate non-squarefree numbers
    let mut n_sq = 49; // 7^2
    let mut next_n_sq = 32; //9^2 - 7^2, skip even numbers.
    while n_sq < max {
        let mut non_sq_free = n_sq;
        while non_sq_free < max {
            prime_filter[non_sq_free] = false;
            while{ //Do-while
                non_sq_free += n_sq + n_sq;
                (non_sq_free%3==0) | (non_sq_free%5==0)
            } {};
        };
        while{ //Do-while
            n_sq += next_n_sq;
            next_n_sq += 8;
            (n_sq%3==0) | (n_sq%5 == 0)
        } {};
    }
    prime_filter
}

#[cfg(test)]
pub fn old_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    slow_prime_filter(iter_size)
}

fn slow_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    if iter_size < 5 {
         let mut ret = vec![false, false, true, true];
         ret.truncate(iter_size);
         return ret
     }
    let mut prime_filter = vec![true; iter_size];
    prime_filter[0] = false;
    prime_filter[1] = false;
    let mut cur_num = 2;
    'outer: loop{
        for i in (cur_num+1)..iter_size{
            if 0 == i%cur_num { prime_filter[i] = false; }
        }
        cur_num += 1;
        while !prime_filter[cur_num]{
            if cur_num*cur_num > iter_size {
                break 'outer
            }
            cur_num += 1;
        }
    };
    prime_filter
}
<commit_msg>Forgot to offset min<commit_after>use std;
pub fn prime_filter(iter_size: usize) -> Vec<bool>{
    if iter_size<100{
        slow_prime_filter(iter_size)
    }else{
        prime_filter_section(0, iter_size)
    }
}
fn prime_filter_section(min:usize, max: usize) -> Vec<bool>{
    //Sieve of Atkin
    assert!(min<max);
    let mut prime_filter = vec![false; max-min];
    if (min <= 2) & (max > 2) {prime_filter[2-min] = true;}
    if (min <= 3) & (max > 3) {prime_filter[3-min] = true;}
    if (min <= 5) & (max > 5) {prime_filter[5-min] = true;}

    let (mut y_sq, mut to_next_y_sq) = match min {
        0|1 => (1, 3),
        _ => (min*min, 2*min + 1),
    };
    while y_sq<max {
        if y_sq%2 == 1 {
            //n_1 = 4x^2 + y^2 === 1 (mod 4)
            let (mut n_1, mut to_next_n_1) = (y_sq, 4);
            loop{
                n_1 += to_next_n_1;
                to_next_n_1 += 8;
                match n_1%60{
                    _ if n_1 >= max => break,
                    1 | 13 | 17 | 29 | 37 | 41 | 49 | 53 => (),
                    _ => continue,
                };

                // println!("1: {}", n_1);
                prime_filter[n_1 - min] ^= true;
            };
        };
        if y_sq%3 == 1 {
            //n_2 = 3x^2 + y^2 === 1 (mod 6)
            let (mut n_2, mut to_next_n_2) = (y_sq, 3);
            loop {
                n_2 += to_next_n_2;
                to_next_n_2 += 6;
                match n_2%60{
                    _ if n_2 >= max => break,
                    7 | 19 | 31 | 43 => (),
                    _ => continue,
                };
                // println!("2: {}", n_2);
                prime_filter[n_2 - min] ^= true;
            };
            //n_3 = 3x^2 - y^2 === 11 (mod 12)
            let (mut n_3, mut to_next_n_3) = (2*y_sq, 3*to_next_y_sq);
            loop {
                n_3 += to_next_n_3;
                to_next_n_3 += 6;
                match n_3%60{
                    _ if n_3 >= max => break,
                    11 | 23 | 47 | 59 => (),
                    _ => continue,
                };
                // println!("3: {}", n_3);
                prime_filter[n_3 - min] ^= true;
            };
        };
        while{ //Do-while
            y_sq += to_next_y_sq;
            to_next_y_sq += 2;
            y_sq%6 == 0
        } {};
    };
    //Eliminate non-squarefree numbers
    let mut n_sq = 49; // 7^2
    let mut next_n_sq = 32; //9^2 - 7^2, skip even numbers.
    while n_sq < max {
        let mut non_sq_free = n_sq;
        while non_sq_free < max {
            if(non_sq_free > min){
                prime_filter[non_sq_free - min] = false;
            }
            while{ //Do-while
                non_sq_free += n_sq + n_sq;
                (non_sq_free%3==0) | (non_sq_free%5==0)
            } {};
        };
        while{ //Do-while
            n_sq += next_n_sq;
            next_n_sq += 8;
            (n_sq%3==0) | (n_sq%5 == 0)
        } {};
    }
    prime_filter
}

#[cfg(test)]
pub fn old_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    slow_prime_filter(iter_size)
}

fn slow_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    if iter_size < 5 {
         let mut ret = vec![false, false, true, true];
         ret.truncate(iter_size);
         return ret
     }
    let mut prime_filter = vec![true; iter_size];
    prime_filter[0] = false;
    prime_filter[1] = false;
    let mut cur_num = 2;
    'outer: loop{
        for i in (cur_num+1)..iter_size{
            if 0 == i%cur_num { prime_filter[i] = false; }
        }
        cur_num += 1;
        while !prime_filter[cur_num]{
            if cur_num*cur_num > iter_size {
                break 'outer
            }
            cur_num += 1;
        }
    };
    prime_filter
}
<|endoftext|>


<commit_before>use std;
use std::thread;
use std::sync::mpsc;

pub fn prime_filter(iter_size: usize) -> Vec<bool>{
    if iter_size<100{
        slow_prime_filter(iter_size)
    }else{
        prime_filter_section(0, iter_size)
    }
}

fn case_1(y_sq: usize, iter_size: usize)
    -> (usize, Vec<bool>) {
    //n_1 = 4x^2 + y^2 === 1 (mod 4)
    let (mut n_1, mut to_next_n_1) = (y_sq, 4);
    let offset = n_1;
    let mut temp_filter = vec![false; iter_size-offset];
    loop{
        n_1 += to_next_n_1;
        to_next_n_1 += 8;
        match n_1%60{
            _ if n_1 >= iter_size => break,
            1 | 13 | 17 | 29 | 37 | 41 | 49 | 53 => (),
            _ => continue,
        };

        // println!("1: {}", n_1);
        temp_filter[n_1-offset] ^= true;
    };
    (offset, temp_filter)
}
fn case_2(y_sq: usize, iter_size: usize)
    -> (usize, Vec<bool>) {
    //n_2 = 3x^2 + y^2 === 1 (mod 6)
    let (mut n_2, mut to_next_n_2) = (y_sq, 3);
    let offset = n_2.clone();

    let mut temp_filter = vec![false; iter_size-offset];
    loop {
        n_2 += to_next_n_2;
        to_next_n_2 += 6;
        match n_2%60{
            _ if n_2 >= iter_size => break,
            7 | 19 | 31 | 43 => (),
            _ => continue,
        };
        // println!("2: {}", n_2);
        temp_filter[n_2 - offset] ^= true;
    };
    (offset, temp_filter)
}
fn case_3(y_sq: usize, to_next_y_sq: usize, iter_size: usize)
    -> (usize, Vec<bool>) {
    //n_3 = 3x^2 - y^2 === 11 (mod 12)
    let (mut n_3, mut to_next_n_3) = (2*y_sq, 3*to_next_y_sq);
    let offset = n_3;
    let mut temp_filter = vec![false; iter_size - offset];
    loop {
        n_3 += to_next_n_3;
        to_next_n_3 += 6;
        match n_3%60{
            _ if n_3 >= iter_size => break,
            11 | 23 | 47 | 59 => (),
            _ => continue,
        };
        // println!("3: {}", n_3);
        temp_filter[n_3 - offset] ^= true;
    };
    (offset, temp_filter)
}

fn prime_filter_section(min:usize, max: usize) -> Vec<bool>{
    //Sieve of Atkin
    assert!(min<max);
    let mut prime_filter = vec![false; max-min];
    if (min <= 2) & (max > 2) {prime_filter[2-min] = true;}
    if (min <= 3) & (max > 3) {prime_filter[3-min] = true;}
    if (min <= 5) & (max > 5) {prime_filter[5-min] = true;}

    let (mut y_sq, mut to_next_y_sq) = match min {
        0|1 => (1, 3),
        _ => (min*min, 2*min + 1),
    };
    let mut spawned_threads = 0;
    let (tx, rx) = mpsc::channel();
    while y_sq<max {
        if y_sq%2 == 1 {
            spawned_threads += 1;
            let (y_sq, tx) = (y_sq, tx.clone());
            thread::spawn(move || {
                tx.send(case_1(y_sq, max)).unwrap();
            });
        };
        if y_sq%3 == 1 {

            spawned_threads += 1;
            let (y_sq, to_next_y_sq, tx1) = (y_sq, to_next_y_sq, tx.clone());
            thread::spawn(move || {
                tx1.send(case_2(y_sq, max)).unwrap();
            });
            if y_sq*2<max{
                spawned_threads += 1;
                let tx2 = tx.clone();
                thread::spawn(move || {
                    tx2.send(case_3(y_sq, to_next_y_sq, max)).unwrap();
                });
            }
        };
        if spawned_threads>0{
            for mes in rx.try_iter(){
                spawned_threads -= 1;
                let (offset, temp_filter) = mes;
                for flip_i in temp_filter.into_iter().enumerate()
                                        .filter_map(|x| match x {
                                            (i, true) => Some(i),
                                            _ => None,
                                        }){
                    prime_filter[offset + flip_i - min] ^= true;
                }
            }
        };
        while{ //Do-while
            y_sq += to_next_y_sq;
            to_next_y_sq += 2;
            y_sq%6 == 0
        } {};
    };

    while spawned_threads>0{
        for mes in rx.try_iter(){
            spawned_threads -= 1;
            let (offset, temp_filter) = mes;
            for flip_i in temp_filter.into_iter().enumerate()
                                    .filter_map(|x| match x {
                                        (i, true) => Some(i),
                                        _ => None,
                                    }){
                prime_filter[offset + flip_i - min] ^= true;
            }
        }
    };
    //Eliminate non-squarefree numbers
    let mut n_sq = 49; // 7^2
    let mut next_n_sq = 32; //9^2 - 7^2, skip even numbers.
    while n_sq < max {
        let mut non_sq_free = n_sq;
        while non_sq_free < max {
            if non_sq_free >= min {
                prime_filter[non_sq_free - min] = false;
            }
            while{ //Do-while
                non_sq_free += n_sq + n_sq;
                (non_sq_free%3==0) | (non_sq_free%5==0)
            } {};
        };
        while{ //Do-while
            n_sq += next_n_sq;
            next_n_sq += 8;
            (n_sq%3==0) | (n_sq%5 == 0)
        } {};
    }
    prime_filter
}
#[cfg(test)]
pub fn old_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    slow_prime_filter(iter_size)
}

fn slow_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    if iter_size < 5 {
         let mut ret = vec![false, false, true, true];
         ret.truncate(iter_size);
         return ret
     }
    let mut prime_filter = vec![true; iter_size];
    prime_filter[0] = false;
    prime_filter[1] = false;
    let mut cur_num = 2;
    'outer: loop{
        for i in (cur_num+1)..iter_size{
            if 0 == i%cur_num { prime_filter[i] = false; }
        }
        cur_num += 1;
        while !prime_filter[cur_num]{
            if cur_num*cur_num > iter_size {
                break 'outer
            }
            cur_num += 1;
        }
    };
    prime_filter
}
<commit_msg>Changed to stack, faster<commit_after>use std;
use std::thread;
use std::sync::mpsc;

pub fn prime_filter(iter_size: usize) -> Vec<bool>{
    if iter_size<100{
        slow_prime_filter(iter_size)
    }else{
        prime_filter_section(0, iter_size)
    }
}

fn case_1(y_sq: usize, iter_size: usize)
    -> Vec<usize> {
    //n_1 = 4x^2 + y^2 === 1 (mod 4)
    let (mut n_1, mut to_next_n_1) = (y_sq, 4);    let mut ret_stack: Vec<usize> = Vec::new();
    loop{
        n_1 += to_next_n_1;
        to_next_n_1 += 8;
        match n_1%60{
            _ if n_1 >= iter_size => break,
            1 | 13 | 17 | 29 | 37 | 41 | 49 | 53 => (),
            _ => continue,
        };

        // println!("1: {}", n_1);
        ret_stack.push(n_1);
    };
    ret_stack
}
fn case_2(y_sq: usize, iter_size: usize)
    -> Vec<usize> {
    //n_2 = 3x^2 + y^2 === 1 (mod 6)
    let (mut n_2, mut to_next_n_2) = (y_sq, 3);
    let mut ret_stack: Vec<usize> = Vec::new();
    loop {
        n_2 += to_next_n_2;
        to_next_n_2 += 6;
        match n_2%60{
            _ if n_2 >= iter_size => break,
            7 | 19 | 31 | 43 => (),
            _ => continue,
        };
        // println!("2: {}", n_2);
        ret_stack.push(n_2);
    };
    ret_stack
}
fn case_3(y_sq: usize, to_next_y_sq: usize, iter_size: usize)
    -> Vec<usize> {
    //n_3 = 3x^2 - y^2 === 11 (mod 12)
    let (mut n_3, mut to_next_n_3) = (2*y_sq, 3*to_next_y_sq);
    let mut ret_stack: Vec<usize> = Vec::new();
    loop {
        n_3 += to_next_n_3;
        to_next_n_3 += 6;
        match n_3%60{
            _ if n_3 >= iter_size => break,
            11 | 23 | 47 | 59 => (),
            _ => continue,
        };
        // println!("3: {}", n_3);
        ret_stack.push(n_3);
    };
    ret_stack
}

fn prime_filter_section(min:usize, max: usize) -> Vec<bool>{
    //Sieve of Atkin
    assert!(min<max);
    let mut prime_filter = vec![false; max-min];
    if (min <= 2) & (max > 2) {prime_filter[2-min] = true;}
    if (min <= 3) & (max > 3) {prime_filter[3-min] = true;}
    if (min <= 5) & (max > 5) {prime_filter[5-min] = true;}

    let (mut y_sq, mut to_next_y_sq) = match min {
        0|1 => (1, 3),
        _ => (min*min, 2*min + 1),
    };
    let mut spawned_threads = 0;
    let (tx, rx) = mpsc::channel();
    while y_sq<max {
        if y_sq%2 == 1 {
            spawned_threads += 1;
            let (y_sq, tx) = (y_sq, tx.clone());
            thread::spawn(move || {
                tx.send(case_1(y_sq, max)).unwrap();
            });
        };
        if y_sq%3 == 1 {

            spawned_threads += 1;
            let (y_sq, to_next_y_sq, tx1) = (y_sq, to_next_y_sq, tx.clone());
            thread::spawn(move || {
                tx1.send(case_2(y_sq, max)).unwrap();
            });
            if y_sq*2<max{
                spawned_threads += 1;
                let tx2 = tx.clone();
                thread::spawn(move || {
                    tx2.send(case_3(y_sq, to_next_y_sq, max)).unwrap();
                });
            }
        };
        if spawned_threads>0{
            for mes in rx.try_iter(){
                spawned_threads -= 1;
                for flip_i in mes{
                    prime_filter[flip_i - min] ^= true;
                }
            }
        };
        while{ //Do-while
            y_sq += to_next_y_sq;
            to_next_y_sq += 2;
            y_sq%6 == 0
        } {};
    };

    while spawned_threads>0{
        for mes in rx.try_iter(){
            spawned_threads -= 1;
            for flip_i in mes{
                prime_filter[flip_i - min] ^= true;
            }
        }
    };
    //Eliminate non-squarefree numbers
    let mut n_sq = 49; // 7^2
    let mut next_n_sq = 32; //9^2 - 7^2, skip even numbers.
    while n_sq < max {
        let mut non_sq_free = n_sq;
        while non_sq_free < max {
            if non_sq_free >= min {
                prime_filter[non_sq_free - min] = false;
            }
            while{ //Do-while
                non_sq_free += n_sq + n_sq;
                (non_sq_free%3==0) | (non_sq_free%5==0)
            } {};
        };
        while{ //Do-while
            n_sq += next_n_sq;
            next_n_sq += 8;
            (n_sq%3==0) | (n_sq%5 == 0)
        } {};
    }
    prime_filter
}
#[cfg(test)]
pub fn old_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    slow_prime_filter(iter_size)
}

fn slow_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    if iter_size < 5 {
         let mut ret = vec![false, false, true, true];
         ret.truncate(iter_size);
         return ret
     }
    let mut prime_filter = vec![true; iter_size];
    prime_filter[0] = false;
    prime_filter[1] = false;
    let mut cur_num = 2;
    'outer: loop{
        for i in (cur_num+1)..iter_size{
            if 0 == i%cur_num { prime_filter[i] = false; }
        }
        cur_num += 1;
        while !prime_filter[cur_num]{
            if cur_num*cur_num > iter_size {
                break 'outer
            }
            cur_num += 1;
        }
    };
    prime_filter
}
<|endoftext|>


<commit_before>/// Formatting macro for constructing [`Ident`]s.
///
/// [`Ident`]: `proc_macro2::Ident`
///
/// # Syntax
///
/// Syntax is copied from the [`format!`] macro, supporting both positional and
/// named arguments.
///
/// Only a limited set of formatting traits are supported. The current mapping
/// of format types to traits is:
///
/// * *nothing* ⇒ [`IdentFragment`]
/// * `o` ⇒ [`Octal`](`std::fmt::Octal`)
/// * `x` ⇒ [`LowerHex`](`std::fmt::LowerHex`)
/// * `X` ⇒ [`UpperHex`](`std::fmt::UpperHex`)
/// * `b` ⇒ [`Binary`](`std::fmt::Binary`)
///
/// See [`std::fmt`] for more information.
///
/// # IdentFragment
///
/// Unlike [`format!`], this macro uses the [`IdentFragment`] formatting trait
/// by default. This trait is like `Display`, with a few differences:
///
/// * `IdentFragment` is only implemented for a limited set of types, such as
///    unsigned integers and strings.
/// * [`Ident`] arguments will have their `r#` prefixes stripped, if present.
///
/// # Hygiene
///
/// The [`Span`] of the first [`Ident`] argument is used as the span of the
/// final identifier, falling back to [`Span::call_site`] when no identifiers
/// are provided.
///
/// ```edition2018
/// # use quote::format_ident;
/// # let ident = format_ident!("Ident");
/// // If `ident` is an Ident, the span of `my_ident` will be inherited from it.
/// let my_ident = format_ident!("My{}{}", ident, "IsCool");
/// assert_eq!(my_ident, "MyIdentIsCool");
/// ```
///
/// Alternatively, the span can be overridden by passing the `span` named
/// argument.
///
/// ```edition2018
/// # use quote::format_ident;
/// # const IGNORE_TOKENS: &'static str = stringify! {
/// let my_span = /* ... */;
/// # };
/// # let my_span = proc_macro2::Span::call_site();
/// format_ident!("MyIdent", span = my_span);
/// ```
///
/// [`Span`]: `proc_macro2::Span`
/// [`Span::call_site`]: `proc_macro2::Span::call_site`
///
/// # Panics
///
/// This method will panic if the formatted string is not a valid identifier, or
/// a formatting trait implementation returned an error.
///
/// # Examples
///
/// Composing raw and non-raw identifiers:
/// ```edition2018
/// # use quote::format_ident;
/// let my_ident = format_ident!("My{}", "Ident");
/// assert_eq!(my_ident, "MyIdent");
///
/// let raw = format_ident!("r#Raw");
/// assert_eq!(raw, "r#Raw");
///
/// let my_ident_raw = format_ident!("{}Is{}", my_ident, raw);
/// assert_eq!(my_ident_raw, "MyIdentIsRaw");
/// ```
///
/// Integer formatting options:
/// ```edition2018
/// # use quote::format_ident;
/// let num: u32 = 10;
///
/// let decimal = format_ident!("Id_{}", num);
/// assert_eq!(decimal, "Id_10");
///
/// let octal = format_ident!("Id_{:o}", num);
/// assert_eq!(octal, "Id_12");
///
/// let binary = format_ident!("Id_{:b}", num);
/// assert_eq!(binary, "Id_1010");
///
/// let lower_hex = format_ident!("Id_{:x}", num);
/// assert_eq!(lower_hex, "Id_a");
///
/// let upper_hex = format_ident!("Id_{:X}", num);
/// assert_eq!(upper_hex, "Id_A");
/// ```
#[macro_export]
macro_rules! format_ident {
    // Final State
    (@@ [$span:expr, $($o:tt)*] $(,)*) => {
        $crate::__rt::mk_ident(&format!($($o)*), $span)
    };

    // Span Argument
    (@@ [$_sp:expr, $($o:tt)*] span = $span:expr, $($t:tt)*) => {
        format_ident!(@@ [
            ::std::option::Option::Some::<$crate::__rt::Span>($span),
            $($o)*
        ] $($t)*)
    };

    // Named Arguments
    (@@ [$span:expr, $($o:tt)*] $i:ident = $e:expr, $($t:tt)*) => {
        match $crate::__rt::IdentFragmentAdapter(&$e) {
            arg => format_ident!(@@ [$span.or(arg.span()), $($o)*, $i = arg] $($t)*),
        }
    };

    // Positional Arguments
    (@@ [$span:expr, $($o:tt)*] $e:expr, $($t:tt)*) => {
        match $crate::__rt::IdentFragmentAdapter(&$e) {
            arg => format_ident!(@@ [$span.or(arg.span()), $($o)*, arg] $($t)*),
        }
    };

    // Argument Options
    ($f:expr) => {
        format_ident!(@@ [
            ::std::option::Option::None,
            $f
        ])
    };
    ($f:expr, $($t:tt)*) => {
        format_ident!(@@ [
            ::std::option::Option::None,
            $f
        ] $($t)*,)
    };
}
<commit_msg>Split format_ident private rules to a hidden macro<commit_after>/// Formatting macro for constructing [`Ident`]s.
///
/// [`Ident`]: `proc_macro2::Ident`
///
/// # Syntax
///
/// Syntax is copied from the [`format!`] macro, supporting both positional and
/// named arguments.
///
/// Only a limited set of formatting traits are supported. The current mapping
/// of format types to traits is:
///
/// * *nothing* ⇒ [`IdentFragment`]
/// * `o` ⇒ [`Octal`](`std::fmt::Octal`)
/// * `x` ⇒ [`LowerHex`](`std::fmt::LowerHex`)
/// * `X` ⇒ [`UpperHex`](`std::fmt::UpperHex`)
/// * `b` ⇒ [`Binary`](`std::fmt::Binary`)
///
/// See [`std::fmt`] for more information.
///
/// # IdentFragment
///
/// Unlike [`format!`], this macro uses the [`IdentFragment`] formatting trait
/// by default. This trait is like `Display`, with a few differences:
///
/// * `IdentFragment` is only implemented for a limited set of types, such as
///    unsigned integers and strings.
/// * [`Ident`] arguments will have their `r#` prefixes stripped, if present.
///
/// # Hygiene
///
/// The [`Span`] of the first [`Ident`] argument is used as the span of the
/// final identifier, falling back to [`Span::call_site`] when no identifiers
/// are provided.
///
/// ```edition2018
/// # use quote::format_ident;
/// # let ident = format_ident!("Ident");
/// // If `ident` is an Ident, the span of `my_ident` will be inherited from it.
/// let my_ident = format_ident!("My{}{}", ident, "IsCool");
/// assert_eq!(my_ident, "MyIdentIsCool");
/// ```
///
/// Alternatively, the span can be overridden by passing the `span` named
/// argument.
///
/// ```edition2018
/// # use quote::format_ident;
/// # const IGNORE_TOKENS: &'static str = stringify! {
/// let my_span = /* ... */;
/// # };
/// # let my_span = proc_macro2::Span::call_site();
/// format_ident!("MyIdent", span = my_span);
/// ```
///
/// [`Span`]: `proc_macro2::Span`
/// [`Span::call_site`]: `proc_macro2::Span::call_site`
///
/// # Panics
///
/// This method will panic if the formatted string is not a valid identifier, or
/// a formatting trait implementation returned an error.
///
/// # Examples
///
/// Composing raw and non-raw identifiers:
/// ```edition2018
/// # use quote::format_ident;
/// let my_ident = format_ident!("My{}", "Ident");
/// assert_eq!(my_ident, "MyIdent");
///
/// let raw = format_ident!("r#Raw");
/// assert_eq!(raw, "r#Raw");
///
/// let my_ident_raw = format_ident!("{}Is{}", my_ident, raw);
/// assert_eq!(my_ident_raw, "MyIdentIsRaw");
/// ```
///
/// Integer formatting options:
/// ```edition2018
/// # use quote::format_ident;
/// let num: u32 = 10;
///
/// let decimal = format_ident!("Id_{}", num);
/// assert_eq!(decimal, "Id_10");
///
/// let octal = format_ident!("Id_{:o}", num);
/// assert_eq!(octal, "Id_12");
///
/// let binary = format_ident!("Id_{:b}", num);
/// assert_eq!(binary, "Id_1010");
///
/// let lower_hex = format_ident!("Id_{:x}", num);
/// assert_eq!(lower_hex, "Id_a");
///
/// let upper_hex = format_ident!("Id_{:X}", num);
/// assert_eq!(upper_hex, "Id_A");
/// ```
#[macro_export]
macro_rules! format_ident {
    ($f:expr) => {
        $crate::format_ident_impl!([
            ::std::option::Option::None,
            $f
        ])
    };

    ($f:expr, $($t:tt)*) => {
        $crate::format_ident_impl!([
            ::std::option::Option::None,
            $f
        ] $($t)*,)
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! format_ident_impl {
    // Final state
    ([$span:expr, $($o:tt)*] $(,)*) => {
        $crate::__rt::mk_ident(&format!($($o)*), $span)
    };

    // Span argument
    ([$_sp:expr, $($o:tt)*] span = $span:expr, $($t:tt)*) => {
        $crate::format_ident_impl!([
            ::std::option::Option::Some::<$crate::__rt::Span>($span),
            $($o)*
        ] $($t)*)
    };

    // Named arguments
    ([$span:expr, $($o:tt)*] $i:ident = $e:expr, $($t:tt)*) => {
        match $crate::__rt::IdentFragmentAdapter(&$e) {
            arg => $crate::format_ident_impl!([$span.or(arg.span()), $($o)*, $i = arg] $($t)*),
        }
    };

    // Positional arguments
    ([$span:expr, $($o:tt)*] $e:expr, $($t:tt)*) => {
        match $crate::__rt::IdentFragmentAdapter(&$e) {
            arg => $crate::format_ident_impl!([$span.or(arg.span()), $($o)*, arg] $($t)*),
        }
    };
}
<|endoftext|>


<commit_before>/**
 * 4.3 Loops
 * http://static.rust-lang.org/doc/master/tutorial.html#loops
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */
struct Pair {
	x: int,
	y: int
}
fn main() {
	/*
	 * An example of a for loop over the contents of a vector:
	 */
	let v: &[uint] = &[4, 2, 1];
	for i in v.iter() {
		println!("{:u} is an integer!", *i);
	}

	/*
	 * A standard library function that applies a closure to every number between 0 and 10.
	 */
	for i in range(0u, 10) {
		println!("{:u} is an integer!", i);
	}

	/*
	 * is inlined by the compiler as:
	 */
	let mut j = 0u;
	while j < 10 {
		println!("{:u} is an integer!", j);
		j += 1;
	}

	/*
	 * Using loop.
	 */
	let mut k = 0u;
	loop {
		k += 1;
		if k == 10 {
			break;
		}
		println!("{:u} is an integer!", k);
	}

	/*
	 * Destructuring a struct in for loops:
	 */
	let pairs = ~[Pair {x: 10, y: 20}, Pair {x: 30, y: 0}];

	for &Pair {x, y} in pairs.iter() {
		assert_eq!(x + y, 30);
	}
}
<commit_msg>Add new code<commit_after>/**
 * 4.3 Loops
 * http://static.rust-lang.org/doc/master/tutorial.html#loops
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */
struct Pair {
	x: int,
	y: int
}
fn main() {
	/*
	 * An example of a for loop over the contents of a vector:
	 */
	let v: &[uint] = &[4, 2, 1];
	for i in v.iter() {
		println!("{:u} is an integer!", *i);
	}

	/*
	 * A standard library function that applies a closure to every number between 0 and 10.
	 */
	for i in range(0u, 10) {
		println!("{:u} is an integer!", i);
	}

	/*
	 * is inlined by the compiler as:
	 */
	let mut j = 0u;
	while j < 10 {
		println!("{:u} is an integer!", j);
		j += 1;
	}

	/*
	 * Using loop.
	 */
	let mut k = 0u;
	loop {
		k += 1;
		if k == 10 {
			break;
		}
		println!("{:u} is an integer!", k);
	}

	/*
	 * More generally, a for loop works with anything implementing the `Iterator` trait.
	 * Data structures can provide one or more methods that return iterators over their contents.
	 * For example, strings support iteration over their contents in various ways:
	 */
	let s = "Hello";
	for c in s.chars() {
    		println!("{}", c);
	}

	/*
	 * Destructuring a struct in for loops:
	 */
	let pairs = ~[Pair {x: 10, y: 20}, Pair {x: 30, y: 0}];

	for &Pair {x, y} in pairs.iter() {
		assert_eq!(x + y, 30);
	}
}
<|endoftext|>