<commit_before>#![feature(nll)]
#![feature(proc_macro_hygiene, decl_macro)]

extern crate getopts;

#[macro_use] extern crate rocket;
#[macro_use] extern crate rocket_contrib;

#[macro_use] extern crate serde_derive;

extern crate pombase;

use std::sync::Mutex;
use std::process;
use std::env;
use std::path::{Path, PathBuf};

use getopts::Options;
use rocket_contrib::json::{Json, JsonValue};
use rocket::response::NamedFile;

use pombase::api::query::Query as PomBaseQuery;
use pombase::api::result::QueryAPIResult;
use pombase::api::search::Search;
use pombase::api::query_exec::QueryExec;
use pombase::api::server_data::ServerData;
use pombase::web::data::{SolrTermSummary, SolrReferenceSummary, GeneDetails, GenotypeDetails,
                         TermDetails, ReferenceDetails};
use pombase::web::config::Config;

const PKG_NAME: &str = env!("CARGO_PKG_NAME");
const VERSION: &str = env!("CARGO_PKG_VERSION");

struct StaticFileState {
    web_root_dir: String,
}

// If the path is a directory, return path+"/index.html".  Otherwise
// try the path, then try path + ".json", then default to loading the
// Angular app from /index.html
#[get("/<path..>", rank=3)]
fn get_misc(path: PathBuf, state: rocket::State<Mutex<StaticFileState>>) -> Option<NamedFile> {
    let web_root_dir = &state.lock().expect("failed to lock").web_root_dir;
    let root_dir_path = Path::new("/").join(web_root_dir);
    let full_path = root_dir_path.join(path);

    print!("attempting to serve this path: {}\n", full_path.display());

    if full_path.is_dir() {
        let index_path = full_path.join("index.html");
        print!("found directory for {}, returning index.html\n", full_path.display());
        return NamedFile::open(index_path).ok();
    }

    if full_path.exists() {
        print!("found file for {}, returning index.html\n", full_path.display());
        return NamedFile::open(full_path).ok();
    }

    let mut json_path_str = full_path.to_str().unwrap().to_owned();
    json_path_str += ".json";
    let json_path: PathBuf = json_path_str.into();

    if json_path.exists() {
        print!("found JSON file for {}, returning index.html\n", full_path.display());
        return NamedFile::open(json_path).ok();
    }

    print!("for {}, /index.html\n", full_path.display());

    NamedFile::open(root_dir_path.join("index.html")).ok()
}

#[get("/api/v1/dataset/latest/data/gene/<id>", rank=2)]
fn get_gene(id: String, state: rocket::State<Mutex<QueryExec>>) -> Option<Json<GeneDetails>> {
    let query_exec = state.lock().expect("failed to lock");
    if let Some(gene) = query_exec.get_server_data().get_full_gene_details(&id) {
        Some(Json(gene))
    } else {
        None
    }
}

#[get("/api/v1/dataset/latest/data/genotype/<id>", rank=2)]
fn get_genotype(id: String, state: rocket::State<Mutex<QueryExec>>) -> Option<Json<GenotypeDetails>> {
    let query_exec = state.lock().expect("failed to lock");
    if let Some(genotype) = query_exec.get_server_data().get_genotype_details(&id) {
        Some(Json(genotype))
    } else {
        None
    }
}

#[get("/api/v1/dataset/latest/data/term/<id>", rank=2)]
fn get_term(id: String, state: rocket::State<Mutex<QueryExec>>) -> Option<Json<TermDetails>> {
    let query_exec = state.lock().expect("failed to lock");
    if let Some(term) = query_exec.get_server_data().get_term_details(&id) {
        Some(Json(term))
    } else {
        None
    }
}

#[get("/api/v1/dataset/latest/data/reference/<id>", rank=2)]
fn get_reference(id: String, state: rocket::State<Mutex<QueryExec>>) -> Option<Json<ReferenceDetails>> {
    let query_exec = state.lock().expect("failed to lock");
    if let Some(reference) = query_exec.get_server_data().get_reference_details(&id) {
        Some(Json(reference))
    } else {
        None
    }
}

#[get("/", rank=1)]
fn get_index(state: rocket::State<Mutex<StaticFileState>>) -> Option<NamedFile> {
    let web_root_dir = &state.lock().expect("failed to lock").web_root_dir;
    let root_dir_path = Path::new("/").join(web_root_dir);
    NamedFile::open(root_dir_path.join("index.html")).ok()
}

#[post("/api/v1/dataset/latest/query", rank=1, data="<q>", format = "application/json")]
fn query_post(q: Json<PomBaseQuery>, state: rocket::State<Mutex<QueryExec>>)
              -> Option<Json<QueryAPIResult>>
{
    let query_exec = state.lock().expect("failed to lock");
    Some(Json(query_exec.exec(&q.into_inner())))
}

#[get ("/reload")]
fn reload(state: rocket::State<Mutex<QueryExec>>) {
    let mut query_exec = state.lock().expect("failed to lock");
    print!("reloading ...\n");
    query_exec.reload();
    print!("... done\n");
}

#[derive(Serialize, Debug)]
struct TermCompletionResponse {
    status: String,
    matches: Vec<SolrTermSummary>,
}

#[derive(Serialize, Debug)]
struct RefCompletionResponse {
    status: String,
    matches: Vec<SolrReferenceSummary>,
}

#[get ("/api/v1/dataset/latest/complete/term/<cv_name>/<q>", rank=1)]
fn term_complete(cv_name: String, q: String, state: rocket::State<Mutex<Search>>)
              -> Option<Json<TermCompletionResponse>>
{
    let search = state.lock().expect("failed to lock");
    let res = search.term_complete(&cv_name, &q);

    let completion_response =
        match res {
            Ok(matches) => {
                TermCompletionResponse {
                    status: "Ok".to_owned(),
                    matches: matches,
                }
            },
            Err(err) => {
                println!("{:?}", err);
                TermCompletionResponse {
                    status: "Error".to_owned(),
                    matches: vec![],
                }
            },
        };

    Some(Json(completion_response))
}

#[get ("/api/v1/dataset/latest/complete/ref/<q>", rank=1)]
fn ref_complete(q: String, state: rocket::State<Mutex<Search>>)
                -> Option<Json<RefCompletionResponse>>
{
    let search = state.lock().expect("failed to lock");
    let res = search.ref_complete(&q);

    let completion_response =
        match res {
            Ok(matches) => {
                RefCompletionResponse {
                    status: "Ok".to_owned(),
                    matches: matches,
                }
            },
            Err(err) => {
                println!("{:?}", err);
                RefCompletionResponse {
                    status: "Error".to_owned(),
                    matches: vec![],
                }
            },
        };

    Some(Json(completion_response))
}

#[get ("/api/v1/dataset/latest/motif_search/<scope>/<q>", rank=1)]
fn motif_search(scope: String, q: String, state: rocket::State<Mutex<Search>>)
                -> Option<String>
{
    let search = state.lock().expect("failed to lock");
    let res = search.motif_search(&scope, &q);

    match res {
        Ok(search_result) => {
            Some(search_result)
        },
        Err(err) => {
            println!("Motif search error: {:?}", err);
            None
        },
    }
}

#[get ("/ping", rank=1)]
fn ping() -> Option<String> {
    Some(String::from("OK") + " " + PKG_NAME + " " + VERSION)
}

#[catch(404)]
fn not_found() -> JsonValue {
    json!({
        "status": "error",
        "reason": "Resource was not found."
    })
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    print!("{} v{}\n", PKG_NAME, VERSION);

    let args: Vec<String> = env::args().collect();
    let mut opts = Options::new();

    opts.optflag("h", "help", "print this help message");
    opts.optopt("c", "config-file", "Configuration file name", "CONFIG");
    opts.optopt("m", "search-maps", "Search data", "MAPS_JSON_FILE");
    opts.optopt("w", "web-root-dir", "Root web data directory", "WEB_ROOT_DIR");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!("Invalid options\n{}", f)
    };

    let program = args[0].clone();

    if matches.opt_present("help") {
        print_usage(&program, opts);
        process::exit(0);
    }

    if !matches.opt_present("config-file") {
        print!("no -c|--config-file option\n");
        print_usage(&program, opts);
        process::exit(1);
    }
    if !matches.opt_present("search-maps") {
        print!("no --search-maps|-m option\n");
        print_usage(&program, opts);
        process::exit(1);
    }
    if !matches.opt_present("web-root-dir") {
        print!("no --web-root-dir|-w option\n");
        print_usage(&program, opts);
        process::exit(1);
    }

    let search_maps_filename = matches.opt_str("m").unwrap();
    println!("Reading data files ...");

    let config_file_name = matches.opt_str("c").unwrap();
    let server_data = ServerData::new(&config_file_name, &search_maps_filename);
    let query_exec = QueryExec::new(server_data);
    let config = Config::read(&config_file_name);
    let searcher = Search::new(&config);

    let web_root_dir = matches.opt_str("w").unwrap();
    let static_file_state = StaticFileState {
        web_root_dir: web_root_dir,
    };

    println!("Starting server ...");
    rocket::ignite()
        .mount("/", routes![get_index, get_misc, query_post,
                            get_gene, get_genotype, get_term, get_reference,
                            reload, term_complete, ref_complete,
                            motif_search, ping])
        .register(catchers![not_found])
        .manage(Mutex::new(query_exec))
        .manage(Mutex::new(searcher))
        .manage(Mutex::new(static_file_state))
        .launch();
}
<commit_msg>Revert "Add code for debugging paths"<commit_after>#![feature(nll)]
#![feature(proc_macro_hygiene, decl_macro)]

extern crate getopts;

#[macro_use] extern crate rocket;
#[macro_use] extern crate rocket_contrib;

#[macro_use] extern crate serde_derive;

extern crate pombase;

use std::sync::Mutex;
use std::process;
use std::env;
use std::path::{Path, PathBuf};

use getopts::Options;
use rocket_contrib::json::{Json, JsonValue};
use rocket::response::NamedFile;

use pombase::api::query::Query as PomBaseQuery;
use pombase::api::result::QueryAPIResult;
use pombase::api::search::Search;
use pombase::api::query_exec::QueryExec;
use pombase::api::server_data::ServerData;
use pombase::web::data::{SolrTermSummary, SolrReferenceSummary, GeneDetails, GenotypeDetails,
                         TermDetails, ReferenceDetails};
use pombase::web::config::Config;

