<commit_before>use std::ops;
use std::num::ToPrimitive;
use std::cmp::Ordering;

use index::Index;

#[derive(Clone, Debug, PartialOrd, PartialEq)]
pub enum Value {
    Bool(bool),
    String(String),
    Float(f64),
    Tuple(Tuple),
    Relation(Relation),
}
pub type Tuple = Vec<Value>;
pub type Relation = Index<Vec<Value>>; // a set of tuples
pub type Id = String; // TODO use uuid?

impl Ord for Value {
    fn cmp(&self, other: &Value) -> Ordering {
        self.partial_cmp(other).unwrap() // TODO this will panic on NaN
    }
}

impl Eq for Value {} // TODO this is unsafe for NaN

impl ops::Index<usize> for Value {
    type Output = Value;

    fn index(&self, index: usize) -> &Value {
        match *self {
            Value::Tuple(ref tuple) => tuple.index(index),
            _ => panic!("Indexing a non-tuple value"),
        }
    }
}

impl ToPrimitive for Value {
    fn to_f64(&self) -> Option<f64> {
        match *self {
            Value::Float(ref float) => float.to_f64(),
            _ => None,
        }
    }
    fn to_i64(&self) -> Option<i64> {
        match *self {
            Value::Float(ref float) => float.to_i64(),
            _ => None,
        }
    }
    fn to_u64(&self) -> Option<u64> {
        match *self {
            Value::Float(ref float) => float.to_u64(),
            _ => None,
        }
    }
}

impl Value {
    pub fn as_str(&self) -> &str {
        match *self {
            Value::String(ref string) => &*string,
            _ => panic!("Not a string: {:?}", self),
        }
    }

    pub fn as_slice(&self) -> &[Value] {
        match *self {
            Value::Tuple(ref tuple) => &*tuple,
            _ => panic!("Not a tuple: {:?}", self),
        }
    }
}<commit_msg>Minor changes to error messages<commit_after>use std::ops;
use std::num::ToPrimitive;
use std::cmp::Ordering;

use index::Index;

#[derive(Clone, Debug, PartialOrd, PartialEq)]
pub enum Value {
    Bool(bool),
    String(String),
    Float(f64),
    Tuple(Tuple),
    Relation(Relation),
}
pub type Tuple = Vec<Value>;
pub type Relation = Index<Vec<Value>>; // a set of tuples
pub type Id = String; // TODO use uuid?

impl Ord for Value {
    fn cmp(&self, other: &Value) -> Ordering {
        self.partial_cmp(other).unwrap() // TODO this will panic on NaN
    }
}

impl Eq for Value {} // TODO this is unsafe for NaN

impl ops::Index<usize> for Value {
    type Output = Value;

    fn index(&self, index: usize) -> &Value {
        match *self {
            Value::Tuple(ref tuple) => tuple.index(index),
            _ => panic!("Cannot index into this non-tuple value: {:?}", self),
        }
    }
}

impl ToPrimitive for Value {
    fn to_f64(&self) -> Option<f64> {
        match *self {
            Value::Float(ref float) => float.to_f64(),
            _ => None,
        }
    }
    fn to_i64(&self) -> Option<i64> {
        match *self {
            Value::Float(ref float) => float.to_i64(),
            _ => None,
        }
    }
    fn to_u64(&self) -> Option<u64> {
        match *self {
            Value::Float(ref float) => float.to_u64(),
            _ => None,
        }
    }
}

impl Value {
    pub fn as_str(&self) -> &str {
        match *self {
            Value::String(ref string) => &*string,
            _ => panic!("Cannot convert this to string: {:?}", self),
        }
    }

    pub fn as_slice(&self) -> &[Value] {
        match *self {
            Value::Tuple(ref tuple) => &*tuple,
            _ => panic!("Cannot convert this to tuple: {:?}", self),
        }
    }
}<|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate rand;
use rand::Rng;

fn one_in(n: f64) -> bool {
    rand::thread_rng().gen_bool(n)
}

#[derive(Debug)]
struct File {
    name: String,
    data: Vec<u8>,
}

impl File {
    fn new(name: &str) -> File {
        File {
            name: String::from(name),
            data: Vec::new(),
        }
    }

    fn new_with_data(name: &str, data: &Vec<u8>) -> File {
        let mut f = File::new(name);
        f.data = data.clone();
        f
    }

    fn read(self: &File, save_to: &mut Vec<u8>) -> Result<usize, String> {
        let mut tmp = self.data.clone();
        let read_length = tmp.len();
        save_to.reserve(read_length);
        save_to.append(&mut tmp);
        Ok(read_length)
    }
}

fn open(f: File) -> Result<File, String> {
    if one_in(1e-1) {
        let err_msg = String::from("Permission denied!");
        return Err(err_msg);
    }
    Ok(f)
}

fn close(f: File) -> Result<File, String> {
    if one_in(1e-2) {
        let err_msg = String::from("Interrupted by signal!");
        return Err(err_msg);
    }
    Ok(f)
}

fn main() {
    let f4_data: Vec<u8> = vec![114, 117, 115, 116, 33];
    let mut f4 = File::new_with_data("4.txt", &f4_data);

    let mut buffer: Vec<u8> = vec![];

    f4 = open(f4).unwrap();
    let f4_length = f4.read(&mut buffer).unwrap();
    f4 = close(f4).unwrap();

    let text = String::from_utf8_lossy(&buffer);

    println!("{:?}", f4);
    println!("{} is {} bytes long", f4.name, f4_length);
    println!("{}", text);
}
<commit_msg>use enum for FileState<commit_after>//#![allow(dead_code)]

//extern crate rand;
//use rand::Rng;
//
//fn one_in(n: f64) -> bool {
//    rand::thread_rng().gen_bool(n)
//}

#[derive(Debug, PartialEq)]
enum FileState {
    Open,
    Closed,
}

#[derive(Debug)]
struct File {
    name: String,
    data: Vec<u8>,
    state: FileState,
}

impl File {
    fn new(name: &str) -> File {
        File {
            name: String::from(name),
            data: Vec::new(),
            state: FileState::Closed,
        }
    }

    fn new_with_data(name: &str, data: &Vec<u8>) -> File {
        let mut f = File::new(name);
        f.data = data.clone();
        f
    }

    fn read(self: &File, save_to: &mut Vec<u8>) -> Result<usize, String> {
        if self.state != FileState::Open {
            return Err(String::from("File must be open for reading"));
        }
        let mut tmp = self.data.clone();
        let read_length = tmp.len();
        save_to.reserve(read_length);
        save_to.append(&mut tmp);
        Ok(read_length)
    }
}

fn open(mut f: File) -> Result<File, String> {
    f.state = FileState::Open;
    Ok(f)
}

fn close(mut f: File) -> Result<File, String> {
    f.state = FileState::Closed;
    Ok(f)
}

fn main() {
    let f5_data: Vec<u8> = vec![114, 117, 115, 116, 33];
    let mut f5 = File::new_with_data("5.txt", &f5_data);

    let mut buffer: Vec<u8> = vec![];

    if f5.read(&mut buffer).is_err() {
        println!("Error checking is working");
    }

    f5 = open(f5).unwrap();
    let f5_length = f5.read(&mut buffer).unwrap();
    f5 = close(f5).unwrap();

    let text = String::from_utf8_lossy(&buffer);

    println!("{:?}", f5);
    println!("{} is {} bytes long", f5.name, f5_length);
    println!("{}", text);
}
<|endoftext|>


<commit_before>use std::{io, fs, env, path::PathBuf};
use crate::spec::{LinkerFlavor, LldFlavor, LinkArgs, RelocModel};
use crate::spec::{Target, TargetOptions, TargetResult};

// The PSP has custom linker requirements.
const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld");

fn write_script() -> io::Result<PathBuf> {
    let path = env::temp_dir().join("rustc-mipsel-sony-psp-linkfile.ld");
    fs::write(&path, LINKER_SCRIPT)?;
    Ok(path)
}

pub fn target() -> TargetResult {
    let script = write_script().map_err(|e| {
        format!("failed to write link script: {}", e)
    })?;

    let mut pre_link_args = LinkArgs::new();
    pre_link_args.insert(
        LinkerFlavor::Lld(LldFlavor::Ld),
        vec![
            "--eh-frame-hdr".to_string(),
            "--emit-relocs".to_string(),
            "--script".to_string(),
            script.display().to_string(),
        ],
    );

    Ok(Target {
        llvm_target: "mipsel-sony-psp".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
        arch: "mips".to_string(),
        target_os: "psp".to_string(),
        target_env: "".to_string(),
        target_vendor: "sony".to_string(),
        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),

        options: TargetOptions {
            cpu: "mips2".to_string(),
            executables: true,
            linker: Some("rust-lld".to_owned()),
            relocation_model: RelocModel::Static,

            // PSP FPU only supports single precision floats.
            features: "+single-float".to_string(),

            // PSP does not support trap-on-condition instructions.
            llvm_args: vec![
                "-mno-check-zero-division".to_string(),
            ],
            pre_link_args,
            ..Default::default()
        },
    })
}
<commit_msg>Formatting<commit_after>use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, RelocModel};
use crate::spec::{Target, TargetOptions, TargetResult};
use std::{env, fs, io, path::PathBuf};

// The PSP has custom linker requirements.
const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld");

fn write_script() -> io::Result<PathBuf> {
    let path = env::temp_dir().join("rustc-mipsel-sony-psp-linkfile.ld");
    fs::write(&path, LINKER_SCRIPT)?;
    Ok(path)
}

pub fn target() -> TargetResult {
    let script = write_script().map_err(|e| format!("failed to write link script: {}", e))?;

    let mut pre_link_args = LinkArgs::new();
    pre_link_args.insert(
        LinkerFlavor::Lld(LldFlavor::Ld),
        vec![
            "--eh-frame-hdr".to_string(),
            "--emit-relocs".to_string(),
            "--script".to_string(),
            script.display().to_string(),
        ],
    );

    Ok(Target {
        llvm_target: "mipsel-sony-psp".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
        arch: "mips".to_string(),
        target_os: "psp".to_string(),
        target_env: "".to_string(),
        target_vendor: "sony".to_string(),
        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),

        options: TargetOptions {
            cpu: "mips2".to_string(),
            executables: true,
            linker: Some("rust-lld".to_owned()),
            relocation_model: RelocModel::Static,

            // PSP FPU only supports single precision floats.
            features: "+single-float".to_string(),

            // PSP does not support trap-on-condition instructions.
            llvm_args: vec!["-mno-check-zero-division".to_string()],
            pre_link_args,
            ..Default::default()
        },
    })
}
<|endoftext|>


<commit_before>use specs::{ReadExpect, ReadStorage, System, WriteStorage};

use crate::combat::components::{Intent, Position, Velocity};

struct Rect {
    x: i32,
    y: i32,
    w: i32,
    h: i32,
}

// TODO: change to be SystemData
const LAIR_BOUNDARY: Rect = Rect {
    x: 0,   //10,
    y: 0,   //30,
    w: 320, // - 10,
    h: 155, // - 30,
};

#[derive(Debug)]
pub struct Boundary {
    pub x: i32,
    pub y: i32,
    pub w: i32,
    pub h: i32,
}

impl Default for Boundary {
    fn default() -> Boundary {
        Boundary {
            x: 0,
            y: 30,
            w: 320,
            h: 150,
        }
    }
}

pub struct RestrictMovementToBoundary;
// takes a velocity and restricts velocity if the resulting movement would
// collide with a boundary

impl<'a> System<'a> for RestrictMovementToBoundary {
    type SystemData = (
        ReadExpect<'a, Boundary>,
        ReadStorage<'a, Position>,
        // anything which can take commands is bounded to the screen.
        // TODO: what happens with off screen (trogg war beasts) enemies?
        ReadStorage<'a, Intent>,
        WriteStorage<'a, Velocity>,
    );
    fn run(&mut self, (top_boundary, position, intent, mut velocity): Self::SystemData) {
        use specs::Join;
        for (position, _, velocity) in (&position, &intent, &mut velocity).join() {
            let new_x = position.x as i32 + velocity.x;
            if new_x < LAIR_BOUNDARY.x && velocity.x < 0
                || new_x > LAIR_BOUNDARY.w && velocity.x > 0
            {
                velocity.x = 0;
            }

            let new_y = position.y as i32 - velocity.y;
            if new_y < top_boundary.y && velocity.y < 0 || new_y > LAIR_BOUNDARY.h && velocity.y > 0
            {
                velocity.y = 0;
            }
        }
    }
}
<commit_msg>Change LAIR_BOUNDARY to SystemData<commit_after>use specs::{ReadExpect, ReadStorage, System, WriteStorage};

use crate::combat::components::{Intent, Position, Velocity};

struct Rect {
    x: i32,
    y: i32,
    w: i32,
    h: i32,
}

#[derive(Debug)]
pub struct Boundary {
    pub x: i32,
    pub y: i32,
    pub w: i32,
    pub h: i32,
}

impl Default for Boundary {
    fn default() -> Boundary {
        Boundary {
            x: 0,
            y: 30,
            w: 320,
            h: 150,
        }
    }
}

pub struct RestrictMovementToBoundary;
// takes a velocity and restricts velocity if the resulting movement would
// collide with a boundary

impl<'a> System<'a> for RestrictMovementToBoundary {
    type SystemData = (
        ReadExpect<'a, Boundary>,
        ReadStorage<'a, Position>,
        // anything which can take commands is bounded to the screen.
        // TODO: what happens with off screen (trogg war beasts) enemies?
        ReadStorage<'a, Intent>,
        WriteStorage<'a, Velocity>,
    );
    fn run(&mut self, (boundary, position, intent, mut velocity): Self::SystemData) {
        use specs::Join;
        for (position, _, velocity) in (&position, &intent, &mut velocity).join() {
            let new_x = position.x as i32 + velocity.x;
            if new_x < boundary.x && velocity.x < 0 || new_x > boundary.w && velocity.x > 0 {
                velocity.x = 0;
            }

            let new_y = position.y as i32 - velocity.y;
            if new_y < boundary.y && velocity.y < 0 || new_y > boundary.h && velocity.y > 0 {
                velocity.y = 0;
            }
        }
    }
}
<|endoftext|>


<commit_before>use actix_http::ResponseBuilder;
use actix_web::{error, get, http::header, http::StatusCode, put, web, HttpResponse};
use anyhow::*;

use crate::config::{self, Config};
use crate::db::DB;
use crate::service::constants::*;
use crate::service::dto;
use crate::service::error::APIError;
use crate::user;

impl error::ResponseError for APIError {
	fn error_response(&self) -> HttpResponse {
		ResponseBuilder::new(self.status_code())
			.set_header(header::CONTENT_TYPE, "text/html; charset=utf-8")
			.body(self.to_string())
	}
	fn status_code(&self) -> StatusCode {
		match *self {
			APIError::IncorrectCredentials => StatusCode::UNAUTHORIZED,
			APIError::Unspecified => StatusCode::INTERNAL_SERVER_ERROR,
		}
	}
}

#[get("/version")]
pub async fn get_version() -> Result<HttpResponse, APIError> {
	let current_version = dto::Version {
		major: CURRENT_MAJOR_VERSION,
		minor: CURRENT_MINOR_VERSION,
	};
	Ok(HttpResponse::Ok().json(current_version))
}

#[get("/initial_setup")]
pub async fn get_initial_setup(db: web::Data<DB>) -> Result<HttpResponse, APIError> {
	let user_count = web::block(move || user::count(&db))
		.await
		.map_err(|_| anyhow!("Could not count users"))?;
	let initial_setup = dto::InitialSetup {
		has_any_users: user_count > 0,
	};
	Ok(HttpResponse::Ok().json(initial_setup))
}

#[put("/settings")]
pub async fn put_settings(
	db: web::Data<DB>,
	// _admin_rights: AdminRights, // TODO.important
	config: web::Json<Config>,
) -> Result<HttpResponse, APIError> {
	web::block(move || config::amend(&db, &config))
		.await
		.map_err(|_| anyhow!("Could not amend config"))?;
	Ok(HttpResponse::Ok().finish())
}
<commit_msg>Added doc reference<commit_after>use actix_http::ResponseBuilder;
use actix_web::{error, get, http::header, http::StatusCode, put, web, HttpResponse};
use anyhow::*;

use crate::config::{self, Config};
use crate::db::DB;
use crate::service::constants::*;
use crate::service::dto;
use crate::service::error::APIError;
use crate::user;

impl error::ResponseError for APIError {
	fn error_response(&self) -> HttpResponse {
		ResponseBuilder::new(self.status_code())
			.set_header(header::CONTENT_TYPE, "text/html; charset=utf-8")
			.body(self.to_string())
	}
	fn status_code(&self) -> StatusCode {
		match *self {
			APIError::IncorrectCredentials => StatusCode::UNAUTHORIZED,
			APIError::Unspecified => StatusCode::INTERNAL_SERVER_ERROR,
		}
	}
}