const PKG_NAME: &str = env!("CARGO_PKG_NAME");
const VERSION: &str = env!("CARGO_PKG_VERSION");

struct StaticFileState {
    web_root_dir: String,
}

// If the path is a directory, return path+"/index.html".  Otherwise
// try the path, then try path + ".json", then default to loading the
// Angular app from /index.html
#[get("/<path..>", rank=3)]
fn get_misc(path: PathBuf, state: rocket::State<Mutex<StaticFileState>>) -> Option<NamedFile> {
    let web_root_dir = &state.lock().expect("failed to lock").web_root_dir;
    let root_dir_path = Path::new("/").join(web_root_dir);
    let full_path = root_dir_path.join(path);

    if full_path.is_dir() {
        let index_path = full_path.join("index.html");
        return NamedFile::open(index_path).ok();
    }

    if full_path.exists() {
        return NamedFile::open(full_path).ok();
    }

    let mut json_path_str = full_path.to_str().unwrap().to_owned();
    json_path_str += ".json";
    let json_path: PathBuf = json_path_str.into();

    if json_path.exists() {
        return NamedFile::open(json_path).ok();
    }

    NamedFile::open(root_dir_path.join("index.html")).ok()
}

#[get("/api/v1/dataset/latest/data/gene/<id>", rank=2)]
fn get_gene(id: String, state: rocket::State<Mutex<QueryExec>>) -> Option<Json<GeneDetails>> {
    let query_exec = state.lock().expect("failed to lock");
    if let Some(gene) = query_exec.get_server_data().get_full_gene_details(&id) {
        Some(Json(gene))
    } else {
        None
    }
}

#[get("/api/v1/dataset/latest/data/genotype/<id>", rank=2)]
fn get_genotype(id: String, state: rocket::State<Mutex<QueryExec>>) -> Option<Json<GenotypeDetails>> {
    let query_exec = state.lock().expect("failed to lock");
    if let Some(genotype) = query_exec.get_server_data().get_genotype_details(&id) {
        Some(Json(genotype))
    } else {
        None
    }
}

#[get("/api/v1/dataset/latest/data/term/<id>", rank=2)]
fn get_term(id: String, state: rocket::State<Mutex<QueryExec>>) -> Option<Json<TermDetails>> {
    let query_exec = state.lock().expect("failed to lock");
    if let Some(term) = query_exec.get_server_data().get_term_details(&id) {
        Some(Json(term))
    } else {
        None
    }
}

#[get("/api/v1/dataset/latest/data/reference/<id>", rank=2)]
fn get_reference(id: String, state: rocket::State<Mutex<QueryExec>>) -> Option<Json<ReferenceDetails>> {
    let query_exec = state.lock().expect("failed to lock");
    if let Some(reference) = query_exec.get_server_data().get_reference_details(&id) {
        Some(Json(reference))
    } else {
        None
    }
}

#[get("/", rank=1)]
fn get_index(state: rocket::State<Mutex<StaticFileState>>) -> Option<NamedFile> {
    let web_root_dir = &state.lock().expect("failed to lock").web_root_dir;
    let root_dir_path = Path::new("/").join(web_root_dir);
    NamedFile::open(root_dir_path.join("index.html")).ok()
}

#[post("/api/v1/dataset/latest/query", rank=1, data="<q>", format = "application/json")]
fn query_post(q: Json<PomBaseQuery>, state: rocket::State<Mutex<QueryExec>>)
              -> Option<Json<QueryAPIResult>>
{
    let query_exec = state.lock().expect("failed to lock");
    Some(Json(query_exec.exec(&q.into_inner())))
}

#[get ("/reload")]
fn reload(state: rocket::State<Mutex<QueryExec>>) {
    let mut query_exec = state.lock().expect("failed to lock");
    print!("reloading ...\n");
    query_exec.reload();
    print!("... done\n");
}

#[derive(Serialize, Debug)]
struct TermCompletionResponse {
    status: String,
    matches: Vec<SolrTermSummary>,
}

#[derive(Serialize, Debug)]
struct RefCompletionResponse {
    status: String,
    matches: Vec<SolrReferenceSummary>,
}

#[get ("/api/v1/dataset/latest/complete/term/<cv_name>/<q>", rank=1)]
fn term_complete(cv_name: String, q: String, state: rocket::State<Mutex<Search>>)
              -> Option<Json<TermCompletionResponse>>
{
    let search = state.lock().expect("failed to lock");
    let res = search.term_complete(&cv_name, &q);

    let completion_response =
        match res {
            Ok(matches) => {
                TermCompletionResponse {
                    status: "Ok".to_owned(),
                    matches: matches,
                }
            },
            Err(err) => {
                println!("{:?}", err);
                TermCompletionResponse {
                    status: "Error".to_owned(),
                    matches: vec![],
                }
            },
        };

    Some(Json(completion_response))
}

#[get ("/api/v1/dataset/latest/complete/ref/<q>", rank=1)]
fn ref_complete(q: String, state: rocket::State<Mutex<Search>>)
                -> Option<Json<RefCompletionResponse>>
{
    let search = state.lock().expect("failed to lock");
    let res = search.ref_complete(&q);

    let completion_response =
        match res {
            Ok(matches) => {
                RefCompletionResponse {
                    status: "Ok".to_owned(),
                    matches: matches,
                }
            },
            Err(err) => {
                println!("{:?}", err);
                RefCompletionResponse {
                    status: "Error".to_owned(),
                    matches: vec![],
                }
            },
        };

    Some(Json(completion_response))
}

#[get ("/api/v1/dataset/latest/motif_search/<scope>/<q>", rank=1)]
fn motif_search(scope: String, q: String, state: rocket::State<Mutex<Search>>)
                -> Option<String>
{
    let search = state.lock().expect("failed to lock");
    let res = search.motif_search(&scope, &q);

    match res {
        Ok(search_result) => {
            Some(search_result)
        },
        Err(err) => {
            println!("Motif search error: {:?}", err);
            None
        },
    }
}

#[get ("/ping", rank=1)]
fn ping() -> Option<String> {
    Some(String::from("OK") + " " + PKG_NAME + " " + VERSION)
}

#[catch(404)]
fn not_found() -> JsonValue {
    json!({
        "status": "error",
        "reason": "Resource was not found."
    })
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    print!("{} v{}\n", PKG_NAME, VERSION);

    let args: Vec<String> = env::args().collect();
    let mut opts = Options::new();

    opts.optflag("h", "help", "print this help message");
    opts.optopt("c", "config-file", "Configuration file name", "CONFIG");
    opts.optopt("m", "search-maps", "Search data", "MAPS_JSON_FILE");
    opts.optopt("w", "web-root-dir", "Root web data directory", "WEB_ROOT_DIR");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!("Invalid options\n{}", f)
    };

    let program = args[0].clone();

    if matches.opt_present("help") {
        print_usage(&program, opts);
        process::exit(0);
    }

    if !matches.opt_present("config-file") {
        print!("no -c|--config-file option\n");
        print_usage(&program, opts);
        process::exit(1);
    }
    if !matches.opt_present("search-maps") {
        print!("no --search-maps|-m option\n");
        print_usage(&program, opts);
        process::exit(1);
    }
    if !matches.opt_present("web-root-dir") {
        print!("no --web-root-dir|-w option\n");
        print_usage(&program, opts);
        process::exit(1);
    }

    let search_maps_filename = matches.opt_str("m").unwrap();
    println!("Reading data files ...");

    let config_file_name = matches.opt_str("c").unwrap();
    let server_data = ServerData::new(&config_file_name, &search_maps_filename);
    let query_exec = QueryExec::new(server_data);
    let config = Config::read(&config_file_name);
    let searcher = Search::new(&config);

    let web_root_dir = matches.opt_str("w").unwrap();
    let static_file_state = StaticFileState {
        web_root_dir: web_root_dir,
    };

    println!("Starting server ...");
    rocket::ignite()
        .mount("/", routes![get_index, get_misc, query_post,
                            get_gene, get_genotype, get_term, get_reference,
                            reload, term_complete, ref_complete,
                            motif_search, ping])
        .register(catchers![not_found])
        .manage(Mutex::new(query_exec))
        .manage(Mutex::new(searcher))
        .manage(Mutex::new(static_file_state))
        .launch();
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, WriteBytesExt};
use std::io::{self, Write};

use crate::color::ColorType;
use crate::error::ImageResult;
use crate::image::ImageEncoder;

use crate::codecs::png::PngEncoder;

// Enum value indicating an ICO image (as opposed to a CUR image):
const ICO_IMAGE_TYPE: u16 = 1;
// The length of an ICO file ICONDIR structure, in bytes:
const ICO_ICONDIR_SIZE: u32 = 6;
// The length of an ICO file DIRENTRY structure, in bytes:
const ICO_DIRENTRY_SIZE: u32 = 16;

/// ICO encoder
pub struct IcoEncoder<W: Write> {
    w: W,
}

impl<W: Write> IcoEncoder<W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: W) -> IcoEncoder<W> {
        IcoEncoder { w }
    }

    /// Encodes the image ```image``` that has dimensions ```width``` and
    /// ```height``` and ```ColorType``` ```c```.  The dimensions of the image
    /// must be between 1 and 256 (inclusive) or an error will be returned.
    pub fn encode(
        mut self,
        data: &[u8],
        width: u32,
        height: u32,
        color: ColorType,
    ) -> ImageResult<()> {
        let mut image_data: Vec<u8> = Vec::new();
        PngEncoder::new(&mut image_data).encode(data, width, height, color)?;

        write_icondir(&mut self.w, 1)?;
        write_direntry(
            &mut self.w,
            width,
            height,
            color,
            ICO_ICONDIR_SIZE + ICO_DIRENTRY_SIZE,
            image_data.len() as u32,
        )?;
        self.w.write_all(&image_data)?;
        Ok(())
    }
}

impl<W: Write> ImageEncoder for IcoEncoder<W> {
    fn write_image(
        self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        self.encode(buf, width, height, color_type)
    }
}

fn write_icondir<W: Write>(w: &mut W, num_images: u16) -> io::Result<()> {
    // Reserved field (must be zero):
    w.write_u16::<LittleEndian>(0)?;
    // Image type (ICO or CUR):
    w.write_u16::<LittleEndian>(ICO_IMAGE_TYPE)?;
    // Number of images in the file:
    w.write_u16::<LittleEndian>(num_images)?;
    Ok(())
}