#[get("/version")]
pub async fn get_version() -> Result<HttpResponse, APIError> {
	let current_version = dto::Version {
		major: CURRENT_MAJOR_VERSION,
		minor: CURRENT_MINOR_VERSION,
	};
	Ok(HttpResponse::Ok().json(current_version))
}

#[get("/initial_setup")]
pub async fn get_initial_setup(db: web::Data<DB>) -> Result<HttpResponse, APIError> {
	let user_count = web::block(move || user::count(&db))
		.await
		.map_err(|_| anyhow!("Could not count users"))?;
	let initial_setup = dto::InitialSetup {
		has_any_users: user_count > 0,
	};
	Ok(HttpResponse::Ok().json(initial_setup))
}

#[put("/settings")]
pub async fn put_settings(
	db: web::Data<DB>,
	// _admin_rights: AdminRights, // TODO.important https://docs.rs/actix-web/2.0.0/actix_web/trait.FromRequest.html
	config: web::Json<Config>,
) -> Result<HttpResponse, APIError> {
	web::block(move || config::amend(&db, &config))
		.await
		.map_err(|_| anyhow!("Could not amend config"))?;
	Ok(HttpResponse::Ok().finish())
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::io::{self, Write};
use std::rc::Rc;
use std::str;
use std::sync::{Arc, Mutex};
use std::thread;

use common::driver::ErrorDestination;
use errors::{self, DiagnosticBuilder, Handler};
use errors::emitter::{ColorConfig, Emitter, EmitterWriter};
use parser::ast::{self, Stmt};
use parser::ast::StmtKind::*;
use parser::codemap::CodeMap;
use parser::lexer::{Reader, StringReader};
use parser::parser::{filemap_to_parser, parse_tts_from_source_str, ParseSess, Parser, PResult};
use parser::ptr::P;
use parser::tokenstream::TokenTree;

use self::ErrorKind::*;

use super::Input;

pub enum IncrCompilerAction {
  Done,
  Error,
  Continue,
  Quit
}

enum ErrorKind {
  UnclosedDelimiter,
  Unknown
}

enum Parsed {
  Item(P<ast::Item>),
  Stmt(ast::Stmt),
  None,
  Error
}

unsafe impl Send for IncrCompilerAction {}

pub struct IncrCompiler {
  pub filename: String,
  pub errdst: Rc<RefCell<ErrorDestination>>, // error destination
}

// Temporarily have stack size set to 16MB to deal with nom-using crates failing
const DEFAULT_STACK_SIZE: usize = 16 * 1024 * 1024; // 16MB

impl IncrCompiler {
  pub fn new(filename: String, errdst: Rc<RefCell<ErrorDestination>>)
      -> IncrCompiler {

    IncrCompiler {
      filename: filename,
      errdst: errdst
    }
  }

  pub fn init(&mut self) {
  }

  pub fn eval(&mut self, line: &str) -> IncrCompilerAction {
    println!("execute line: {}", line);
    struct Sink(Arc<Mutex<Vec<u8>>>);
    impl Write for Sink {
        fn write(&mut self, data: &[u8]) -> io::Result<usize> {
            Write::write(&mut *self.0.lock().unwrap(), data)
        }
        fn flush(&mut self) -> io::Result<()> {
            Ok(())
        }
    }

    let data = Arc::new(Mutex::new(Vec::new()));
    let err = Sink(data.clone());
    let errdst = self.errdst.borrow().clone();
    let line = line.to_owned();
    let filename = self.filename.clone();

    let task = thread::Builder::new().name("parsing".to_owned());
    let handle = task.spawn(move || {

      io::set_panic(Some(Box::new(err)));

      let cm = Rc::new(CodeMap::new());
      let (emitter, errs) = new_emitter(errdst, cm.clone());
      let handler = Handler::with_emitter(true, false, emitter);
      let parsess = ParseSess::with_span_handler(handler, cm.clone());
      let filemap = parsess.codemap().new_filemap_and_lines(&filename, None, &line);
      let mut parser = filemap_to_parser(&parsess, filemap);

      debug!("filemap_to_parser...");
      if need_more_liens(&errs) {
        return IncrCompilerAction::Continue;
      } else if is_error(&errs) {
        return IncrCompilerAction::Error;
      }

      match parse(&mut parser) {
        Parsed::Item(item) => {
          debug!("item: {:?}", item);
          IncrCompilerAction::Done
        }
        Parsed::Stmt(stmt) => {
          debug!("stmt: {:?}", stmt);
          IncrCompilerAction::Done
        }
        Parsed::None => {
          debug!("none");
          IncrCompilerAction::Done
        }
        Parsed::Error => {
          debug!("error");
          IncrCompilerAction::Error
        }
      }

    }).unwrap();

    let action = match handle.join() {
      Ok(result) => {
        debug!("handle Ok");
        result
      }
      Err(value) => {
        debug!("handle Err");
        if !value.is::<errors::FatalError>() {
          writeln!(io::stderr(), "{}", str::from_utf8(&data.lock().unwrap()).unwrap()).unwrap();
        }
        IncrCompilerAction::Error
      }
    };

    action
  }
} // IncrCompiler

pub type CompilerResult = Result<(), u64>;

fn compiler_input(input: &Input) {
  match phase_1_parse_input(input) {
    Ok(_) => {},
    Err(_) => {}
  };
}

fn phase_1_parse_input(input: &Input) -> PResult<ast::Package> {
  unimplemented!()
}

/// it tries to parse a given line.
/// It firstly assumes the line as an item, and tries to parse the line.
/// Otherwise, it regards
fn parse(parser: &mut Parser) -> Parsed {
  let parsed_item: PResult<Option<P<ast::Item>>> = match parser.parse_item() {
    Ok(Some(item)) => Ok(Some(item)),
    Ok(None) => Ok(None),
    Err(mut e) => {
      e.cancel();
      Err(e)
     }
  };

  let parsed_stmt: PResult<Option<Stmt>> = if parsed_item.is_err() {
    match parser.parse_full_stmt() {
      Ok(Some(stmt)) => Ok(Some(stmt)),
      Ok(None) => Ok(None),
      Err(mut e) => {
        e.cancel();
        Err(e)
      }
    }
  } else {
    Ok(None)
  };

  match (parsed_item, parsed_stmt) {
    (Ok(Some(item)), Ok(None)) => {
      debug!("item: {:?}", item);
      Parsed::Item(item)
    }
    (Ok(Some(item)), Err(_)) => {
      debug!("item: {:?}", item);
      Parsed::Item(item)
    }
    (Ok(None), Ok(Some(stmt))) => {
      debug!("stmt: {:?}", stmt);
      Parsed::Stmt(stmt)
    }
    (Err(_), Ok(Some(stmt))) => {
      debug!("stmt: {:?}", stmt);
      Parsed::Stmt(stmt)
    }
    (Err(_), Err(_)) => {
      debug!("error");
      Parsed::Error
    }
    (_, _) => {
      debug!("None");
      Parsed::None
    }
  }
}

fn need_more_liens(errs: &Rc<RefCell<Vec<ErrorKind>>>) -> bool {
  errs.borrow().len() == 1 && match errs.borrow()[0] {
    UnclosedDelimiter => true,
    _ => false
  }
}

fn is_error(errs: &Rc<RefCell<Vec<ErrorKind>>>) -> bool {
  if errs.borrow().len() == 0 {
    return false;
  }

  if errs.borrow().len() > 2 {
    return true;
  }

  // only if errors.len() == 1
  match errs.borrow()[0] {
    UnclosedDelimiter => false,
    _ => true
  }
}

fn new_emitter(errdst: ErrorDestination, cm: Rc<CodeMap>)
      -> (Box<Emitter>, Rc<RefCell<Vec<ErrorKind>>>) {
    let ew = match errdst {
      ErrorDestination::Stderr => {
        EmitterWriter::stderr(ColorConfig::Auto, Some(cm))
      }
      ErrorDestination::Raw(ref buf) => {
        let delegator = WriteDelegator {write: buf.clone()};
        EmitterWriter::new(Box::new(delegator), Some(cm))
      }
    };

    let (emitter, errkinds) = EmitterDelegator::new(ew);
    (Box::new(emitter), errkinds)
}

pub struct WriteDelegator {
  write: Rc<RefCell<Box<io::Write + Send>>>
}

unsafe impl Send for WriteDelegator {}

impl io::Write for WriteDelegator {
  fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
    self.write.borrow_mut().write(buf)
  }

  fn flush(&mut self) -> io::Result<()> {
    self.write.borrow_mut().flush()
  }
}

struct EmitterDelegator {
  em: EmitterWriter,
  errors: Rc<RefCell<Vec<ErrorKind>>>
}

impl EmitterDelegator {
  pub fn new(em : EmitterWriter)
      -> (EmitterDelegator, Rc<RefCell<Vec<ErrorKind>>>) {
    let errors = Rc::new(RefCell::new(Vec::new()));
    let delegator = EmitterDelegator { em : em, errors: errors.clone() };
    (delegator, errors)
  }
}

impl Emitter for EmitterDelegator {
  fn emit(&mut self, db: &DiagnosticBuilder) {

    let errkind = error_kind(db.message());

    match errkind {
      UnclosedDelimiter => {},
      _ => self.em.emit(db)
    };

    self.errors.borrow_mut().push(errkind);
  }
}

fn error_kind(msg: &str) -> ErrorKind {
  if is_unclosed_delemiter(msg) {
    ErrorKind::UnclosedDelimiter
  } else {
    Unknown
  }
}

fn is_unclosed_delemiter(msg: &str) -> bool {
  msg == "this file contains an un-closed delimiter"
}<commit_msg>Fix a bug of incremental::parse()<commit_after>use std::cell::RefCell;
use std::io::{self, Write};
use std::rc::Rc;
use std::str;
use std::sync::{Arc, Mutex};
use std::thread;

use common::driver::ErrorDestination;
use errors::{self, DiagnosticBuilder, Handler};
use errors::emitter::{ColorConfig, Emitter, EmitterWriter};
use parser::ast::{self, Stmt};
use parser::ast::StmtKind::*;
use parser::codemap::CodeMap;
use parser::lexer::{Reader, StringReader};
use parser::parser::{filemap_to_parser, parse_tts_from_source_str, ParseSess, Parser, PResult};
use parser::ptr::P;
use parser::tokenstream::TokenTree;

use self::ErrorKind::*;

use super::Input;

pub enum IncrCompilerAction {
  Done,
  Error,
  Continue,
  Quit
}

enum ErrorKind {
  UnclosedDelimiter,
  Unknown
}

enum Parsed {
  Item(P<ast::Item>),
  Stmt(ast::Stmt),
  None,
  Error
}

unsafe impl Send for IncrCompilerAction {}

pub struct IncrCompiler {
  pub filename: String,
  pub errdst: Rc<RefCell<ErrorDestination>>, // error destination
}

// Temporarily have stack size set to 16MB to deal with nom-using crates failing
const DEFAULT_STACK_SIZE: usize = 16 * 1024 * 1024; // 16MB

impl IncrCompiler {
  pub fn new(filename: String, errdst: Rc<RefCell<ErrorDestination>>)
      -> IncrCompiler {

    IncrCompiler {
      filename: filename,
      errdst: errdst
    }
  }

  pub fn init(&mut self) {
  }

  pub fn eval(&mut self, line: &str) -> IncrCompilerAction {
    println!("execute line: {}", line);
    struct Sink(Arc<Mutex<Vec<u8>>>);
    impl Write for Sink {
        fn write(&mut self, data: &[u8]) -> io::Result<usize> {
            Write::write(&mut *self.0.lock().unwrap(), data)
        }
        fn flush(&mut self) -> io::Result<()> {
            Ok(())
        }
    }

    let data = Arc::new(Mutex::new(Vec::new()));
    let err = Sink(data.clone());
    let errdst = self.errdst.borrow().clone();
    let line = line.to_owned();
    let filename = self.filename.clone();

    let task = thread::Builder::new().name("parsing".to_owned());
    let handle = task.spawn(move || {

      io::set_panic(Some(Box::new(err)));

      let cm = Rc::new(CodeMap::new());
      let (emitter, errs) = new_emitter(errdst, cm.clone());
      let handler = Handler::with_emitter(true, false, emitter);
      let parsess = ParseSess::with_span_handler(handler, cm.clone());
      let filemap = parsess.codemap().new_filemap_and_lines(&filename, None, &line);
      let mut parser = filemap_to_parser(&parsess, filemap);

      debug!("filemap_to_parser...");
      if need_more_liens(&errs) {
        return IncrCompilerAction::Continue;
      } else if is_error(&errs) {
        return IncrCompilerAction::Error;
      }

      match parse(&mut parser) {
        Parsed::Item(item) => {
          debug!("item: {:?}", item);
          IncrCompilerAction::Done
        }
        Parsed::Stmt(stmt) => {
          debug!("stmt: {:?}", stmt);
          IncrCompilerAction::Done
        }
        Parsed::None => {
          debug!("none");
          IncrCompilerAction::Done
        }
        Parsed::Error => {
          debug!("error");
          IncrCompilerAction::Error
        }
      }

    }).unwrap();

    let action = match handle.join() {
      Ok(result) => {
        debug!("handle Ok");
        result
      }
      Err(value) => {
        debug!("handle Err");
        if !value.is::<errors::FatalError>() {
          writeln!(io::stderr(), "{}", str::from_utf8(&data.lock().unwrap()).unwrap()).unwrap();
        }
        IncrCompilerAction::Error
      }
    };

    action
  }
} // IncrCompiler

pub type CompilerResult = Result<(), u64>;

fn compiler_input(input: &Input) {
  match phase_1_parse_input(input) {
    Ok(_) => {},
    Err(_) => {}
  };
}

fn phase_1_parse_input(input: &Input) -> PResult<ast::Package> {
  unimplemented!()
}

fn should_parse_stmt(item: &PResult<Option<P<ast::Item>>>) -> bool {
  // if item is error or none
  item.is_err() || item.as_ref().ok().unwrap().is_none()
}

/// it tries to parse a given line.
/// It firstly assumes the line as an item, and tries to parse the line.
/// Otherwise, it regards
fn parse(parser: &mut Parser) -> Parsed {
  let mut parsed_item = parser.parse_item();

  if parsed_item.is_err() {
    let e = parsed_item.as_mut().err().unwrap();
    e.cancel();
  }

  let mut parsed_stmt = if should_parse_stmt(&parsed_item) {
    parser.parse_full_stmt()
  } else {
    Ok(None)
  };

  if parsed_stmt.is_err() {
    let e = parsed_stmt.as_mut().err().unwrap();
    e.cancel();
  }

  // There are 9 cases:
  // 1: (Ok(Some(item)), Ok(Some(stmt))) - how it happens?
  // 2: (Ok(Some(item)), Ok(None))       - item
  // 3: (Ok(Some(item)), Err(e))         - item
  // 4: (Ok(None)), Ok(Some(stmt)))      - stmt
  // 5: (Err(e),    Ok(Some(stmt)))      - stmt
  // 6: (Ok(None),  Ok(None))            - none
  // 7: (Ok(None),  Err(e))              - none
  // 8: (Err(e),  Ok(None))              - none
  // 9: (Err(e),  Err(e))                - error
  match (parsed_item, parsed_stmt) {
    // case 1
    (Ok(Some(item)), Ok(Some(stmt))) => {
      panic!("A line is regarded as an item as well as a statement.")
    }
    // case 2, 3
    (Ok(Some(item)), _) => {
      Parsed::Item(item)
    }
    // case 4, 5
    (_, Ok(Some(stmt))) => {
      Parsed::Stmt(stmt)
    }
    // case 9
    (Err(_), Err(_)) => {
      Parsed::Error
    }
    // case 6, 7, 8
    (_, _) => {
      Parsed::None
    }
  }
}

fn need_more_liens(errs: &Rc<RefCell<Vec<ErrorKind>>>) -> bool {
  errs.borrow().len() == 1 && match errs.borrow()[0] {
    UnclosedDelimiter => true,
    _ => false
  }
}

fn is_error(errs: &Rc<RefCell<Vec<ErrorKind>>>) -> bool {
  if errs.borrow().len() == 0 {
    return false;
  }

  if errs.borrow().len() > 2 {
    return true;
  }

  // only if errors.len() == 1
  match errs.borrow()[0] {
    UnclosedDelimiter => false,
    _ => true
  }
}