fn write_direntry<W: Write>(
    w: &mut W,
    width: u32,
    height: u32,
    color: ColorType,
    data_start: u32,
    data_size: u32,
) -> io::Result<()> {
    // Image dimensions:
    write_width_or_height(w, width)?;
    write_width_or_height(w, height)?;
    // Number of colors in palette (or zero for no palette):
    w.write_u8(0)?;
    // Reserved field (must be zero):
    w.write_u8(0)?;
    // Color planes:
    w.write_u16::<LittleEndian>(0)?;
    // Bits per pixel:
    w.write_u16::<LittleEndian>(color.bits_per_pixel())?;
    // Image data size, in bytes:
    w.write_u32::<LittleEndian>(data_size)?;
    // Image data offset, in bytes:
    w.write_u32::<LittleEndian>(data_start)?;
    Ok(())
}

/// Encode a width/height value as a single byte, where 0 means 256.
fn write_width_or_height<W: Write>(w: &mut W, value: u32) -> io::Result<()> {
    if value < 1 || value > 256 {
        // TODO: this is not very idiomatic yet. Should return an EncodingError and be checked
        // prior to encoding.
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            "Invalid ICO dimensions (width and \
             height must be between 1 and 256)",
        ));
    }
    w.write_u8(if value < 256 { value as u8 } else { 0 })
}
<commit_msg>Deprecate IcoEncoder::encode due to endianness issue<commit_after>use byteorder::{LittleEndian, WriteBytesExt};
use std::io::{self, Write};

use crate::color::ColorType;
use crate::error::ImageResult;
use crate::image::ImageEncoder;

use crate::codecs::png::PngEncoder;

// Enum value indicating an ICO image (as opposed to a CUR image):
const ICO_IMAGE_TYPE: u16 = 1;
// The length of an ICO file ICONDIR structure, in bytes:
const ICO_ICONDIR_SIZE: u32 = 6;
// The length of an ICO file DIRENTRY structure, in bytes:
const ICO_DIRENTRY_SIZE: u32 = 16;

/// ICO encoder
pub struct IcoEncoder<W: Write> {
    w: W,
}

impl<W: Write> IcoEncoder<W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: W) -> IcoEncoder<W> {
        IcoEncoder { w }
    }

    /// Encodes the image ```image``` that has dimensions ```width``` and
    /// ```height``` and ```ColorType``` ```c```.  The dimensions of the image
    /// must be between 1 and 256 (inclusive) or an error will be returned.
    ///
    /// Expects data to be big endian.
    #[deprecated = "Use `IcoEncoder::write_image` instead. Beware that `write_image` has a different endianness convention"]
    pub fn encode(
        mut self,
        data: &[u8],
        width: u32,
        height: u32,
        color: ColorType,
    ) -> ImageResult<()> {
        let mut image_data: Vec<u8> = Vec::new();
        #[allow(deprecated)]
        PngEncoder::new(&mut image_data).encode(data, width, height, color)?;

        write_icondir(&mut self.w, 1)?;
        write_direntry(
            &mut self.w,
            width,
            height,
            color,
            ICO_ICONDIR_SIZE + ICO_DIRENTRY_SIZE,
            image_data.len() as u32,
        )?;
        self.w.write_all(&image_data)?;
        Ok(())
    }
}

impl<W: Write> ImageEncoder for IcoEncoder<W> {
    /// Write an ICO image with the specified width, height, and color type.
    ///
    /// For color types with 16-bit per channel or larger, the contents of `buf` should be in
    /// native endian.
    ///
    /// WARNING: In image 0.23.14 and earlier this method erroneously expected buf to be in big endian.
    fn write_image(
        mut self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        let mut image_data: Vec<u8> = Vec::new();
        PngEncoder::new(&mut image_data).write_image(buf, width, height, color_type)?;

        write_icondir(&mut self.w, 1)?;
        write_direntry(
            &mut self.w,
            width,
            height,
            color_type,
            ICO_ICONDIR_SIZE + ICO_DIRENTRY_SIZE,
            image_data.len() as u32,
        )?;
        self.w.write_all(&image_data)?;
        Ok(())
    }
}

fn write_icondir<W: Write>(w: &mut W, num_images: u16) -> io::Result<()> {
    // Reserved field (must be zero):
    w.write_u16::<LittleEndian>(0)?;
    // Image type (ICO or CUR):
    w.write_u16::<LittleEndian>(ICO_IMAGE_TYPE)?;
    // Number of images in the file:
    w.write_u16::<LittleEndian>(num_images)?;
    Ok(())
}

fn write_direntry<W: Write>(
    w: &mut W,
    width: u32,
    height: u32,
    color: ColorType,
    data_start: u32,
    data_size: u32,
) -> io::Result<()> {
    // Image dimensions:
    write_width_or_height(w, width)?;
    write_width_or_height(w, height)?;
    // Number of colors in palette (or zero for no palette):
    w.write_u8(0)?;
    // Reserved field (must be zero):
    w.write_u8(0)?;
    // Color planes:
    w.write_u16::<LittleEndian>(0)?;
    // Bits per pixel:
    w.write_u16::<LittleEndian>(color.bits_per_pixel())?;
    // Image data size, in bytes:
    w.write_u32::<LittleEndian>(data_size)?;
    // Image data offset, in bytes:
    w.write_u32::<LittleEndian>(data_start)?;
    Ok(())
}

/// Encode a width/height value as a single byte, where 0 means 256.
fn write_width_or_height<W: Write>(w: &mut W, value: u32) -> io::Result<()> {
    if value < 1 || value > 256 {
        // TODO: this is not very idiomatic yet. Should return an EncodingError and be checked
        // prior to encoding.
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            "Invalid ICO dimensions (width and \
             height must be between 1 and 256)",
        ));
    }
    w.write_u8(if value < 256 { value as u8 } else { 0 })
}
<|endoftext|>


<commit_before>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use config::file_lines::FileLines;
use config::options::WidthHeuristics;

/// Trait for types that can be used in `Config`.
pub trait ConfigType: Sized {
    /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a
    /// pipe-separated list of variants; for other types it returns "<type>".
    fn doc_hint() -> String;
}

impl ConfigType for bool {
    fn doc_hint() -> String {
        String::from("<boolean>")
    }
}

impl ConfigType for usize {
    fn doc_hint() -> String {
        String::from("<unsigned integer>")
    }
}

impl ConfigType for isize {
    fn doc_hint() -> String {
        String::from("<signed integer>")
    }
}

impl ConfigType for String {
    fn doc_hint() -> String {
        String::from("<string>")
    }
}

impl ConfigType for FileLines {
    fn doc_hint() -> String {
        String::from("<json>")
    }
}

impl ConfigType for WidthHeuristics {
    fn doc_hint() -> String {
        String::new()
    }
}

/// Check if we're in a nightly build.
///
/// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap
/// to "stable", "beta", or "nightly" depending on what toolchain is being built.
/// If we are being built as part of the stable or beta toolchains, we want
/// to disable unstable configuration options.
///
/// If we're being built by cargo (e.g. `cargo +nightly install rustfmt-nightly`),
/// `CFG_RELEASE_CHANNEL` is not set. As we only support being built against the
/// nightly compiler when installed from crates.io, default to nightly mode.
macro_rules! is_nightly_channel {
    () => {
        option_env!("CFG_RELEASE_CHANNEL")
            .map(|c| c == "nightly")
            .unwrap_or(true)
    };
}

macro_rules! create_config {
    ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => (
        use std::collections::HashSet;

        #[derive(Clone)]
        pub struct Config {
            // if a license_template_path has been specified, successfully read, parsed and compiled
            // into a regex, it will be stored here
            pub license_template: Option<Regex>,
            // For each config item, we store a bool indicating whether it has
            // been accessed and the value, and a bool whether the option was
            // manually initialised, or taken from the default,
            $($i: (Cell<bool>, bool, $ty, bool)),+
        }

        // Just like the Config struct but with each property wrapped
        // as Option<T>. This is used to parse a rustfmt.toml that doesn't
        // specify all properties of `Config`.
        // We first parse into `PartialConfig`, then create a default `Config`
        // and overwrite the properties with corresponding values from `PartialConfig`.
        #[derive(Deserialize, Serialize, Clone)]
        pub struct PartialConfig {
            $(pub $i: Option<$ty>),+
        }

        impl PartialConfig {
            pub fn to_toml(&self) -> Result<String, String> {
                // Non-user-facing options can't be specified in TOML
                let mut cloned = self.clone();
                cloned.file_lines = None;
                cloned.verbose = None;
                cloned.width_heuristics = None;

                ::toml::to_string(&cloned)
                    .map_err(|e| format!("Could not output config: {}", e.to_string()))
            }
        }

        // Macro hygiene won't allow us to make `set_$i()` methods on Config
        // for each item, so this struct is used to give the API to set values:
        // `config.set().option(false)`. It's pretty ugly. Consider replacing
        // with `config.set_option(false)` if we ever get a stable/usable
        // `concat_idents!()`.
        pub struct ConfigSetter<'a>(&'a mut Config);

        impl<'a> ConfigSetter<'a> {
            $(
            pub fn $i(&mut self, value: $ty) {
                (self.0).$i.2 = value;
                match stringify!($i) {
                    "use_small_heuristics" => self.0.set_heuristics(),
                    "license_template_path" => self.0.set_license_template(),
                    &_ => (),
                }
            }
            )+
        }

        // Query each option, returns true if the user set the option, false if
        // a default was used.
        pub struct ConfigWasSet<'a>(&'a Config);

        impl<'a> ConfigWasSet<'a> {
            $(
            pub fn $i(&self) -> bool {
                (self.0).$i.1
            }
            )+
        }

        impl Config {
            pub fn version_meets_requirement(&self, error_summary: &mut Summary) -> bool {
                if self.was_set().required_version() {
                    let version = env!("CARGO_PKG_VERSION");
                    let required_version = self.required_version();
                    if version != required_version {
                        println!(
                            "Error: rustfmt version ({}) doesn't match the required version ({})",
                            version,
                            required_version,
                        );
                        error_summary.add_formatting_error();
                        return false;
                    }
                }

                true
            }

            $(
            pub fn $i(&self) -> $ty {
                self.$i.0.set(true);
                self.$i.2.clone()
            }
            )+

            pub fn set<'a>(&'a mut self) -> ConfigSetter<'a> {
                ConfigSetter(self)
            }

            pub fn was_set<'a>(&'a self) -> ConfigWasSet<'a> {
                ConfigWasSet(self)
            }

            fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config {
            $(
                if let Some(val) = parsed.$i {
                    if self.$i.3 {
                        self.$i.1 = true;
                        self.$i.2 = val;
                    } else {
                        if is_nightly_channel!() {
                            self.$i.1 = true;
                            self.$i.2 = val;
                        } else {
                            eprintln!("Warning: can't set `{} = {:?}`, unstable features are only \
                                       available in nightly channel.", stringify!($i), val);
                        }
                    }
                }
            )+
                self.set_heuristics();
                self.set_license_template();
                self
            }

            /// Returns a hash set initialized with every user-facing config option name.
            pub fn hash_set() -> HashSet<String> {
                let mut hash_set = HashSet::new();
                $(
                    hash_set.insert(stringify!($i).to_owned());
                )+
                hash_set
            }

            pub fn is_valid_name(name: &str) -> bool {
                match name {
                    $(
                        stringify!($i) => true,
                    )+
                        _ => false,
                }
            }

            pub fn from_toml(toml: &str) -> Result<Config, String> {
                let parsed: ::toml::Value =
                    toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?;
                let mut err: String = String::new();
                {
                    let table = parsed
                        .as_table()
                        .ok_or(String::from("Parsed config was not table"))?;
                    for key in table.keys() {
                        if !Config::is_valid_name(key) {
                            let msg = &format!("Warning: Unknown configuration option `{}`\n", key);
                            err.push_str(msg)
                        }
                    }
                }
                match parsed.try_into() {
                    Ok(parsed_config) => {
                        if !err.is_empty() {
                            eprint!("{}", err);
                        }
                        Ok(Config::default().fill_from_parsed_config(parsed_config))
                    }
                    Err(e) => {
                        err.push_str("Error: Decoding config file failed:\n");
                        err.push_str(format!("{}\n", e).as_str());
                        err.push_str("Please check your config file.");
                        Err(err)
                    }
                }
            }

            pub fn used_options(&self) -> PartialConfig {
                PartialConfig {
                    $(
                        $i: if self.$i.0.get() {
                                Some(self.$i.2.clone())
                            } else {
                                None
                            },
                    )+
                }
            }

            pub fn all_options(&self) -> PartialConfig {
                PartialConfig {
                    $(
                        $i: Some(self.$i.2.clone()),
                    )+
                }
            }

            pub fn override_value(&mut self, key: &str, val: &str)
            {
                match key {
                    $(
                        stringify!($i) => {
                            self.$i.2 = val.parse::<$ty>()
                                .expect(&format!("Failed to parse override for {} (\"{}\") as a {}",
                                                 stringify!($i),
                                                 val,
                                                 stringify!($ty)));
                        }
                    )+
                    _ => panic!("Unknown config key in override: {}", key)
                }

                match key {
                    "use_small_heuristics" => self.set_heuristics(),
                    "license_template_path" => self.set_license_template(),
                    &_ => (),
                }
            }

            /// Construct a `Config` from the toml file specified at `file_path`.
            ///
            /// This method only looks at the provided path, for a method that
            /// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`.
            ///
            /// Return a `Config` if the config could be read and parsed from
            /// the file, Error otherwise.
            pub fn from_toml_path(file_path: &Path) -> Result<Config, Error> {
                let mut file = File::open(&file_path)?;
                let mut toml = String::new();
                file.read_to_string(&mut toml)?;
                Config::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err))
            }

            /// Resolve the config for input in `dir`.
            ///
            /// Searches for `rustfmt.toml` beginning with `dir`, and
            /// recursively checking parents of `dir` if no config file is found.
            /// If no config file exists in `dir` or in any parent, a
            /// default `Config` will be returned (and the returned path will be empty).
            ///
            /// Returns the `Config` to use, and the path of the project file if there was
            /// one.
            pub fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option<PathBuf>), Error> {

                /// Try to find a project file in the given directory and its parents.
                /// Returns the path of a the nearest project file if one exists,
                /// or `None` if no project file was found.
                fn resolve_project_file(dir: &Path) -> Result<Option<PathBuf>, Error> {
                    let mut current = if dir.is_relative() {
                        env::current_dir()?.join(dir)
                    } else {
                        dir.to_path_buf()
                    };

                    current = fs::canonicalize(current)?;

                    loop {
                        match get_toml_path(&current) {
                            Ok(Some(path)) => return Ok(Some(path)),
                            Err(e) => return Err(e),
                            _ => ()
                        }

                        // If the current directory has no parent, we're done searching.
                        if !current.pop() {
                            return Ok(None);
                        }
                    }
                }

                match resolve_project_file(dir)? {
                    None => Ok((Config::default(), None)),
                    Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))),
                }
            }

            pub fn is_hidden_option(name: &str) -> bool {
                const HIDE_OPTIONS: [&str; 3] = ["verbose", "file_lines", "width_heuristics"];
                HIDE_OPTIONS.contains(&name)
            }

            pub fn print_docs() {
                use std::cmp;
                let max = 0;
                $( let max = cmp::max(max, stringify!($i).len()+1); )+
                let mut space_str = String::with_capacity(max);
                for _ in 0..max {
                    space_str.push(' ');
                }
                println!("Configuration Options:");
                $(
                    let name_raw = stringify!($i);

                    if !Config::is_hidden_option(name_raw) {
                        let mut name_out = String::with_capacity(max);
                        for _ in name_raw.len()..max-1 {
                            name_out.push(' ')
                        }
                        name_out.push_str(name_raw);
                        name_out.push(' ');
                        println!("{}{} Default: {:?}",
                                name_out,
                                <$ty>::doc_hint(),
                                $def);
                        $(
                            println!("{}{}", space_str, $dstring);
                        )+
                        println!();
                    }
                )+
            }

            fn set_heuristics(&mut self) {
                if self.use_small_heuristics.2 {
                    let max_width = self.max_width.2;
                    self.set().width_heuristics(WidthHeuristics::scaled(max_width));
                } else {
                    self.set().width_heuristics(WidthHeuristics::null());
                }
            }

            fn set_license_template(&mut self) {
                if self.was_set().license_template_path() {
                    let license_template_path = self.license_template_path();
                    let mut license_template_file = match File::open(&license_template_path) {
                        Ok(file) => file,
                        Err(e) => {
                            eprintln!("Warning: unable to open license template file {:?}: {}",
                                    license_template_path, e);
                            return;
                        }
                    };
                    let mut license_template_str = String::new();
                    if let Err(e) = license_template_file.read_to_string(&mut license_template_str) {
                        eprintln!("Warning: unable to read from license template file {:?}: {}",
                                license_template_path, e);
                        return;
                    };
                    let license_template_parsed = match TemplateParser::parse(&license_template_str) {
                        Ok(string) => string,
                        Err(e) => {
                            eprintln!("Warning: unable to parse license template file {:?}: {}",
                                    license_template_path, e);
                            return;
                        }
                    };
                    self.license_template = match Regex::new(&license_template_parsed) {
                        Ok(re) => Some(re),
                        Err(e) => {
                            eprintln!("Warning: regex syntax error in placeholder, unable to compile \
                                    license template from file {:?}: {}", license_template_path, e);
                            return;
                        }
                    }
                }
            }
        }

        // Template for the default configuration
        impl Default for Config {
            fn default() -> Config {
                Config {
                    license_template: None,
                    $(
                        $i: (Cell::new(false), false, $def, $stb),
                    )+
                }
            }
        }
    )
}
<commit_msg>Fix indentation in create_config macro definition<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use config::file_lines::FileLines;
use config::options::WidthHeuristics;

/// Trait for types that can be used in `Config`.
pub trait ConfigType: Sized {
    /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a
    /// pipe-separated list of variants; for other types it returns "<type>".
    fn doc_hint() -> String;
}

impl ConfigType for bool {
    fn doc_hint() -> String {
        String::from("<boolean>")
    }
}

impl ConfigType for usize {
    fn doc_hint() -> String {
        String::from("<unsigned integer>")
    }
}

impl ConfigType for isize {
    fn doc_hint() -> String {
        String::from("<signed integer>")
    }
}

impl ConfigType for String {
    fn doc_hint() -> String {
        String::from("<string>")
    }
}

impl ConfigType for FileLines {
    fn doc_hint() -> String {
        String::from("<json>")
    }
}

impl ConfigType for WidthHeuristics {
    fn doc_hint() -> String {
        String::new()
    }
}

/// Check if we're in a nightly build.
///
/// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap
/// to "stable", "beta", or "nightly" depending on what toolchain is being built.
/// If we are being built as part of the stable or beta toolchains, we want
/// to disable unstable configuration options.
///
/// If we're being built by cargo (e.g. `cargo +nightly install rustfmt-nightly`),
/// `CFG_RELEASE_CHANNEL` is not set. As we only support being built against the
/// nightly compiler when installed from crates.io, default to nightly mode.
macro_rules! is_nightly_channel {
    () => {
        option_env!("CFG_RELEASE_CHANNEL")
            .map(|c| c == "nightly")
            .unwrap_or(true)
    };
}