fn new_emitter(errdst: ErrorDestination, cm: Rc<CodeMap>)
      -> (Box<Emitter>, Rc<RefCell<Vec<ErrorKind>>>) {
    let ew = match errdst {
      ErrorDestination::Stderr => {
        EmitterWriter::stderr(ColorConfig::Auto, Some(cm))
      }
      ErrorDestination::Raw(ref buf) => {
        let delegator = WriteDelegator {write: buf.clone()};
        EmitterWriter::new(Box::new(delegator), Some(cm))
      }
    };

    let (emitter, errkinds) = EmitterDelegator::new(ew);
    (Box::new(emitter), errkinds)
}

pub struct WriteDelegator {
  write: Rc<RefCell<Box<io::Write + Send>>>
}

unsafe impl Send for WriteDelegator {}

impl io::Write for WriteDelegator {
  fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
    self.write.borrow_mut().write(buf)
  }

  fn flush(&mut self) -> io::Result<()> {
    self.write.borrow_mut().flush()
  }
}

struct EmitterDelegator {
  em: EmitterWriter,
  errors: Rc<RefCell<Vec<ErrorKind>>>
}

impl EmitterDelegator {
  pub fn new(em : EmitterWriter)
      -> (EmitterDelegator, Rc<RefCell<Vec<ErrorKind>>>) {
    let errors = Rc::new(RefCell::new(Vec::new()));
    let delegator = EmitterDelegator { em : em, errors: errors.clone() };
    (delegator, errors)
  }
}

impl Emitter for EmitterDelegator {
  fn emit(&mut self, db: &DiagnosticBuilder) {

    let errkind = error_kind(db.message());

    match errkind {
      UnclosedDelimiter => {},
      _ => self.em.emit(db)
    };

    self.errors.borrow_mut().push(errkind);
  }
}

fn error_kind(msg: &str) -> ErrorKind {
  if is_unclosed_delemiter(msg) {
    ErrorKind::UnclosedDelimiter
  } else {
    Unknown
  }
}

fn is_unclosed_delemiter(msg: &str) -> bool {
  msg == "this file contains an un-closed delimiter"
}<|endoftext|>


<commit_before>//! Fields which are common to all segment-section and gate descriptors

use shared::PrivilegeLevel;
use shared::segmentation;

/// System-Segment and Gate-Descriptor Types for IA32e mode.  When the `S`
/// (descriptor type) flag in a segment descriptor is clear, the descriptor type
/// is a system descriptor.
///
/// See Intel manual 3a, 3.5 "System Descriptor Types", and Table 3-2,
/// System-Segment and Gate-Descriptor Types".
#[repr(u8)]
pub enum SystemType {
    // Reserved = 0
    TssAvailable = 1,
    /// Only for 16-bit
    LocalDescriptorTable = 2,
    TssBusy = 3,
    CallGate = 4,
    /// Only for 16-bit
    TaskGate = 5,
    InterruptGate = 6,
    TrapGate = 7,
}

/// A high-level representation of a descriptor type. One can convert to and
/// from the `Flags` bitfield to encode/decode an actual descriptor.
#[repr(u8)]
pub enum Type {
    SystemDescriptor {
        /// false/0: 16-bit
        /// true/1: native (32- or 64-bit)
        size: bool,
        ty: SystemType
    },
    SegmentDescriptor {
        ty: segmentation::Type,
        accessed: bool
    }
}

impl Type {
    pub fn pack(self) -> u8 {
        match self {
            Type::SystemDescriptor { size, ty } =>
                (size as u8) << 3 | (ty as u8) | FLAGS_TYPE_SYS.bits,
            Type::SegmentDescriptor { ty, accessed } =>
                (accessed as u8)  | ty.pack()  | FLAGS_TYPE_SYS.bits,
        }
    }
}

bitflags!{
    /// Actual encoding of the flags in byte 6 common to all descriptors.
    ///
    /// See Intel manual 3a, figures 3-8, 6-2, and 6-7.
    pub flags Flags: u8 {
        /// Descriptor is Present.
        const FLAGS_PRESENT = 1 << 7,

        // Descriptor privilege level
        const FLAGS_DPL_RING_0 = 0b00 << 5,
        const FLAGS_DPL_RING_1 = 0b01 << 5,
        const FLAGS_DPL_RING_2 = 0b10 << 5,
        const FLAGS_DPL_RING_3 = 0b11 << 5,

        // Is system descriptor
        const FLAGS_TYPE_SYS = 0 << 4,
        const FLAGS_TYPE_SEG = 1 << 4,

        // System-Segment and Gate-Descriptor Types.
        // When the S (descriptor type) flag in a segment descriptor is clear,
        // the descriptor type is a system descriptor

        // All modes (supporting segments)
        const TYPE_SYS_LDT = 0b0_0010,

        // Protected Mode and older
        const FLAGS_TYPE_SYS_16BIT_TSS_AVAILABLE = 0b0_0001,
        const FLAGS_TYPE_SYS_16BIT_TSS_BUSY = 0b0_0011,
        const FLAGS_TYPE_SYS_16BIT_CALL_GATE = 0b0_0100,
        const FLAGS_TYPE_SYS_16BIT_TASK_GATE = 0b0_0101,
        const FLAGS_TYPE_SYS_16BIT_INTERRUPT_GATE = 0b0_0110,
        const FLAGS_TYPE_SYS_16BIT_TRAP_GATE = 0b0_0111,

        // 64-bit in IA-32e Mode (either submode), 32-bit in Protected Mode
        const FLAGS_TYPE_SYS_NATIVE_TSS_AVAILABLE = 0b0_1001,
        const FLAGS_TYPE_SYS_NATIVE_TSS_BUSY = 0b0_1011,
        const FLAGS_TYPE_SYS_NATIVE_CALL_GATE = 0b0_1100,
        const FLAGS_TYPE_SYS_NATIVE_INTERRUPT_GATE = 0b0_1110,
        const FLAGS_TYPE_SYS_NATIVE_TRAP_GATE = 0b0_1111,

        // Code- and Data-Segment Descriptor Types.
        // When the S (descriptor type) flag in a segment descriptor is set,
        // the descriptor is for either a code or a data segment.

        /// Data or code, accessed
        const FLAGS_TYPE_SEG_ACCESSED = 0b1_0001,

        const FLAGS_TYPE_DATA = 0b1_0000,
        const FLAGS_TYPE_CODE = 0b1_1000,

        // Data => permissions
        const FLAGS_TYPE_SEG_D_WRITE = 0b1_0010,
        const FLAGS_TYPE_SEG_D_EXPAND_DOWN = 0b1_0100,

        // Code => permissions
        const FLAGS_TYPE_SEG_C_READ = 0b1_0010,
        const FLAGS_TYPE_SEG_D_CONFORMING = 0b1_0100,

        /// Data Read-Only
        const FLAGS_TYPE_SEG_D_RO     = FLAGS_TYPE_DATA.bits,
        /// Data Read-Only, accessed
        const FLAGS_TYPE_SEG_D_ROA    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read/Write
        const FLAGS_TYPE_SEG_D_RW     = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits,
        /// Data Read/Write, accessed
        const FLAGS_TYPE_SEG_D_RWA    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read-Only, expand-down
        const FLAGS_TYPE_SEG_D_ROEXD  = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits,
        /// Data Read-Only, expand-down, accessed
        const FLAGS_TYPE_SEG_D_ROEXDA = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read/Write, expand-down
        const FLAGS_TYPE_SEG_D_RWEXD  = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits,
        /// Data Read/Write, expand-down, accessed
        const FLAGS_TYPE_SEG_D_RWEXDA = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,

        /// Code Execute-Only
        const FLAGS_TYPE_SEG_C_EO     = FLAGS_TYPE_CODE.bits,
        /// Code Execute-Only, accessed
        const FLAGS_TYPE_SEG_C_EOA    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute/Read
        const FLAGS_TYPE_SEG_C_ER     = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits,
        /// Code Execute/Read, accessed
        const FLAGS_TYPE_SEG_C_ERA    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute-Only, conforming
        const FLAGS_TYPE_SEG_C_EOC    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_D_CONFORMING.bits,
        /// Code Execute-Only, conforming, accessed
        const FLAGS_TYPE_SEG_C_EOCA   = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_D_CONFORMING.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute/Read, conforming
        const FLAGS_TYPE_SEG_C_ERC    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_D_CONFORMING.bits,
        /// Code Execute/Read, conforming, accessed
        const FLAGS_TYPE_SEG_C_ERCA   = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_D_CONFORMING.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
    }
}

impl Flags {
    pub const BLANK: Flags = Flags { bits: 0 };

    pub const fn from_priv(dpl: PrivilegeLevel) -> Flags {
        Flags { bits: (dpl as u8) << 5 }
    }

    pub fn from_type(ty: Type) -> Flags {
        Flags { bits: ty.pack() }
    }

    pub const fn const_or(self, other: Self) -> Flags {
        Flags { bits: self.bits | other.bits }
    }

    pub const fn cond(self, cond: bool) -> Flags {
        Flags { bits: (-(cond as i8) as u8) & self.bits }
    }

    pub const fn const_mux(self, other: Self, cond: bool) -> Flags {
        self.cond(cond).const_or(other.cond(!cond))
    }
}
<commit_msg>Fix naming of FLAGS_TYPE_SEG_C_CONFORMING from ..._D_... to ..._C_...<commit_after>//! Fields which are common to all segment-section and gate descriptors

use shared::PrivilegeLevel;
use shared::segmentation;

/// System-Segment and Gate-Descriptor Types for IA32e mode.  When the `S`
/// (descriptor type) flag in a segment descriptor is clear, the descriptor type
/// is a system descriptor.
///
/// See Intel manual 3a, 3.5 "System Descriptor Types", and Table 3-2,
/// System-Segment and Gate-Descriptor Types".
#[repr(u8)]
pub enum SystemType {
    // Reserved = 0
    TssAvailable = 1,
    /// Only for 16-bit
    LocalDescriptorTable = 2,
    TssBusy = 3,
    CallGate = 4,
    /// Only for 16-bit
    TaskGate = 5,
    InterruptGate = 6,
    TrapGate = 7,
}

/// A high-level representation of a descriptor type. One can convert to and
/// from the `Flags` bitfield to encode/decode an actual descriptor.
#[repr(u8)]
pub enum Type {
    SystemDescriptor {
        /// false/0: 16-bit
        /// true/1: native (32- or 64-bit)
        size: bool,
        ty: SystemType
    },
    SegmentDescriptor {
        ty: segmentation::Type,
        accessed: bool
    }
}

impl Type {
    pub fn pack(self) -> u8 {
        match self {
            Type::SystemDescriptor { size, ty } =>
                (size as u8) << 3 | (ty as u8) | FLAGS_TYPE_SYS.bits,
            Type::SegmentDescriptor { ty, accessed } =>
                (accessed as u8)  | ty.pack()  | FLAGS_TYPE_SYS.bits,
        }
    }
}

bitflags!{
    /// Actual encoding of the flags in byte 6 common to all descriptors.
    ///
    /// See Intel manual 3a, figures 3-8, 6-2, and 6-7.
    pub flags Flags: u8 {
        /// Descriptor is Present.
        const FLAGS_PRESENT = 1 << 7,

        // Descriptor privilege level
        const FLAGS_DPL_RING_0 = 0b00 << 5,
        const FLAGS_DPL_RING_1 = 0b01 << 5,
        const FLAGS_DPL_RING_2 = 0b10 << 5,
        const FLAGS_DPL_RING_3 = 0b11 << 5,

        // Is system descriptor
        const FLAGS_TYPE_SYS = 0 << 4,
        const FLAGS_TYPE_SEG = 1 << 4,

        // System-Segment and Gate-Descriptor Types.
        // When the S (descriptor type) flag in a segment descriptor is clear,
        // the descriptor type is a system descriptor

        // All modes (supporting segments)
        const TYPE_SYS_LDT = 0b0_0010,

        // Protected Mode and older
        const FLAGS_TYPE_SYS_16BIT_TSS_AVAILABLE = 0b0_0001,
        const FLAGS_TYPE_SYS_16BIT_TSS_BUSY = 0b0_0011,
        const FLAGS_TYPE_SYS_16BIT_CALL_GATE = 0b0_0100,
        const FLAGS_TYPE_SYS_16BIT_TASK_GATE = 0b0_0101,
        const FLAGS_TYPE_SYS_16BIT_INTERRUPT_GATE = 0b0_0110,
        const FLAGS_TYPE_SYS_16BIT_TRAP_GATE = 0b0_0111,

        // 64-bit in IA-32e Mode (either submode), 32-bit in Protected Mode
        const FLAGS_TYPE_SYS_NATIVE_TSS_AVAILABLE = 0b0_1001,
        const FLAGS_TYPE_SYS_NATIVE_TSS_BUSY = 0b0_1011,
        const FLAGS_TYPE_SYS_NATIVE_CALL_GATE = 0b0_1100,
        const FLAGS_TYPE_SYS_NATIVE_INTERRUPT_GATE = 0b0_1110,
        const FLAGS_TYPE_SYS_NATIVE_TRAP_GATE = 0b0_1111,

        // Code- and Data-Segment Descriptor Types.
        // When the S (descriptor type) flag in a segment descriptor is set,
        // the descriptor is for either a code or a data segment.

        /// Data or code, accessed
        const FLAGS_TYPE_SEG_ACCESSED = 0b1_0001,

        const FLAGS_TYPE_DATA = 0b1_0000,
        const FLAGS_TYPE_CODE = 0b1_1000,

        // Data => permissions
        const FLAGS_TYPE_SEG_D_WRITE = 0b1_0010,
        const FLAGS_TYPE_SEG_D_EXPAND_DOWN = 0b1_0100,

        // Code => permissions
        const FLAGS_TYPE_SEG_C_READ = 0b1_0010,
        const FLAGS_TYPE_SEG_C_CONFORMING = 0b1_0100,

        /// Data Read-Only
        const FLAGS_TYPE_SEG_D_RO     = FLAGS_TYPE_DATA.bits,
        /// Data Read-Only, accessed
        const FLAGS_TYPE_SEG_D_ROA    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read/Write
        const FLAGS_TYPE_SEG_D_RW     = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits,
        /// Data Read/Write, accessed
        const FLAGS_TYPE_SEG_D_RWA    = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read-Only, expand-down
        const FLAGS_TYPE_SEG_D_ROEXD  = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits,
        /// Data Read-Only, expand-down, accessed
        const FLAGS_TYPE_SEG_D_ROEXDA = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Data Read/Write, expand-down
        const FLAGS_TYPE_SEG_D_RWEXD  = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits,
        /// Data Read/Write, expand-down, accessed
        const FLAGS_TYPE_SEG_D_RWEXDA = FLAGS_TYPE_DATA.bits
                                      | FLAGS_TYPE_SEG_D_WRITE.bits
                                      | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,

        /// Code Execute-Only
        const FLAGS_TYPE_SEG_C_EO     = FLAGS_TYPE_CODE.bits,
        /// Code Execute-Only, accessed
        const FLAGS_TYPE_SEG_C_EOA    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute/Read
        const FLAGS_TYPE_SEG_C_ER     = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits,
        /// Code Execute/Read, accessed
        const FLAGS_TYPE_SEG_C_ERA    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute-Only, conforming
        const FLAGS_TYPE_SEG_C_EOC    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_CONFORMING.bits,
        /// Code Execute-Only, conforming, accessed
        const FLAGS_TYPE_SEG_C_EOCA   = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_CONFORMING.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
        /// Code Execute/Read, conforming
        const FLAGS_TYPE_SEG_C_ERC    = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_C_CONFORMING.bits,
        /// Code Execute/Read, conforming, accessed
        const FLAGS_TYPE_SEG_C_ERCA   = FLAGS_TYPE_CODE.bits
                                      | FLAGS_TYPE_SEG_C_READ.bits
                                      | FLAGS_TYPE_SEG_C_CONFORMING.bits
                                      | FLAGS_TYPE_SEG_ACCESSED.bits,
    }
}

impl Flags {
    pub const BLANK: Flags = Flags { bits: 0 };

    pub const fn from_priv(dpl: PrivilegeLevel) -> Flags {
        Flags { bits: (dpl as u8) << 5 }
    }

    pub fn from_type(ty: Type) -> Flags {
        Flags { bits: ty.pack() }
    }

    pub const fn const_or(self, other: Self) -> Flags {
        Flags { bits: self.bits | other.bits }
    }

    pub const fn cond(self, cond: bool) -> Flags {
        Flags { bits: (-(cond as i8) as u8) & self.bits }
    }

    pub const fn const_mux(self, other: Self, cond: bool) -> Flags {
        self.cond(cond).const_or(other.cond(!cond))
    }
}
<|endoftext|>


<commit_before>use crate::config::file_lines::FileLines;
use crate::config::options::{IgnoreList, WidthHeuristics};

/// Trait for types that can be used in `Config`.
pub(crate) 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()
    }
}