macro_rules! create_config {
    ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => (
        use std::collections::HashSet;

        #[derive(Clone)]
        pub struct Config {
            // if a license_template_path has been specified, successfully read, parsed and compiled
            // into a regex, it will be stored here
            pub license_template: Option<Regex>,
            // For each config item, we store a bool indicating whether it has
            // been accessed and the value, and a bool whether the option was
            // manually initialised, or taken from the default,
            $($i: (Cell<bool>, bool, $ty, bool)),+
        }

        // Just like the Config struct but with each property wrapped
        // as Option<T>. This is used to parse a rustfmt.toml that doesn't
        // specify all properties of `Config`.
        // We first parse into `PartialConfig`, then create a default `Config`
        // and overwrite the properties with corresponding values from `PartialConfig`.
        #[derive(Deserialize, Serialize, Clone)]
        pub struct PartialConfig {
            $(pub $i: Option<$ty>),+
        }

        impl PartialConfig {
            pub fn to_toml(&self) -> Result<String, String> {
                // Non-user-facing options can't be specified in TOML
                let mut cloned = self.clone();
                cloned.file_lines = None;
                cloned.verbose = None;
                cloned.width_heuristics = None;

                ::toml::to_string(&cloned)
                    .map_err(|e| format!("Could not output config: {}", e.to_string()))
            }
        }

        // Macro hygiene won't allow us to make `set_$i()` methods on Config
        // for each item, so this struct is used to give the API to set values:
        // `config.set().option(false)`. It's pretty ugly. Consider replacing
        // with `config.set_option(false)` if we ever get a stable/usable
        // `concat_idents!()`.
        pub struct ConfigSetter<'a>(&'a mut Config);

        impl<'a> ConfigSetter<'a> {
            $(
            pub fn $i(&mut self, value: $ty) {
                (self.0).$i.2 = value;
                match stringify!($i) {
                    "use_small_heuristics" => self.0.set_heuristics(),
                    "license_template_path" => self.0.set_license_template(),
                    &_ => (),
                }
            }
            )+
        }

        // Query each option, returns true if the user set the option, false if
        // a default was used.
        pub struct ConfigWasSet<'a>(&'a Config);

        impl<'a> ConfigWasSet<'a> {
            $(
            pub fn $i(&self) -> bool {
                (self.0).$i.1
            }
            )+
        }

        impl Config {
            pub fn version_meets_requirement(&self, error_summary: &mut Summary) -> bool {
                if self.was_set().required_version() {
                    let version = env!("CARGO_PKG_VERSION");
                    let required_version = self.required_version();
                    if version != required_version {
                        println!(
                            "Error: rustfmt version ({}) doesn't match the required version ({})",
                            version,
                            required_version,
                        );
                        error_summary.add_formatting_error();
                        return false;
                    }
                }

                true
            }

            $(
            pub fn $i(&self) -> $ty {
                self.$i.0.set(true);
                self.$i.2.clone()
            }
            )+

            pub fn set<'a>(&'a mut self) -> ConfigSetter<'a> {
                ConfigSetter(self)
            }

            pub fn was_set<'a>(&'a self) -> ConfigWasSet<'a> {
                ConfigWasSet(self)
            }

            fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config {
            $(
                if let Some(val) = parsed.$i {
                    if self.$i.3 {
                        self.$i.1 = true;
                        self.$i.2 = val;
                    } else {
                        if is_nightly_channel!() {
                            self.$i.1 = true;
                            self.$i.2 = val;
                        } else {
                            eprintln!("Warning: can't set `{} = {:?}`, unstable features are only \
                                       available in nightly channel.", stringify!($i), val);
                        }
                    }
                }
            )+
                self.set_heuristics();
                self.set_license_template();
                self
            }

            /// Returns a hash set initialized with every user-facing config option name.
            pub fn hash_set() -> HashSet<String> {
                let mut hash_set = HashSet::new();
                $(
                    hash_set.insert(stringify!($i).to_owned());
                )+
                hash_set
            }

            pub fn is_valid_name(name: &str) -> bool {
                match name {
                    $(
                        stringify!($i) => true,
                    )+
                        _ => false,
                }
            }

            pub fn from_toml(toml: &str) -> Result<Config, String> {
                let parsed: ::toml::Value =
                    toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?;
                let mut err: String = String::new();
                {
                    let table = parsed
                        .as_table()
                        .ok_or(String::from("Parsed config was not table"))?;
                    for key in table.keys() {
                        if !Config::is_valid_name(key) {
                            let msg = &format!("Warning: Unknown configuration option `{}`\n", key);
                            err.push_str(msg)
                        }
                    }
                }
                match parsed.try_into() {
                    Ok(parsed_config) => {
                        if !err.is_empty() {
                            eprint!("{}", err);
                        }
                        Ok(Config::default().fill_from_parsed_config(parsed_config))
                    }
                    Err(e) => {
                        err.push_str("Error: Decoding config file failed:\n");
                        err.push_str(format!("{}\n", e).as_str());
                        err.push_str("Please check your config file.");
                        Err(err)
                    }
                }
            }

            pub fn used_options(&self) -> PartialConfig {
                PartialConfig {
                    $(
                        $i: if self.$i.0.get() {
                                Some(self.$i.2.clone())
                            } else {
                                None
                            },
                    )+
                }
            }

            pub fn all_options(&self) -> PartialConfig {
                PartialConfig {
                    $(
                        $i: Some(self.$i.2.clone()),
                    )+
                }
            }

            pub fn override_value(&mut self, key: &str, val: &str)
            {
                match key {
                    $(
                        stringify!($i) => {
                            self.$i.2 = val.parse::<$ty>()
                                .expect(&format!("Failed to parse override for {} (\"{}\") as a {}",
                                                 stringify!($i),
                                                 val,
                                                 stringify!($ty)));
                        }
                    )+
                    _ => panic!("Unknown config key in override: {}", key)
                }

                match key {
                    "use_small_heuristics" => self.set_heuristics(),
                    "license_template_path" => self.set_license_template(),
                    &_ => (),
                }
            }

            /// Construct a `Config` from the toml file specified at `file_path`.
            ///
            /// This method only looks at the provided path, for a method that
            /// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`.
            ///
            /// Return a `Config` if the config could be read and parsed from
            /// the file, Error otherwise.
            pub fn from_toml_path(file_path: &Path) -> Result<Config, Error> {
                let mut file = File::open(&file_path)?;
                let mut toml = String::new();
                file.read_to_string(&mut toml)?;
                Config::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err))
            }

            /// Resolve the config for input in `dir`.
            ///
            /// Searches for `rustfmt.toml` beginning with `dir`, and
            /// recursively checking parents of `dir` if no config file is found.
            /// If no config file exists in `dir` or in any parent, a
            /// default `Config` will be returned (and the returned path will be empty).
            ///
            /// Returns the `Config` to use, and the path of the project file if there was
            /// one.
            pub fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option<PathBuf>), Error> {

                /// Try to find a project file in the given directory and its parents.
                /// Returns the path of a the nearest project file if one exists,
                /// or `None` if no project file was found.
                fn resolve_project_file(dir: &Path) -> Result<Option<PathBuf>, Error> {
                    let mut current = if dir.is_relative() {
                        env::current_dir()?.join(dir)
                    } else {
                        dir.to_path_buf()
                    };

                    current = fs::canonicalize(current)?;

                    loop {
                        match get_toml_path(&current) {
                            Ok(Some(path)) => return Ok(Some(path)),
                            Err(e) => return Err(e),
                            _ => ()
                        }

                        // If the current directory has no parent, we're done searching.
                        if !current.pop() {
                            return Ok(None);
                        }
                    }
                }

                match resolve_project_file(dir)? {
                    None => Ok((Config::default(), None)),
                    Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))),
                }
            }

            pub fn is_hidden_option(name: &str) -> bool {
                const HIDE_OPTIONS: [&str; 3] = ["verbose", "file_lines", "width_heuristics"];
                HIDE_OPTIONS.contains(&name)
            }

            pub fn print_docs() {
                use std::cmp;
                let max = 0;
                $( let max = cmp::max(max, stringify!($i).len()+1); )+
                let mut space_str = String::with_capacity(max);
                for _ in 0..max {
                    space_str.push(' ');
                }
                println!("Configuration Options:");
                $(
                    let name_raw = stringify!($i);

                    if !Config::is_hidden_option(name_raw) {
                        let mut name_out = String::with_capacity(max);
                        for _ in name_raw.len()..max-1 {
                            name_out.push(' ')
                        }
                        name_out.push_str(name_raw);
                        name_out.push(' ');
                        println!("{}{} Default: {:?}",
                                name_out,
                                <$ty>::doc_hint(),
                                $def);
                        $(
                            println!("{}{}", space_str, $dstring);
                        )+
                        println!();
                    }
                )+
            }

            fn set_heuristics(&mut self) {
                if self.use_small_heuristics.2 {
                    let max_width = self.max_width.2;
                    self.set().width_heuristics(WidthHeuristics::scaled(max_width));
                } else {
                    self.set().width_heuristics(WidthHeuristics::null());
                }
            }

            fn set_license_template(&mut self) {
                if self.was_set().license_template_path() {
                    let license_template_path = self.license_template_path();
                    let mut license_template_file = match File::open(&license_template_path) {
                        Ok(file) => file,
                        Err(e) => {
                            eprintln!("Warning: unable to open license template file {:?}: {}",
                                      license_template_path, e);
                            return;
                        }
                    };
                    let mut license_template_str = String::new();
                    if let Err(e) = license_template_file.read_to_string(&mut license_template_str) {
                        eprintln!("Warning: unable to read from license template file {:?}: {}",
                                  license_template_path, e);
                        return;
                    };
                    let license_template_parsed = match TemplateParser::parse(&license_template_str) {
                        Ok(string) => string,
                        Err(e) => {
                            eprintln!("Warning: unable to parse license template file {:?}: {}",
                                      license_template_path, e);
                            return;
                        }
                    };
                    self.license_template = match Regex::new(&license_template_parsed) {
                        Ok(re) => Some(re),
                        Err(e) => {
                            eprintln!("Warning: regex syntax error in placeholder, unable to compile \
                                       license template from file {:?}: {}", license_template_path, e);
                            return;
                        }
                    }
                }
            }
        }

        // Template for the default configuration
        impl Default for Config {
            fn default() -> Config {
                Config {
                    license_template: None,
                    $(
                        $i: (Cell::new(false), false, $def, $stb),
                    )+
                }
            }
        }
    )
}
<|endoftext|>


<commit_before>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) whitequark <whitequark@whitequark.org>
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
extern crate fringe;

use fringe::{Stack, SliceStack, OwnedStack, OsStack};
use fringe::generator::{Generator, Yielder};

fn add_one_fn<S: Stack>(yielder: &mut Yielder<i32, i32, S>, mut input: i32) {
  loop {
    if input == 0 { break }
    input = yielder.suspend(input + 1)
  }
}

fn new_add_one() -> Generator<i32, i32, OsStack> {
  let stack = OsStack::new(0).unwrap();
  Generator::new(stack, add_one_fn)
}

#[test]
fn generator() {
  let mut add_one = new_add_one();
  assert_eq!(add_one.resume(1), Some(2));
  assert_eq!(add_one.resume(2), Some(3));
  assert_eq!(add_one.resume(0), None);
}

#[test]
fn move_after_new() {
  let mut add_one = new_add_one();
  assert_eq!(add_one.resume(1), Some(2));

  #[inline(never)]
  fn run_moved(mut add_one: Generator<i32, i32, OsStack>) {
    assert_eq!(add_one.resume(2), Some(3));
    assert_eq!(add_one.resume(3), Some(4));
    assert_eq!(add_one.resume(0), None);
  }
  run_moved(add_one);
}

#[test]
#[should_panic]
fn panic_safety() {
  struct Wrapper {
    gen: Generator<(), (), OsStack>
  }

  impl Drop for Wrapper {
    fn drop(&mut self) {
      self.gen.resume(());
    }
  }

  let stack = OsStack::new(4 << 20).unwrap();
  let gen = Generator::new(stack, move |_yielder, ()| {
    panic!("foo")
  });

  let mut wrapper = Wrapper { gen: gen };
  wrapper.gen.resume(());
}

#[test]
fn with_slice_stack() {
  let mut memory = [0; 1024];
  let stack = SliceStack(&mut memory);
  let mut add_one = unsafe { Generator::unsafe_new(stack, add_one_fn) };
  assert_eq!(add_one.resume(1), Some(2));
  assert_eq!(add_one.resume(2), Some(3));
}

#[test]
fn with_owned_stack() {
  let stack = OwnedStack::new(1024);
  let mut add_one = unsafe { Generator::unsafe_new(stack, add_one_fn) };
  assert_eq!(add_one.resume(1), Some(2));
  assert_eq!(add_one.resume(2), Some(3));
}
<commit_msg>add regression test for #31<commit_after>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) whitequark <whitequark@whitequark.org>,
//               edef <edef@edef.eu>
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
extern crate fringe;

use fringe::{Stack, SliceStack, OwnedStack, OsStack};
use fringe::generator::{Generator, Yielder};

fn add_one_fn<S: Stack>(yielder: &mut Yielder<i32, i32, S>, mut input: i32) {
  loop {
    if input == 0 { break }
    input = yielder.suspend(input + 1)
  }
}

fn new_add_one() -> Generator<i32, i32, OsStack> {
  let stack = OsStack::new(0).unwrap();
  Generator::new(stack, add_one_fn)
}

#[test]
fn generator() {
  let mut add_one = new_add_one();
  assert_eq!(add_one.resume(1), Some(2));
  assert_eq!(add_one.resume(2), Some(3));
  assert_eq!(add_one.resume(0), None);
}

#[test]
fn move_after_new() {
  let mut add_one = new_add_one();
  assert_eq!(add_one.resume(1), Some(2));

  #[inline(never)]
  fn run_moved(mut add_one: Generator<i32, i32, OsStack>) {
    assert_eq!(add_one.resume(2), Some(3));
    assert_eq!(add_one.resume(3), Some(4));
    assert_eq!(add_one.resume(0), None);
  }
  run_moved(add_one);
}

#[test]
#[should_panic]
fn panic_safety() {
  struct Wrapper {
    gen: Generator<(), (), OsStack>
  }

  impl Drop for Wrapper {
    fn drop(&mut self) {
      self.gen.resume(());
    }
  }

  let stack = OsStack::new(4 << 20).unwrap();
  let gen = Generator::new(stack, move |_yielder, ()| {
    panic!("foo")
  });

  let mut wrapper = Wrapper { gen: gen };
  wrapper.gen.resume(());
}

#[test]
fn with_slice_stack() {
  let mut memory = [0; 1024];
  let stack = SliceStack(&mut memory);
  let mut add_one = unsafe { Generator::unsafe_new(stack, add_one_fn) };
  assert_eq!(add_one.resume(1), Some(2));
  assert_eq!(add_one.resume(2), Some(3));
}

#[test]
fn with_owned_stack() {
  let stack = OwnedStack::new(1024);
  let mut add_one = unsafe { Generator::unsafe_new(stack, add_one_fn) };
  assert_eq!(add_one.resume(1), Some(2));
  assert_eq!(add_one.resume(2), Some(3));
}

#[test]
fn forget_yielded() {
  struct Dropper(*mut bool);

  unsafe impl Send for Dropper {}

  impl Drop for Dropper {
    fn drop(&mut self) {
      unsafe {
        if *self.0 {
          panic!("double drop!")
        }
        *self.0 = true;
      }
    }
  }

  let stack = fringe::OsStack::new(1<<16).unwrap();
  let mut generator = Generator::new(stack, |yielder, ()| {
    let mut flag = false;
    yielder.suspend(Dropper(&mut flag as *mut bool));
  });
  generator.resume(());
  generator.resume(());
}
<|endoftext|>


<commit_before>use super::{InlineAsmArch, InlineAsmType};
use rustc_macros::HashStable_Generic;

def_reg_class! {
    Nvptx NvptxInlineAsmRegClass {
        reg16,
        reg32,
        reg64,
    }
}

impl NvptxInlineAsmRegClass {
    pub fn valid_modifiers(self, _arch: InlineAsmArch) -> &'static [char] {
        &[]
    }

    pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
        None
    }

    pub fn suggest_modifier(
        self,
        _arch: InlineAsmArch,
        _ty: InlineAsmType,
    ) -> Option<(char, &'static str)> {
        None
    }

    pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
        None
    }

    pub fn supported_types(
        self,
        _arch: InlineAsmArch,
    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
        match self {
            Self::reg16 => types! { _: I8, I16; },
            Self::reg32 => types! { _: I8, I16, I32, F32; },
            Self::reg64 => types! { _: I8, I16, I32, F32, I64, F64; },
        }
    }
}

def_regs! {
    Nvptx NvptxInlineAsmReg NvptxInlineAsmRegClass {}
}
<commit_msg>Added comment on there being no predefined registers<commit_after>use super::{InlineAsmArch, InlineAsmType};
use rustc_macros::HashStable_Generic;

def_reg_class! {
    Nvptx NvptxInlineAsmRegClass {
        reg16,
        reg32,
        reg64,
    }
}

impl NvptxInlineAsmRegClass {
    pub fn valid_modifiers(self, _arch: InlineAsmArch) -> &'static [char] {
        &[]
    }

    pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
        None
    }

    pub fn suggest_modifier(
        self,
        _arch: InlineAsmArch,
        _ty: InlineAsmType,
    ) -> Option<(char, &'static str)> {
        None
    }

    pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
        None
    }

    pub fn supported_types(
        self,
        _arch: InlineAsmArch,
    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
        match self {
            Self::reg16 => types! { _: I8, I16; },
            Self::reg32 => types! { _: I8, I16, I32, F32; },
            Self::reg64 => types! { _: I8, I16, I32, F32, I64, F64; },
        }
    }
}

def_regs! {
    // Registers in PTX are declared in the assembly.
    // There are no predefined registers that one can use.
    Nvptx NvptxInlineAsmReg NvptxInlineAsmRegClass {}
}
<|endoftext|>


<commit_before>// Note: More specifically this lint is largely inspired (aka copied) from
// *rustc*'s
// [`missing_doc`].
//
// [`missing_doc`]: https://github.com/rust-lang/rust/blob/d6d05904697d89099b55da3331155392f1db9c00/src/librustc_lint/builtin.rs#L246
//

use crate::utils::{in_macro, span_lint};
use rustc::hir;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
use rustc::ty;
use rustc::{declare_tool_lint, lint_array};
use syntax::ast;
use syntax::attr;
use syntax::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Warns if there is missing doc for any documentable item
    /// (public or private).
    ///
    /// **Why is this bad?** Doc is good. *rustc* has a `MISSING_DOCS`
    /// allowed-by-default lint for
    /// public members, but has no way to enforce documentation of private items.
    /// This lint fixes that.
    ///
    /// **Known problems:** None.
    pub MISSING_DOCS_IN_PRIVATE_ITEMS,
    restriction,
    "detects missing documentation for public and private members"
}

pub struct MissingDoc {
    /// Stack of whether #[doc(hidden)] is set
    /// at each level which has lint attributes.
    doc_hidden_stack: Vec<bool>,
}

impl ::std::default::Default for MissingDoc {
    fn default() -> Self {
        Self::new()
    }
}

impl MissingDoc {
    pub fn new() -> Self {
        Self {
            doc_hidden_stack: vec![false],
        }
    }

    fn doc_hidden(&self) -> bool {
        *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
    }

    fn check_missing_docs_attrs(
        &self,
        cx: &LateContext<'_, '_>,
        attrs: &[ast::Attribute],
        sp: Span,
        desc: &'static str,
    ) {
        // If we're building a test harness, then warning about
        // documentation is probably not really relevant right now.
        if cx.sess().opts.test {
            return;
        }

        // `#[doc(hidden)]` disables missing_docs check.
        if self.doc_hidden() {
            return;
        }

        if in_macro(sp) {
            return;
        }

        let has_doc = attrs.iter().any(|a| a.is_value_str() && a.name() == "doc");
        if !has_doc {
            span_lint(
                cx,
                MISSING_DOCS_IN_PRIVATE_ITEMS,
                sp,
                &format!("missing documentation for {}", desc),
            );
        }
    }
}

impl LintPass for MissingDoc {
    fn get_lints(&self) -> LintArray {
        lint_array![MISSING_DOCS_IN_PRIVATE_ITEMS]
    }