impl ConfigType for IgnoreList {
    fn doc_hint() -> String {
        String::from("[<string>,..]")
    }
}

macro_rules! create_config {
    ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => (
        #[cfg(test)]
        use std::collections::HashSet;
        use std::io::Write;

        use serde::{Deserialize, Serialize};

        #[derive(Clone)]
        #[allow(unreachable_pub)]
        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)]
        #[allow(unreachable_pub)]
        pub struct PartialConfig {
            $(pub $i: Option<$ty>),+
        }

        // 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!()`.
        #[allow(unreachable_pub)]
        pub struct ConfigSetter<'a>(&'a mut Config);

        impl<'a> ConfigSetter<'a> {
            $(
            #[allow(unreachable_pub)]
            pub fn $i(&mut self, value: $ty) {
                (self.0).$i.2 = value;
                match stringify!($i) {
                    "max_width"
                    | "use_small_heuristics"
                    | "fn_call_width"
                    | "single_line_if_else_max_width"
                    | "attr_fn_like_width"
                    | "struct_lit_width"
                    | "struct_variant_width"
                    | "array_width"
                    | "chain_width" => self.0.set_heuristics(),
                    "license_template_path" => self.0.set_license_template(),
                    "merge_imports" => self.0.set_merge_imports(),
                    &_ => (),
                }
            }
            )+
        }

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

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

        impl Config {
            $(
            #[allow(unreachable_pub)]
            pub fn $i(&self) -> $ty {
                self.$i.0.set(true);
                self.$i.2.clone()
            }
            )+

            #[allow(unreachable_pub)]
            pub fn set(&mut self) -> ConfigSetter<'_> {
                ConfigSetter(self)
            }

            #[allow(unreachable_pub)]
            pub fn was_set(&self) -> ConfigWasSet<'_> {
                ConfigWasSet(self)
            }

            fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config {
            $(
                if let Some(val) = parsed.$i {
                    if self.$i.3 {
                        self.$i.1 = true;
                        self.$i.2 = val;
                    } else {
                        if crate::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.set_ignore(dir);
                self.set_merge_imports();
                self
            }

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

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

            #[allow(unreachable_pub)]
            pub fn is_valid_key_val(key: &str, val: &str) -> bool {
                match key {
                    $(
                        stringify!($i) => val.parse::<$ty>().is_ok(),
                    )+
                        _ => false,
                }
            }

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

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

            #[allow(unreachable_pub)]
            pub fn override_value(&mut self, key: &str, val: &str)
            {
                match key {
                    $(
                        stringify!($i) => {
                            self.$i.1 = true;
                            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 {
                    "max_width"
                    | "use_small_heuristics"
                    | "fn_call_width"
                    | "single_line_if_else_max_width"
                    | "attr_fn_like_width"
                    | "struct_lit_width"
                    | "struct_variant_width"
                    | "array_width"
                    | "chain_width" => self.set_heuristics(),
                    "license_template_path" => self.set_license_template(),
                    "merge_imports" => self.set_merge_imports(),
                    &_ => (),
                }
            }

            #[allow(unreachable_pub)]
            pub fn is_hidden_option(name: &str) -> bool {
                const HIDE_OPTIONS: [&str; 5] =
                    ["verbose", "verbose_diff", "file_lines", "width_heuristics", "merge_imports"];
                HIDE_OPTIONS.contains(&name)
            }

            #[allow(unreachable_pub)]
            pub fn print_docs(out: &mut dyn Write, include_unstable: bool) {
                use std::cmp;
                let max = 0;
                $( let max = cmp::max(max, stringify!($i).len()+1); )+
                let space_str = " ".repeat(max);
                writeln!(out, "Configuration Options:").unwrap();
                $(
                    if $stb || include_unstable {
                        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(' ');
                            let mut default_str = format!("{}", $def);
                            if default_str.is_empty() {
                                default_str = String::from("\"\"");
                            }
                            writeln!(out,
                                    "{}{} Default: {}{}",
                                    name_out,
                                    <$ty>::doc_hint(),
                                    default_str,
                                    if !$stb { " (unstable)" } else { "" }).unwrap();
                            $(
                                writeln!(out, "{}{}", space_str, $dstring).unwrap();
                            )+
                            writeln!(out).unwrap();
                        }
                    }
                )+
            }

            fn set_width_heuristics(&mut self, heuristics: WidthHeuristics) {
                let max_width = self.max_width.2;
                let get_width_value = |
                    was_set: bool,
                    override_value: usize,
                    heuristic_value: usize,
                    config_key: &str,
                | -> usize {
                    if !was_set {
                        return heuristic_value;
                    }
                    if override_value > max_width {
                        eprintln!(
                            "`{0}` cannot have a value that exceeds `max_width`. \
                            `{0}` will be set to the same value as `max_width`",
                            config_key,
                        );
                        return max_width;
                    }
                    override_value
                };

                let fn_call_width = get_width_value(
                    self.was_set().fn_call_width(),
                    self.fn_call_width.2,
                    heuristics.fn_call_width,
                    "fn_call_width",
                );
                self.fn_call_width.2 = fn_call_width;

                let attr_fn_like_width = get_width_value(
                    self.was_set().attr_fn_like_width(),
                    self.attr_fn_like_width.2,
                    heuristics.attr_fn_like_width,
                    "attr_fn_like_width",
                );
                self.attr_fn_like_width.2 = attr_fn_like_width;

                let struct_lit_width = get_width_value(
                    self.was_set().struct_lit_width(),
                    self.struct_lit_width.2,
                    heuristics.struct_lit_width,
                    "struct_lit_width",
                );
                self.struct_lit_width.2 = struct_lit_width;

                let struct_variant_width = get_width_value(
                    self.was_set().struct_variant_width(),
                    self.struct_variant_width.2,
                    heuristics.struct_variant_width,
                    "struct_variant_width",
                );
                self.struct_variant_width.2 = struct_variant_width;

                let array_width = get_width_value(
                    self.was_set().array_width(),
                    self.array_width.2,
                    heuristics.array_width,
                    "array_width",
                );
                self.array_width.2 = array_width;

                let chain_width = get_width_value(
                    self.was_set().chain_width(),
                    self.chain_width.2,
                    heuristics.chain_width,
                    "chain_width",
                );
                self.chain_width.2 = chain_width;

                let single_line_if_else_max_width = get_width_value(
                    self.was_set().single_line_if_else_max_width(),
                    self.single_line_if_else_max_width.2,
                    heuristics.single_line_if_else_max_width,
                    "single_line_if_else_max_width",
                );
                self.single_line_if_else_max_width.2 = single_line_if_else_max_width;
            }

            fn set_heuristics(&mut self) {
                let max_width = self.max_width.2;
                match self.use_small_heuristics.2 {
                    Heuristics::Default =>
                        self.set_width_heuristics(WidthHeuristics::scaled(max_width)),
                    Heuristics::Max => self.set_width_heuristics(WidthHeuristics::set(max_width)),
                    Heuristics::Off => self.set_width_heuristics(WidthHeuristics::null()),
                };
            }

            fn set_license_template(&mut self) {
                if self.was_set().license_template_path() {
                    let lt_path = self.license_template_path();
                    if lt_path.len() > 0 {
                        match license::load_and_compile_template(&lt_path) {
                            Ok(re) => self.license_template = Some(re),
                            Err(msg) => eprintln!("Warning for license template file {:?}: {}",
                                                lt_path, msg),
                        }
                    } else {
                        self.license_template = None;
                    }
                }
            }

            fn set_ignore(&mut self, dir: &Path) {
                self.ignore.2.add_prefix(dir);
            }

            fn set_merge_imports(&mut self) {
                if self.was_set().merge_imports() {
                    eprintln!(
                        "Warning: the `merge_imports` option is deprecated. \
                        Use `imports_granularity=Crate` instead"
                    );
                    if !self.was_set().imports_granularity() {
                        self.imports_granularity.2 = if self.merge_imports() {
                            ImportGranularity::Crate
                        } else {
                            ImportGranularity::Preserve
                        };
                    }
                }
            }

            #[allow(unreachable_pub)]
            /// Returns `true` if the config key was explicitly set and is the default value.
            pub fn is_default(&self, key: &str) -> bool {
                $(
                    if let stringify!($i) = key {
                        return self.$i.1 && self.$i.2 == $def;
                    }
                 )+
                false
            }
        }

        // 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>Improve pasta copyability of `merge_imports` deprecation message<commit_after>use crate::config::file_lines::FileLines;
use crate::config::options::{IgnoreList, WidthHeuristics};

/// Trait for types that can be used in `Config`.
pub(crate) 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()
    }
}

impl ConfigType for IgnoreList {
    fn doc_hint() -> String {
        String::from("[<string>,..]")
    }
}

macro_rules! create_config {
    ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => (
        #[cfg(test)]
        use std::collections::HashSet;
        use std::io::Write;

        use serde::{Deserialize, Serialize};

        #[derive(Clone)]
        #[allow(unreachable_pub)]
        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)]
        #[allow(unreachable_pub)]
        pub struct PartialConfig {
            $(pub $i: Option<$ty>),+
        }

        // 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!()`.
        #[allow(unreachable_pub)]
        pub struct ConfigSetter<'a>(&'a mut Config);

        impl<'a> ConfigSetter<'a> {
            $(
            #[allow(unreachable_pub)]
            pub fn $i(&mut self, value: $ty) {
                (self.0).$i.2 = value;
                match stringify!($i) {
                    "max_width"
                    | "use_small_heuristics"
                    | "fn_call_width"
                    | "single_line_if_else_max_width"
                    | "attr_fn_like_width"
                    | "struct_lit_width"
                    | "struct_variant_width"
                    | "array_width"
                    | "chain_width" => self.0.set_heuristics(),
                    "license_template_path" => self.0.set_license_template(),
                    "merge_imports" => self.0.set_merge_imports(),
                    &_ => (),
                }
            }
            )+
        }

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

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

        impl Config {
            $(
            #[allow(unreachable_pub)]
            pub fn $i(&self) -> $ty {
                self.$i.0.set(true);
                self.$i.2.clone()
            }
            )+

            #[allow(unreachable_pub)]
            pub fn set(&mut self) -> ConfigSetter<'_> {
                ConfigSetter(self)
            }

            #[allow(unreachable_pub)]
            pub fn was_set(&self) -> ConfigWasSet<'_> {
                ConfigWasSet(self)
            }

            fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config {
            $(
                if let Some(val) = parsed.$i {
                    if self.$i.3 {
                        self.$i.1 = true;
                        self.$i.2 = val;
                    } else {
                        if crate::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.set_ignore(dir);
                self.set_merge_imports();
                self
            }

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

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

            #[allow(unreachable_pub)]
            pub fn is_valid_key_val(key: &str, val: &str) -> bool {
                match key {
                    $(
                        stringify!($i) => val.parse::<$ty>().is_ok(),
                    )+
                        _ => false,
                }
            }

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

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

            #[allow(unreachable_pub)]
            pub fn override_value(&mut self, key: &str, val: &str)
            {
                match key {
                    $(
                        stringify!($i) => {
                            self.$i.1 = true;
                            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 {
                    "max_width"
                    | "use_small_heuristics"
                    | "fn_call_width"
                    | "single_line_if_else_max_width"
                    | "attr_fn_like_width"
                    | "struct_lit_width"
                    | "struct_variant_width"
                    | "array_width"
                    | "chain_width" => self.set_heuristics(),
                    "license_template_path" => self.set_license_template(),
                    "merge_imports" => self.set_merge_imports(),
                    &_ => (),
                }
            }

            #[allow(unreachable_pub)]
            pub fn is_hidden_option(name: &str) -> bool {
                const HIDE_OPTIONS: [&str; 5] =
                    ["verbose", "verbose_diff", "file_lines", "width_heuristics", "merge_imports"];
                HIDE_OPTIONS.contains(&name)
            }

            #[allow(unreachable_pub)]
            pub fn print_docs(out: &mut dyn Write, include_unstable: bool) {
                use std::cmp;
                let max = 0;
                $( let max = cmp::max(max, stringify!($i).len()+1); )+
                let space_str = " ".repeat(max);
                writeln!(out, "Configuration Options:").unwrap();
                $(
                    if $stb || include_unstable {
                        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(' ');
                            let mut default_str = format!("{}", $def);
                            if default_str.is_empty() {
                                default_str = String::from("\"\"");
                            }
                            writeln!(out,
                                    "{}{} Default: {}{}",
                                    name_out,
                                    <$ty>::doc_hint(),
                                    default_str,
                                    if !$stb { " (unstable)" } else { "" }).unwrap();
                            $(
                                writeln!(out, "{}{}", space_str, $dstring).unwrap();
                            )+
                            writeln!(out).unwrap();
                        }
                    }
                )+
            }

            fn set_width_heuristics(&mut self, heuristics: WidthHeuristics) {
                let max_width = self.max_width.2;
                let get_width_value = |
                    was_set: bool,
                    override_value: usize,
                    heuristic_value: usize,
                    config_key: &str,
                | -> usize {
                    if !was_set {
                        return heuristic_value;
                    }
                    if override_value > max_width {
                        eprintln!(
                            "`{0}` cannot have a value that exceeds `max_width`. \
                            `{0}` will be set to the same value as `max_width`",
                            config_key,
                        );
                        return max_width;
                    }
                    override_value
                };

                let fn_call_width = get_width_value(
                    self.was_set().fn_call_width(),
                    self.fn_call_width.2,
                    heuristics.fn_call_width,
                    "fn_call_width",
                );
                self.fn_call_width.2 = fn_call_width;

                let attr_fn_like_width = get_width_value(
                    self.was_set().attr_fn_like_width(),
                    self.attr_fn_like_width.2,
                    heuristics.attr_fn_like_width,
                    "attr_fn_like_width",
                );
                self.attr_fn_like_width.2 = attr_fn_like_width;

                let struct_lit_width = get_width_value(
                    self.was_set().struct_lit_width(),
                    self.struct_lit_width.2,
                    heuristics.struct_lit_width,
                    "struct_lit_width",
                );
                self.struct_lit_width.2 = struct_lit_width;

                let struct_variant_width = get_width_value(
                    self.was_set().struct_variant_width(),
                    self.struct_variant_width.2,
                    heuristics.struct_variant_width,
                    "struct_variant_width",
                );
                self.struct_variant_width.2 = struct_variant_width;

                let array_width = get_width_value(
                    self.was_set().array_width(),
                    self.array_width.2,
                    heuristics.array_width,
                    "array_width",
                );
                self.array_width.2 = array_width;

                let chain_width = get_width_value(
                    self.was_set().chain_width(),
                    self.chain_width.2,
                    heuristics.chain_width,
                    "chain_width",
                );
                self.chain_width.2 = chain_width;

                let single_line_if_else_max_width = get_width_value(
                    self.was_set().single_line_if_else_max_width(),
                    self.single_line_if_else_max_width.2,
                    heuristics.single_line_if_else_max_width,
                    "single_line_if_else_max_width",
                );
                self.single_line_if_else_max_width.2 = single_line_if_else_max_width;
            }

            fn set_heuristics(&mut self) {
                let max_width = self.max_width.2;
                match self.use_small_heuristics.2 {
                    Heuristics::Default =>
                        self.set_width_heuristics(WidthHeuristics::scaled(max_width)),
                    Heuristics::Max => self.set_width_heuristics(WidthHeuristics::set(max_width)),
                    Heuristics::Off => self.set_width_heuristics(WidthHeuristics::null()),
                };
            }

            fn set_license_template(&mut self) {
                if self.was_set().license_template_path() {
                    let lt_path = self.license_template_path();
                    if lt_path.len() > 0 {
                        match license::load_and_compile_template(&lt_path) {
                            Ok(re) => self.license_template = Some(re),
                            Err(msg) => eprintln!("Warning for license template file {:?}: {}",
                                                lt_path, msg),
                        }
                    } else {
                        self.license_template = None;
                    }
                }
            }

            fn set_ignore(&mut self, dir: &Path) {
                self.ignore.2.add_prefix(dir);
            }

            fn set_merge_imports(&mut self) {
                if self.was_set().merge_imports() {
                    eprintln!(
                        "Warning: the `merge_imports` option is deprecated. \
                        Use `imports_granularity=\"Crate\"` instead"
                    );
                    if !self.was_set().imports_granularity() {
                        self.imports_granularity.2 = if self.merge_imports() {
                            ImportGranularity::Crate
                        } else {
                            ImportGranularity::Preserve
                        };
                    }
                }
            }

            #[allow(unreachable_pub)]
            /// Returns `true` if the config key was explicitly set and is the default value.
            pub fn is_default(&self, key: &str) -> bool {
                $(
                    if let stringify!($i) = key {
                        return self.$i.1 && self.$i.2 == $def;
                    }
                 )+
                false
            }
        }

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