    fn name(&self) -> &'static str {
        "MissingDoc"
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
    fn enter_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, attrs: &'tcx [ast::Attribute]) {
        let doc_hidden = self.doc_hidden()
            || attrs.iter().any(|attr| {
                attr.check_name("doc")
                    && match attr.meta_item_list() {
                        None => false,
                        Some(l) => attr::list_contains_name(&l[..], "hidden"),
                    }
            });
        self.doc_hidden_stack.push(doc_hidden);
    }

    fn exit_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx [ast::Attribute]) {
        self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
    }

    fn check_crate(&mut self, cx: &LateContext<'a, 'tcx>, krate: &'tcx hir::Crate) {
        self.check_missing_docs_attrs(cx, &krate.attrs, krate.span, "crate");
    }

    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item) {
        let desc = match it.node {
            hir::ItemKind::Const(..) => "a constant",
            hir::ItemKind::Enum(..) => "an enum",
            hir::ItemKind::Fn(..) => {
                // ignore main()
                if it.ident.name == "main" {
                    let def_id = cx.tcx.hir().local_def_id_from_hir_id(it.hir_id);
                    let def_key = cx.tcx.hir().def_key(def_id);
                    if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) {
                        return;
                    }
                }
                "a function"
            },
            hir::ItemKind::Mod(..) => "a module",
            hir::ItemKind::Static(..) => "a static",
            hir::ItemKind::Struct(..) => "a struct",
            hir::ItemKind::Trait(..) => "a trait",
            hir::ItemKind::TraitAlias(..) => "a trait alias",
            hir::ItemKind::Ty(..) => "a type alias",
            hir::ItemKind::Union(..) => "a union",
            hir::ItemKind::Existential(..) => "an existential type",
            hir::ItemKind::ExternCrate(..)
            | hir::ItemKind::ForeignMod(..)
            | hir::ItemKind::GlobalAsm(..)
            | hir::ItemKind::Impl(..)
            | hir::ItemKind::Use(..) => return,
        };

        self.check_missing_docs_attrs(cx, &it.attrs, it.span, desc);
    }

    fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, trait_item: &'tcx hir::TraitItem) {
        let desc = match trait_item.node {
            hir::TraitItemKind::Const(..) => "an associated constant",
            hir::TraitItemKind::Method(..) => "a trait method",
            hir::TraitItemKind::Type(..) => "an associated type",
        };

        self.check_missing_docs_attrs(cx, &trait_item.attrs, trait_item.span, desc);
    }

    fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem) {
        // If the method is an impl for a trait, don't doc.
        let def_id = cx.tcx.hir().local_def_id_from_hir_id(impl_item.hir_id);
        match cx.tcx.associated_item(def_id).container {
            ty::TraitContainer(_) => return,
            ty::ImplContainer(cid) => {
                if cx.tcx.impl_trait_ref(cid).is_some() {
                    return;
                }
            },
        }

        let desc = match impl_item.node {
            hir::ImplItemKind::Const(..) => "an associated constant",
            hir::ImplItemKind::Method(..) => "a method",
            hir::ImplItemKind::Type(_) => "an associated type",
            hir::ImplItemKind::Existential(_) => "an existential type",
        };
        self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc);
    }

    fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, sf: &'tcx hir::StructField) {
        if !sf.is_positional() {
            self.check_missing_docs_attrs(cx, &sf.attrs, sf.span, "a struct field");
        }
    }

    fn check_variant(&mut self, cx: &LateContext<'a, 'tcx>, v: &'tcx hir::Variant, _: &hir::Generics) {
        self.check_missing_docs_attrs(cx, &v.node.attrs, v.span, "a variant");
    }
}
<commit_msg>Add `doc(include = ...)` detection to `missing_docs_in_private_items`<commit_after>// Note: More specifically this lint is largely inspired (aka copied) from
// *rustc*'s
// [`missing_doc`].
//
// [`missing_doc`]: https://github.com/rust-lang/rust/blob/d6d05904697d89099b55da3331155392f1db9c00/src/librustc_lint/builtin.rs#L246
//

use crate::utils::{in_macro, span_lint};
use if_chain::if_chain;
use rustc::hir;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
use rustc::ty;
use rustc::{declare_tool_lint, lint_array};
use syntax::ast::{self, MetaItem, MetaItemKind};
use syntax::attr;
use syntax::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Warns if there is missing doc for any documentable item
    /// (public or private).
    ///
    /// **Why is this bad?** Doc is good. *rustc* has a `MISSING_DOCS`
    /// allowed-by-default lint for
    /// public members, but has no way to enforce documentation of private items.
    /// This lint fixes that.
    ///
    /// **Known problems:** None.
    pub MISSING_DOCS_IN_PRIVATE_ITEMS,
    restriction,
    "detects missing documentation for public and private members"
}

pub struct MissingDoc {
    /// Stack of whether #[doc(hidden)] is set
    /// at each level which has lint attributes.
    doc_hidden_stack: Vec<bool>,
}

impl ::std::default::Default for MissingDoc {
    fn default() -> Self {
        Self::new()
    }
}

impl MissingDoc {
    pub fn new() -> Self {
        Self {
            doc_hidden_stack: vec![false],
        }
    }

    fn doc_hidden(&self) -> bool {
        *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
    }

    #[allow(clippy::needless_bool)]
    fn has_include(meta: Option<MetaItem>) -> bool {
        if_chain! {
            if let Some(meta) = meta;
            if let MetaItemKind::List(list) = meta.node;
            if let Some(meta) = list.get(0);
            if let Some(name) = meta.name();
            if name == "include";
            then {
                true
            } else {
                false
            }
        }
    }

    fn check_missing_docs_attrs(
        &self,
        cx: &LateContext<'_, '_>,
        attrs: &[ast::Attribute],
        sp: Span,
        desc: &'static str,
    ) {
        // If we're building a test harness, then warning about
        // documentation is probably not really relevant right now.
        if cx.sess().opts.test {
            return;
        }

        // `#[doc(hidden)]` disables missing_docs check.
        if self.doc_hidden() {
            return;
        }

        if in_macro(sp) {
            return;
        }

        let has_doc = attrs
            .iter()
            .any(|a| a.name() == "doc" && (a.is_value_str() || Self::has_include(a.meta())));
        if !has_doc {
            span_lint(
                cx,
                MISSING_DOCS_IN_PRIVATE_ITEMS,
                sp,
                &format!("missing documentation for {}", desc),
            );
        }
    }
}

impl LintPass for MissingDoc {
    fn get_lints(&self) -> LintArray {
        lint_array![MISSING_DOCS_IN_PRIVATE_ITEMS]
    }

    fn name(&self) -> &'static str {
        "MissingDoc"
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
    fn enter_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, attrs: &'tcx [ast::Attribute]) {
        let doc_hidden = self.doc_hidden()
            || attrs.iter().any(|attr| {
                attr.check_name("doc")
                    && match attr.meta_item_list() {
                        None => false,
                        Some(l) => attr::list_contains_name(&l[..], "hidden"),
                    }
            });
        self.doc_hidden_stack.push(doc_hidden);
    }

    fn exit_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx [ast::Attribute]) {
        self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
    }

    fn check_crate(&mut self, cx: &LateContext<'a, 'tcx>, krate: &'tcx hir::Crate) {
        self.check_missing_docs_attrs(cx, &krate.attrs, krate.span, "crate");
    }

    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item) {
        let desc = match it.node {
            hir::ItemKind::Const(..) => "a constant",
            hir::ItemKind::Enum(..) => "an enum",
            hir::ItemKind::Fn(..) => {
                // ignore main()
                if it.ident.name == "main" {
                    let def_id = cx.tcx.hir().local_def_id_from_hir_id(it.hir_id);
                    let def_key = cx.tcx.hir().def_key(def_id);
                    if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) {
                        return;
                    }
                }
                "a function"
            },
            hir::ItemKind::Mod(..) => "a module",
            hir::ItemKind::Static(..) => "a static",
            hir::ItemKind::Struct(..) => "a struct",
            hir::ItemKind::Trait(..) => "a trait",
            hir::ItemKind::TraitAlias(..) => "a trait alias",
            hir::ItemKind::Ty(..) => "a type alias",
            hir::ItemKind::Union(..) => "a union",
            hir::ItemKind::Existential(..) => "an existential type",
            hir::ItemKind::ExternCrate(..)
            | hir::ItemKind::ForeignMod(..)
            | hir::ItemKind::GlobalAsm(..)
            | hir::ItemKind::Impl(..)
            | hir::ItemKind::Use(..) => return,
        };

        self.check_missing_docs_attrs(cx, &it.attrs, it.span, desc);
    }

    fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, trait_item: &'tcx hir::TraitItem) {
        let desc = match trait_item.node {
            hir::TraitItemKind::Const(..) => "an associated constant",
            hir::TraitItemKind::Method(..) => "a trait method",
            hir::TraitItemKind::Type(..) => "an associated type",
        };

        self.check_missing_docs_attrs(cx, &trait_item.attrs, trait_item.span, desc);
    }

    fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem) {
        // If the method is an impl for a trait, don't doc.
        let def_id = cx.tcx.hir().local_def_id_from_hir_id(impl_item.hir_id);
        match cx.tcx.associated_item(def_id).container {
            ty::TraitContainer(_) => return,
            ty::ImplContainer(cid) => {
                if cx.tcx.impl_trait_ref(cid).is_some() {
                    return;
                }
            },
        }

        let desc = match impl_item.node {
            hir::ImplItemKind::Const(..) => "an associated constant",
            hir::ImplItemKind::Method(..) => "a method",
            hir::ImplItemKind::Type(_) => "an associated type",
            hir::ImplItemKind::Existential(_) => "an existential type",
        };
        self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc);
    }

    fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, sf: &'tcx hir::StructField) {
        if !sf.is_positional() {
            self.check_missing_docs_attrs(cx, &sf.attrs, sf.span, "a struct field");
        }
    }

    fn check_variant(&mut self, cx: &LateContext<'a, 'tcx>, v: &'tcx hir::Variant, _: &hir::Generics) {
        self.check_missing_docs_attrs(cx, &v.node.attrs, v.span, "a variant");
    }
}
<|endoftext|>


<commit_before>//! Functions to read and write control registers.

/// A model specific register.
pub struct Msr(u32);

impl Msr {
    /// Create an instance from a register.
    pub const fn new(reg: u32) -> Msr {
        Msr(reg)
    }

    /// Read 64 bits msr register.
    pub unsafe fn read(&self) -> u64 {
        let (high, low): (u32, u32);
        asm!("rdmsr" : "={eax}" (low), "={edx}" (high) : "{ecx}" (self.0) : "memory" : "volatile");
        ((high as u64) << 32) | (low as u64)
    }

    /// Write 64 bits to msr register.
    pub unsafe fn write(&mut self, value: u64) {
        let low = value as u32;
        let high = (value >> 32) as u32;
        asm!("wrmsr" :: "{ecx}" (self.0), "{eax}" (low), "{edx}" (high) : "memory" : "volatile" );
    }
}

/// The Extended Feature Enable Register.
pub struct Efer;

impl Efer {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC0000080);

    /// Read the current EFER flags.
    pub fn read() -> EferFlags {
        EferFlags::from_bits_truncate(Self::read_raw())
    }

    /// Read the current raw EFER flags.
    pub fn read_raw() -> u64 {
        unsafe { Self::MSR.read() }
    }

    /// Write the EFER flags, preserving reserved values.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to break memory
    /// safety, e.g. by disabling long mode.
    pub unsafe fn write(flags: EferFlags) {
        let old_value = Self::read_raw();
        let reserved = old_value & !(EferFlags::all().bits());
        let new_value = reserved | flags.bits();

        Self::write_raw(new_value);
    }

    /// Write the EFER flags.
    ///
    /// Does not preserve any bits, including reserved fields. Unsafe because it's possible to
    /// break memory safety, e.g. by disabling long mode.
    pub unsafe fn write_raw(flags: u64) {
        Self::MSR.write(flags);
    }

    /// Update EFER flags.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to break memory
    /// safety, e.g. by disabling long mode.
    pub unsafe fn update<F>(f: F)
    where
        F: FnOnce(&mut EferFlags),
    {
        let mut flags = Self::read();
        f(&mut flags);
        Self::write(flags);
    }
}

bitflags! {
    pub struct EferFlags: u64 {
        const SYSTEM_CALL_EXTENSIONS = 1 << 0;
        const LONG_MODE_ENABLE = 1 << 8;
        const LONG_MODE_ACTIVE = 1 << 10;
        const NO_EXECUTE_ENABLE = 1 << 11;
        const SECURE_VIRTUAL_MACHINE_ENABLE = 1 << 12;
        const LONG_MODE_SEGMENT_LIMIT_ENABLE = 1 << 13;
        const FAST_FXSAVE_FXRSTOR = 1 << 14;
        const TRANSLATION_CACHE_EXTENSION = 1 << 15;
    }
}
<commit_msg>Document EFER flags<commit_after>//! Functions to read and write control registers.

/// A model specific register.
pub struct Msr(u32);

impl Msr {
    /// Create an instance from a register.
    pub const fn new(reg: u32) -> Msr {
        Msr(reg)
    }

    /// Read 64 bits msr register.
    pub unsafe fn read(&self) -> u64 {
        let (high, low): (u32, u32);
        asm!("rdmsr" : "={eax}" (low), "={edx}" (high) : "{ecx}" (self.0) : "memory" : "volatile");
        ((high as u64) << 32) | (low as u64)
    }

    /// Write 64 bits to msr register.
    pub unsafe fn write(&mut self, value: u64) {
        let low = value as u32;
        let high = (value >> 32) as u32;
        asm!("wrmsr" :: "{ecx}" (self.0), "{eax}" (low), "{edx}" (high) : "memory" : "volatile" );
    }
}

/// The Extended Feature Enable Register.
pub struct Efer;

impl Efer {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC0000080);

    /// Read the current EFER flags.
    pub fn read() -> EferFlags {
        EferFlags::from_bits_truncate(Self::read_raw())
    }

    /// Read the current raw EFER flags.
    pub fn read_raw() -> u64 {
        unsafe { Self::MSR.read() }
    }

    /// Write the EFER flags, preserving reserved values.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to break memory
    /// safety, e.g. by disabling long mode.
    pub unsafe fn write(flags: EferFlags) {
        let old_value = Self::read_raw();
        let reserved = old_value & !(EferFlags::all().bits());
        let new_value = reserved | flags.bits();

        Self::write_raw(new_value);
    }

    /// Write the EFER flags.
    ///
    /// Does not preserve any bits, including reserved fields. Unsafe because it's possible to
    /// break memory safety, e.g. by disabling long mode.
    pub unsafe fn write_raw(flags: u64) {
        Self::MSR.write(flags);
    }

    /// Update EFER flags.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to break memory
    /// safety, e.g. by disabling long mode.
    pub unsafe fn update<F>(f: F)
    where
        F: FnOnce(&mut EferFlags),
    {
        let mut flags = Self::read();
        f(&mut flags);
        Self::write(flags);
    }
}

bitflags! {
    /// Flags of the Extended Feature Enable Register.
    pub struct EferFlags: u64 {
        /// Enables the `syscall` and `sysret` instructions.
        const SYSTEM_CALL_EXTENSIONS = 1 << 0;
        /// Activates long mode, requires activating paging.
        const LONG_MODE_ENABLE = 1 << 8;
        /// Indicates that long mode is active.
        const LONG_MODE_ACTIVE = 1 << 10;
        /// Enables the no-execute page-protection feature.
        const NO_EXECUTE_ENABLE = 1 << 11;
        /// Enables SVM extensions.
        const SECURE_VIRTUAL_MACHINE_ENABLE = 1 << 12;
        /// Enable certain limit checks in 64-bit mode.
        const LONG_MODE_SEGMENT_LIMIT_ENABLE = 1 << 13;
        /// Enable the `fxsave` and `fxrstor` instructions to execute faster in 64-bit mode.
        const FAST_FXSAVE_FXRSTOR = 1 << 14;
        /// Changes how the `invlpg` instruction operates on TLB entries of upper-level entries.
        const TRANSLATION_CACHE_EXTENSION = 1 << 15;
    }
}
<|endoftext|>


<commit_before>mod user;
mod pass;
mod pwd;
mod cwd;
mod cdup;
mod list;
mod syst;
mod feat;
mod ty;
mod passive;
mod active;
mod quit;
mod retr;

use {Error, Io};
use {server, protocol};

/// Handles a command sent to a server from a client.
pub fn command(client: &mut server::Client,
               command: &protocol::CommandKind,
               ftp: &mut server::FileTransferProtocol,
               io: &mut Io) -> Result<protocol::Reply, Error> {
    use protocol::CommandKind::*;

    println!("received {:?}", command);

    match *command {
        // User attempting to log in.
        USER(ref user) => self::user::handle(user, client, ftp),
        PASS(ref pass) => self::pass::handle(pass, client, ftp),
        PWD(..) => self::pwd::handle(client),
        CWD(ref cwd) => self::cwd::handle(cwd, client),
        CDUP(..) => self::cdup::handle(client),
        LIST(ref list) => self::list::handle(list, client, ftp),
        // Client requesting information about the server system.
        SYST(..) => self::syst::handle(),
        FEAT(..) => self::feat::handle(),
        TYPE(ref ty) => self::ty::handle(ty, client),
        PASV(..) => self::passive::handle_pasv(client, io),
        EPSV(..) => self::passive::handle_epsv(client, io),
        PORT(ref port) => self::active::handle_port(port, client),
        QUIT(..) => self::quit::handle(),
        RETR(ref retr) => self::retr::handle(retr, client, ftp),
        ref command => {
            Err(Error::Protocol(protocol::ClientError::UnimplementedCommand {
                name: command.command_name().to_string(),
            }.into()))
        },
    }
}
<commit_msg>Add stub handlers for all command types<commit_after>mod user;
mod pass;
mod pwd;
mod cwd;
mod cdup;
mod list;
mod syst;
mod feat;
mod ty;
mod passive;
mod active;
mod quit;
mod retr;

use {Error, Io};
use {server, protocol};

/// Handles a command sent to a server from a client.
pub fn command(client: &mut server::Client,
               command: &protocol::CommandKind,
               ftp: &mut server::FileTransferProtocol,
               io: &mut Io) -> Result<protocol::Reply, Error> {
    use protocol::CommandKind::*;

    println!("received {:?}", command);

    match *command {
        // User attempting to log in.
        USER(ref user) => self::user::handle(user, client, ftp),
        PASS(ref pass) => self::pass::handle(pass, client, ftp),
        PWD(..) => self::pwd::handle(client),
        CWD(ref cwd) => self::cwd::handle(cwd, client),
        CDUP(..) => self::cdup::handle(client),
        LIST(ref list) => self::list::handle(list, client, ftp),
        // Client requesting information about the server system.
        SYST(..) => self::syst::handle(),
        FEAT(..) => self::feat::handle(),
        TYPE(ref ty) => self::ty::handle(ty, client),
        PASV(..) => self::passive::handle_pasv(client, io),
        EPSV(..) => self::passive::handle_epsv(client, io),
        PORT(ref port) => self::active::handle_port(port, client),
        QUIT(..) => self::quit::handle(),
        RETR(ref retr) => self::retr::handle(retr, client, ftp),
        EPRT(..) => self::unimplemented("EPRT"),
        ABOR(..) => self::unimplemented("ABOR"),
        ACCT(..) => self::unimplemented("ACCT"),
        ADAT(..) => self::unimplemented("ADAT"),
        ALLO(..) => self::unimplemented("ALLO"),
        APPE(..) => self::unimplemented("APPE"),
        AUTH(..) => self::unimplemented("AUTH"),
        CCC(..) => self::unimplemented("CCC"),
        CONF(..) => self::unimplemented("CONF"),
        DELE(..) => self::unimplemented("DELE"),
        ENC(..) => self::unimplemented("ENC"),
        HELP(..) => self::unimplemented("HELP"),
        HOST(..) => self::unimplemented("HOST"),
        LANG(..) => self::unimplemented("LANG"),
        LPRT(..) => self::unimplemented("LPRT"),
        LPSV(..) => self::unimplemented("LPSV"),
        MDTM(..) => self::unimplemented("MDTM"),
        MIC(..) => self::unimplemented("MIC"),
        MKD(..) => self::unimplemented("MKD"),
        MLSD(..) => self::unimplemented("MLSD"),
        MLST(..) => self::unimplemented("MLST"),
        MODE(..) => self::unimplemented("MODE"),
        NLST(..) => self::unimplemented("NLST"),
        NOOP(..) => self::unimplemented("NOOP"),
        OPTS(..) => self::unimplemented("OPTS"),
        PBSZ(..) => self::unimplemented("PBSZ"),
        PROT(..) => self::unimplemented("PROT"),
        REIN(..) => self::unimplemented("REIN"),
        REST(..) => self::unimplemented("REST"),
        RMD(..) => self::unimplemented("RMD"),
        RNFR(..) => self::unimplemented("RNFR"),
        RNTO(..) => self::unimplemented("RNTO"),
        SITE(..) => self::unimplemented("SITE"),
        SIZE(..) => self::unimplemented("SIZE"),
        SMNT(..) => self::unimplemented("SMNT"),
        STAT(..) => self::unimplemented("STAT"),
        STOR(..) => self::unimplemented("STOR"),
        STOU(..) => self::unimplemented("STOU"),
        STRU(..) => self::unimplemented("STRU"),
        XCUP(..) => self::unimplemented("XCUP"),
        XMKD(..) => self::unimplemented("XMKD"),
        XPWD(..) => self::unimplemented("XPWD"),
        XRCP(..) => self::unimplemented("XRCP"),
        XRMD(..) => self::unimplemented("XRMD"),
        XRSQ(..) => self::unimplemented("XRSQ"),
        XSEM(..) => self::unimplemented("XSEM"),
        XSEN(..) => self::unimplemented("XSEN"),
    }
}

/// Generate a reply for an unimplemented command.
fn unimplemented(command_name: &'static str) -> Result<protocol::Reply, Error> {
    Err(Error::Protocol(protocol::ClientError::UnimplementedCommand {
        name: command_name.to_string(),
    }.into()))
}
<|endoftext|>