<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Factory extension. Provides resource construction shortcuts.

use gfx_core::{format, handle, tex};
use gfx_core::{Primitive, Resources, ShaderSet, VertexCount};
use gfx_core::factory::{BufferRole, Factory};
use gfx_core::pso::{CreationError, Descriptor};
use gfx_core::state::{CullFace, Rasterizer};
use encoder::Encoder;
use mesh::{Slice, SliceKind, ToIndexSlice};
use pso;
use shade::{ProgramError, ShaderSource};

/// Error creating a PipelineState
#[derive(Clone, PartialEq, Debug)]
pub enum PipelineStateError {
    /// Shader program failed to link.
    Program(ProgramError),
    /// Unable to create PSO descriptor due to mismatched formats.
    DescriptorInit(pso::InitError),
    /// Device failed to create the handle give the descriptor.
    DeviceCreate(CreationError),
}

/// Factory extension trait
pub trait FactoryExt<R: Resources>: Factory<R> + Sized {
    /// Create a new graphics command Encoder
    fn create_encoder(&mut self) -> Encoder<R, Self::CommandBuffer> {
        Encoder::create(self)
    }

    /// Create a vertex buffer with an associated slice.
    fn create_vertex_buffer<T>(&mut self, data: &[T])
                            -> (handle::Buffer<R, T>, Slice<R>) where
                            T: Copy + pso::buffer::Structure<format::Format>
    {
        let nv = data.len();
        //debug_assert!(nv <= self.get_capabilities().max_vertex_count);
        let buf = self.create_buffer_static(data, BufferRole::Vertex);
        (buf, Slice {
            start: 0,
            end: nv as VertexCount,
            instances: None,
            kind: SliceKind::Vertex,
        })
    }

    /// Create a vertex buffer with an index, returned by a slice.
    fn create_vertex_buffer_indexed<V, I>(&mut self, vd: &[V], id: I)
                                    -> (handle::Buffer<R, V>, Slice<R>) where
        V: Copy + pso::buffer::Structure<format::Format>,
        I: ToIndexSlice<R>,
    {
        let buf = self.create_buffer_static(vd, BufferRole::Vertex);
        (buf, id.to_slice(self))
    }

    /// Create a constant buffer for `num` identical elements of type `T`.
    fn create_constant_buffer<T>(&mut self, num: usize) -> handle::Buffer<R, T> {
        self.create_buffer_dynamic(num, BufferRole::Uniform)
    }

    /// Create a shader set from a given vs/ps code for multiple shader models.
    fn create_shader_set(&mut self, vs_code: &[u8], ps_code: &[u8])
                         -> Result<ShaderSet<R>, ProgramError> {
        let vs = match self.create_shader_vertex(vs_code) {
            Ok(s) => s,
            Err(e) => return Err(ProgramError::Vertex(e)),
        };
        let ps = match self.create_shader_pixel(ps_code) {
            Ok(s) => s,
            Err(e) => return Err(ProgramError::Pixel(e)),
        };
        Ok(ShaderSet::Simple(vs, ps))
    }

    /// Create a simple program given a vertex shader with a pixel one.
    fn link_program(&mut self, vs_code: &[u8], ps_code: &[u8])
                    -> Result<handle::Program<R>, ProgramError> {

        let set = try!(self.create_shader_set(vs_code, ps_code));
        self.create_program(&set)
            .map_err(|e| ProgramError::Link(e))
    }

    /// Create a simple program given `ShaderSource` versions of vertex and
    /// pixel shaders, automatically picking available shader variant.
    fn link_program_source(&mut self, vs_src: ShaderSource, ps_src: ShaderSource)
                           -> Result<handle::Program<R>, ProgramError> {
        use gfx_core::shade::CreateShaderError;
        let model = self.get_capabilities().shader_model;

        match (vs_src.choose(model), ps_src.choose(model)) {
            (Ok(vs_code), Ok(ps_code)) => self.link_program(vs_code, ps_code),
            (Err(_), Ok(_)) => Err(ProgramError::Vertex(CreateShaderError::ModelNotSupported)),
            (_, Err(_)) => Err(ProgramError::Pixel(CreateShaderError::ModelNotSupported)),
        }
    }

    /// Create a strongly-typed Pipeline State.
    fn create_pipeline_state<I: pso::PipelineInit>(&mut self, shaders: &ShaderSet<R>,
                             primitive: Primitive, rasterizer: Rasterizer, init: I)
                             -> Result<pso::PipelineState<R, I::Meta>, PipelineStateError>
    {
        let program = match self.create_program(shaders) {
            Ok(p) => p,
            Err(e) => return Err(PipelineStateError::Program(ProgramError::Link(e))),
        };
        let mut descriptor = Descriptor::new(primitive, rasterizer);
        let meta = match init.link_to(&mut descriptor, program.get_info()) {
            Ok(m) => m,
            Err(e) => return Err(PipelineStateError::DescriptorInit(e)),
        };
        let raw = match self.create_pipeline_state_raw(&program, &descriptor) {
            Ok(raw) => raw,
            Err(e) => return Err(PipelineStateError::DeviceCreate(e)),
        };

        Ok(pso::PipelineState::new(raw, primitive, meta))
    }

    /// Create a simplified version of the Pipeline State,
    /// which works on triangles, and only has VS and PS shaders in it.
    fn create_pipeline_simple<I: pso::PipelineInit>(&mut self, vs: &[u8], ps: &[u8], cull: CullFace, init: I)
                              -> Result<pso::PipelineState<R, I::Meta>, PipelineStateError>
    {
        match self.create_shader_set(vs, ps) {
            Ok(ref s) => self.create_pipeline_state(s,
                Primitive::TriangleList, Rasterizer::new_fill(cull), init),
            Err(e) => Err(PipelineStateError::Program(e)),
        }
    }

    /// Create a linear sampler with clamping to border.
    fn create_sampler_linear(&mut self) -> handle::Sampler<R> {
        self.create_sampler(tex::SamplerInfo::new(
            tex::FilterMethod::Trilinear,
            tex::WrapMode::Clamp,
        ))
    }
}

impl<R: Resources, F: Factory<R>> FactoryExt<R> for F {}
<commit_msg>Added create_pipeline_from_program helper<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Factory extension. Provides resource construction shortcuts.

use gfx_core::{format, handle, tex};
use gfx_core::{Primitive, Resources, ShaderSet, VertexCount};
use gfx_core::factory::{BufferRole, Factory};
use gfx_core::pso::{CreationError, Descriptor};
use gfx_core::state::{CullFace, Rasterizer};
use encoder::Encoder;
use mesh::{Slice, SliceKind, ToIndexSlice};
use pso;
use shade::{ProgramError, ShaderSource};

/// Error creating a PipelineState
#[derive(Clone, PartialEq, Debug)]
pub enum PipelineStateError {
    /// Shader program failed to link.
    Program(ProgramError),
    /// Unable to create PSO descriptor due to mismatched formats.
    DescriptorInit(pso::InitError),
    /// Device failed to create the handle give the descriptor.
    DeviceCreate(CreationError),
}

/// Factory extension trait
pub trait FactoryExt<R: Resources>: Factory<R> + Sized {
    /// Create a new graphics command Encoder
    fn create_encoder(&mut self) -> Encoder<R, Self::CommandBuffer> {
        Encoder::create(self)
    }

    /// Create a vertex buffer with an associated slice.
    fn create_vertex_buffer<T>(&mut self, data: &[T])
                            -> (handle::Buffer<R, T>, Slice<R>) where
                            T: Copy + pso::buffer::Structure<format::Format>
    {
        let nv = data.len();
        //debug_assert!(nv <= self.get_capabilities().max_vertex_count);
        let buf = self.create_buffer_static(data, BufferRole::Vertex);
        (buf, Slice {
            start: 0,
            end: nv as VertexCount,
            instances: None,
            kind: SliceKind::Vertex,
        })
    }

    /// Create a vertex buffer with an index, returned by a slice.
    fn create_vertex_buffer_indexed<V, I>(&mut self, vd: &[V], id: I)
                                    -> (handle::Buffer<R, V>, Slice<R>) where
        V: Copy + pso::buffer::Structure<format::Format>,
        I: ToIndexSlice<R>,
    {
        let buf = self.create_buffer_static(vd, BufferRole::Vertex);
        (buf, id.to_slice(self))
    }

    /// Create a constant buffer for `num` identical elements of type `T`.
    fn create_constant_buffer<T>(&mut self, num: usize) -> handle::Buffer<R, T> {
        self.create_buffer_dynamic(num, BufferRole::Uniform)
    }

    /// Create a shader set from a given vs/ps code for multiple shader models.
    fn create_shader_set(&mut self, vs_code: &[u8], ps_code: &[u8])
                         -> Result<ShaderSet<R>, ProgramError> {
        let vs = match self.create_shader_vertex(vs_code) {
            Ok(s) => s,
            Err(e) => return Err(ProgramError::Vertex(e)),
        };
        let ps = match self.create_shader_pixel(ps_code) {
            Ok(s) => s,
            Err(e) => return Err(ProgramError::Pixel(e)),
        };
        Ok(ShaderSet::Simple(vs, ps))
    }

    /// Create a simple program given a vertex shader with a pixel one.
    fn link_program(&mut self, vs_code: &[u8], ps_code: &[u8])
                    -> Result<handle::Program<R>, ProgramError> {

        let set = try!(self.create_shader_set(vs_code, ps_code));
        self.create_program(&set)
            .map_err(|e| ProgramError::Link(e))
    }

    /// Create a simple program given `ShaderSource` versions of vertex and
    /// pixel shaders, automatically picking available shader variant.
    fn link_program_source(&mut self, vs_src: ShaderSource, ps_src: ShaderSource)
                           -> Result<handle::Program<R>, ProgramError> {
        use gfx_core::shade::CreateShaderError;
        let model = self.get_capabilities().shader_model;

        match (vs_src.choose(model), ps_src.choose(model)) {
            (Ok(vs_code), Ok(ps_code)) => self.link_program(vs_code, ps_code),
            (Err(_), Ok(_)) => Err(ProgramError::Vertex(CreateShaderError::ModelNotSupported)),
            (_, Err(_)) => Err(ProgramError::Pixel(CreateShaderError::ModelNotSupported)),
        }
    }

    /// Create a strongly-typed Pipeline State.
    fn create_pipeline_state<I: pso::PipelineInit>(&mut self, shaders: &ShaderSet<R>,
                             primitive: Primitive, rasterizer: Rasterizer, init: I)
                             -> Result<pso::PipelineState<R, I::Meta>, PipelineStateError>
    {
        match self.create_program(shaders) {
            Ok(p) => self.create_pipeline_from_program(&p, primitive, rasterizer, init),
            Err(e) => Err(PipelineStateError::Program(ProgramError::Link(e))),
        }
    }

    /// Create PSO with a given program.
    fn create_pipeline_from_program<I: pso::PipelineInit>(&mut self, program: &handle::Program<R>,
                                    primitive: Primitive, rasterizer: Rasterizer, init: I)
                                    -> Result<pso::PipelineState<R, I::Meta>, PipelineStateError>
    {
        let mut descriptor = Descriptor::new(primitive, rasterizer);
        let meta = match init.link_to(&mut descriptor, program.get_info()) {
            Ok(m) => m,
            Err(e) => return Err(PipelineStateError::DescriptorInit(e)),
        };
        let raw = match self.create_pipeline_state_raw(program, &descriptor) {
            Ok(raw) => raw,
            Err(e) => return Err(PipelineStateError::DeviceCreate(e)),
        };

        Ok(pso::PipelineState::new(raw, primitive, meta))
    }

    /// Create a simplified version of the Pipeline State,
    /// which works on triangles, and only has VS and PS shaders in it.
    fn create_pipeline_simple<I: pso::PipelineInit>(&mut self, vs: &[u8], ps: &[u8], cull: CullFace, init: I)
                              -> Result<pso::PipelineState<R, I::Meta>, PipelineStateError>
    {
        match self.create_shader_set(vs, ps) {
            Ok(ref s) => self.create_pipeline_state(s,
                Primitive::TriangleList, Rasterizer::new_fill(cull), init),
            Err(e) => Err(PipelineStateError::Program(e)),
        }
    }

    /// Create a linear sampler with clamping to border.
    fn create_sampler_linear(&mut self) -> handle::Sampler<R> {
        self.create_sampler(tex::SamplerInfo::new(
            tex::FilterMethod::Trilinear,
            tex::WrapMode::Clamp,
        ))
    }
}

impl<R: Resources, F: Factory<R>> FactoryExt<R> for F {}
<|endoftext|>


<commit_before>//! rustbuild, the Rust build system
//!
//! This is the entry point for the build system used to compile the `rustc`
//! compiler. Lots of documentation can be found in the `README.md` file in the
//! parent directory, and otherwise documentation can be found throughout the `build`
//! directory in each respective module.

use std::env;

use bootstrap::{Build, Config};

fn main() {
    let args = env::args().skip(1).collect::<Vec<_>>();
    let config = Config::parse(&args);

    let changelog_suggestion = check_version(&config);
    if let Some(suggestion) = &changelog_suggestion {
        println!("{}", suggestion);
    }

    Build::new(config).build();

    if let Some(suggestion) = changelog_suggestion {
        println!("{}", suggestion);
        println!("note: this message was printed twice to make it more likely to be seen");
    }
}

fn check_version(config: &Config) -> Option<String> {
    const VERSION: usize = 1;

    let mut msg = String::new();

    let suggestion = if let Some(seen) = config.changelog_seen {
        if seen != VERSION {
            msg.push_str("warning: there have been changes to x.py since you last updated.\n");
            format!("update `config.toml` to use `changelog-seen = {}` instead", VERSION)
        } else {
            return None;
        }
    } else {
        msg.push_str("warning: x.py has made several changes recently you may want to look at\n");
        format!("add `changelog-seen = {}` to `config.toml`", VERSION)
    };

    msg.push_str("help: consider looking at the changes in `src/bootstrap/CHANGELOG.md`\n");
    msg.push_str("note: to silence this warning, ");
    msg.push_str(&suggestion);

    Some(msg)
}
<commit_msg>clarify that `changelog-seen = 1` goes to the beginning of config.toml<commit_after>//! rustbuild, the Rust build system
//!
//! This is the entry point for the build system used to compile the `rustc`
//! compiler. Lots of documentation can be found in the `README.md` file in the
//! parent directory, and otherwise documentation can be found throughout the `build`
//! directory in each respective module.

use std::env;

use bootstrap::{Build, Config};

fn main() {
    let args = env::args().skip(1).collect::<Vec<_>>();
    let config = Config::parse(&args);

    let changelog_suggestion = check_version(&config);
    if let Some(suggestion) = &changelog_suggestion {
        println!("{}", suggestion);
    }

    Build::new(config).build();

    if let Some(suggestion) = changelog_suggestion {
        println!("{}", suggestion);
        println!("note: this message was printed twice to make it more likely to be seen");
    }
}

fn check_version(config: &Config) -> Option<String> {
    const VERSION: usize = 1;

    let mut msg = String::new();

    let suggestion = if let Some(seen) = config.changelog_seen {
        if seen != VERSION {
            msg.push_str("warning: there have been changes to x.py since you last updated.\n");
            format!("update `config.toml` to use `changelog-seen = {}` instead", VERSION)
        } else {
            return None;
        }
    } else {
        msg.push_str("warning: x.py has made several changes recently you may want to look at\n");
        format!("add `changelog-seen = {}` at the top of `config.toml`", VERSION)
    };

    msg.push_str("help: consider looking at the changes in `src/bootstrap/CHANGELOG.md`\n");
    msg.push_str("note: to silence this warning, ");
    msg.push_str(&suggestion);

    Some(msg)
}
<|endoftext|>


<commit_before>extern crate syntax;
extern crate rustc;
extern crate rustc_front;
extern crate rustc_driver;
extern crate rustc_resolve as resolve;
extern crate rustc_typeck as typeck;

use self::syntax::{codemap, diagnostic};
pub use self::syntax::diagnostic::Level;
use self::rustc::front::map as hir_map;
use self::rustc::front::map::NodePrinter;
use self::rustc_front::lowering::{lower_crate, LoweringContext};
use self::rustc_front::print::pprust;
use self::rustc::session::{self, config};
use self::rustc::metadata::creader::LocalCrateReader;
use self::rustc::middle::{self, stability, ty};
use self::rustc_driver::driver;

//use std::cell::RefCell;
use std::env;
use std::collections::HashMap;
use std::ops::Range;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str;
use std::sync::{Arc, Weak};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread;

#[cfg(windows)]
const EXE_SUFFIX: &'static str = "exe";
#[cfg(not(windows))]
const EXE_SUFFIX: &'static str = "";

fn get_rustc_dir_path() -> PathBuf {
    if cfg!(windows) {
        env::current_exe().unwrap().parent().unwrap().to_path_buf()
    } else {
        let out = Command::new("which").arg("rustc").output().unwrap();
        if !out.status.success() {
            panic!("Failed to get rustc path: {}", String::from_utf8(out.stderr).unwrap());
        }
        Path::new(str::from_utf8(&out.stdout).unwrap().trim()).parent().unwrap().to_path_buf()
    }
}

pub fn init_env() {
    if cfg!(windows) {
        // Set up %PATH% to be able to run the bundled `rustc.exe`.
        if let Some(path) = env::var_os("PATH") {
            let mut paths = env::split_paths(&path).collect::<Vec<_>>();
            paths.push(get_rustc_dir_path());
            let new_path = env::join_paths(paths.iter()).unwrap();
            env::set_var("PATH", &new_path);
        }
    }
}

pub fn compile_and_run(path: &Path) {
    let path = env::current_dir().unwrap().join(path);
    assert!(path.is_absolute());
    let exe = path.with_extension(EXE_SUFFIX);

    // There seems to be a bug that Rust programs (including `rustc.exe`) ran with inherited
    // std{in,out,err} via `.status()` or `.spawn()` produce a "`xyz.exe` has stopped working"
    // message unconditionally.
    if cfg!(windows) {
        let out = Command::new("rustc").arg(&path).arg("-o").arg(&exe).output().unwrap();
        println!("{}\n{}", String::from_utf8(out.stdout).unwrap(), String::from_utf8(out.stderr).unwrap());
        if !out.status.success() {
            println!("compilation failed");
        } else {
            match Command::new(&exe).output() {
                Err(e) => {
                    println!("failed to execute `{:?}`: {}", exe, e);
                }
                Ok(out) => {
                    println!("{}\n{}", String::from_utf8(out.stdout).unwrap(),
                                       String::from_utf8(out.stderr).unwrap());
                }
            }
        }
    } else {
        if let Ok(status) = Command::new("rustc").arg(&path).arg("-o").arg(&exe).status() {
            if status.success() {
                if let Err(e) = Command::new(&exe).spawn() {
                    println!("failed to execute `{:?}`: {}", exe, e);
                }
            }
        }
    }
}

enum Req {
    TypesAtOffset(usize, Range<usize>)
}

enum Res {
    Done,
    Aborted,
    Diagnostic(Diagnostic),
    TypesAtOffset(usize, Vec<(Range<usize>, String)>)
}

struct Diagnostic {
    line: usize,
    col: usize,
    level: Level,
    message: String
}

struct ErrorLogger {
    tx: Sender<Res>,
    file_end: usize
}

impl diagnostic::Emitter for ErrorLogger {
    fn emit(&mut self,
            cmsp: Option<(&codemap::CodeMap, codemap::Span)>,
            msg: &str, _code: Option<&str>, lvl: Level) {
        if msg.starts_with("aborting due to ") {
            return;
        }
        let (line, col) = match cmsp {
            Some((codemap, sp)) => {
                if sp.hi.0 as usize <= self.file_end {
                    let pos = codemap.lookup_char_pos(sp.lo);
                    (pos.line - 1, pos.col.0)
                } else {
                    (0, 0)
                }
            }
            None => (0, 0)
        };
        let _ = self.tx.send(Res::Diagnostic(Diagnostic {
            line: line,
            col: col,
            level: lvl,
            message: msg.to_owned()
        }));
    }

    fn custom_emit(&mut self, cm: &codemap::CodeMap,
                   sp: diagnostic::RenderSpan, msg: &str, lvl: Level) {
        let sp = match sp {
            diagnostic::FullSpan(s) | diagnostic::FileLine(s) |
            diagnostic::EndSpan(s) | diagnostic::Suggestion(s, _)  => s
        };
        self.emit(Some((cm, sp)), msg, None, lvl);
    }
}

fn rustc_thread(input: String, mut lifeline: Arc<()>, rx: Receiver<Req>, tx: Sender<Res>, emitter: ErrorLogger) {
    macro_rules! still_alive {
        () => (lifeline = match Weak::upgrade(&Arc::downgrade(&{lifeline})) {
                Some(x) => x, None => return
        })
    }
    let input = config::Input::Str(input);

    let rustc_dir_path = get_rustc_dir_path();

    let sessopts = config::Options {
        maybe_sysroot: Some(rustc_dir_path.parent().unwrap().to_path_buf()),
        ..config::basic_options().clone()
    };

    let codemap = codemap::CodeMap::new();
    let diagnostic_handler = diagnostic::Handler::with_emitter(true, Box::new(emitter));
    let span_diagnostic_handler = diagnostic::SpanHandler::new(diagnostic_handler, codemap);

    let sess = session::build_session_(sessopts,
                                       None,
                                       span_diagnostic_handler);

    let cfg = config::build_configuration(&sess);

    still_alive!();
    let krate = driver::phase_1_parse_input(&sess, cfg, &input);

    still_alive!();
    let krate = driver::phase_2_configure_and_expand(&sess, krate, "r3", None)
        .expect("phase_2_configure_and_expand aborted");

    still_alive!();
    let krate = driver::assign_node_ids(&sess, krate);

    let lcx = LoweringContext::new(&sess, Some(&krate));
    let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate));
    let arenas = ty::CtxtArenas::new();

    still_alive!();
    let hir_map = hir_map::map_crate(&mut hir_forest);
    let krate = hir_map.krate();

    still_alive!();
    LocalCrateReader::new(&sess, &hir_map).read_crates(krate);
    let lang_items = middle::lang_items::collect_language_items(&sess, &hir_map);

    still_alive!();
    let resolve::CrateMap {
        def_map,
        freevars,
        trait_map,
        ..
    } = resolve::resolve_crate(&sess,
                               &hir_map,
                               resolve::MakeGlobMap::No);

    // Discard MTWT tables that aren't required past resolution.
    syntax::ext::mtwt::clear_tables();

    still_alive!();
    let named_region_map = middle::resolve_lifetime::krate(&sess, krate, &def_map);

    still_alive!();
    let region_map = middle::region::resolve_crate(&sess, krate);

    //middle::check_loop::check_crate(&sess, krate);

    //middle::check_static_recursion::check_crate(&sess, krate, &def_map, &hir_map);

    still_alive!();
    ty::ctxt::create_and_enter(&sess,
                               &arenas,
                               def_map,
                               named_region_map,
                               hir_map,
                               freevars,
                               region_map,
                               lang_items,
                               stability::Index::new(krate), |tcx| {
        /*typeck::collect::collect_item_types(tcx);
        tcx.sess.abort_if_errors();

        still_alive!();
        typeck::variance::infer_variance(tcx);

        still_alive!();
        let ccx = typeck::CrateCtxt {
            trait_map: trait_map,
            all_traits: RefCell::new(None),
            tcx: tcx
        };
        typeck::coherence::check_coherence(&ccx);*/
        typeck::check_crate(tcx, trait_map);

        let _ = tx.send(Res::Done);

        for req in rx.iter() {
            still_alive!();
            match req {
                Req::TypesAtOffset(offset, line) => {
                    let mut out = vec![];
                    for (&id, ty) in tcx.node_types().iter() {
                        let node =  if let Some(node) = tcx.map.find(id) {
                            node
                        } else {
                            continue;
                        };
                        // Avoid statements, they're always ().
                        if let hir_map::NodeStmt(_) = node {
                            continue;
                        }
                        if let Some(sp) = tcx.map.opt_span(id) {
                            /*
                            // Avoid peeking at macro expansions.
                            if sp.expn_id != codemap::NO_EXPANSION {
                                continue;
                            }*/

                            let (lo, hi) = (sp.lo.0 as usize, sp.hi.0 as usize);
                            if line.start <= lo && lo <= offset && offset <= hi && hi <= line.end {
                                match node {
                                    // These cannot be reliably printed.
                                    hir_map::NodeLocal(_) | hir_map::NodeStructCtor(_) => {}
                                    // There is an associated NodeExpr(ExprBlock) where this actually matters.
                                    hir_map::NodeBlock(_) => continue,
                                    _ => {
                                        let node_string = pprust::to_string(|s| s.print_node(&node));
                                        let span_string = tcx.sess.codemap().span_to_snippet(sp).unwrap();
                                        let is_macro = regex!(r"^\w+\s*!\s*[\(\[\{]").is_match(&span_string);
                                        if !is_macro && node_string.replace(" ", "") != span_string.replace(" ", "") {
                                            continue;
                                        }
                                    }
                                }
                                let clean = regex!(concat![r"\b(",
                                    "core::(option::Option|result::Result)|",
                                    "collections::(vec::Vec|string::String)",
                                r")\b"]);
                                let ty_string = clean.replace_all(&ty.to_string(), |c: &::regex::Captures| {
                                    c.at(0).unwrap().split(':').next_back().unwrap().to_owned()
                                });
                                out.push((lo-line.start..hi-line.start, ty_string));
                            }
                        }
                    }
                    let _ = tx.send(Res::TypesAtOffset(offset, out));
                }
            }
        }
    });
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub enum State {
    Compiling,
    Aborted,
    Waiting,
    TypesAtOffset(usize)
}

pub struct Rustc {
    pub file_end: usize,
    _lifeline: Arc<()>,
    req_tx: Sender<Req>,
    res_rx: Receiver<Res>,
    pub state: State,
    // True if error.
    pub diagnostics: HashMap<usize, Vec<(Level, usize, String)>>,
    pub errors: usize,
    pub types_at_offset: Option<Vec<(Range<usize>, String)>>
}

impl Rustc {
    pub fn start(input: String) -> Rustc {
        let lifeline = Arc::new(());
        let lifeline2 = lifeline.clone();
        let (req_tx, req_rx) = channel();
        let (res_tx, res_rx) = channel();
        let input_len = input.len();
        thread::spawn(move || {
            let res_tx2 = res_tx.clone();
            let res = thread::catch_panic(move || {
                rustc_thread(input, lifeline2, req_rx, res_tx.clone(), ErrorLogger {
                    tx: res_tx,
                    file_end: input_len
                });
            });
            if res.is_err() {
                let _ = res_tx2.send(Res::Aborted);
            }
        });
        Rustc {
            file_end: input_len,
            _lifeline: lifeline,
            req_tx: req_tx,
            res_rx: res_rx,
            state: State::Compiling,
            diagnostics: HashMap::new(),
            errors: 0,
            types_at_offset: None
        }
    }

    pub fn update(&mut self) -> bool {
        let mut dirty = false;
        while let Ok(res) = self.res_rx.try_recv() {
            match res {
                Res::Done => {
                    assert_eq!(self.state, State::Compiling);
                    self.state = State::Waiting;
                }
                Res::Aborted => {
                    assert!(self.errors > 0, "aborted without errors?!");
                    self.state = State::Aborted;
                }
                Res::Diagnostic(d) => {
                     match d.level {
                        Level::Bug | Level::Fatal | Level::Error => {
                            self.errors += 1;
                        }
                        _ => {}
                    }
                    self.diagnostics.entry(d.line).or_insert(vec![]).push((d.level, d.col, d.message));
                    dirty = true;
                }
                Res::TypesAtOffset(offset, result) => {
                    if self.state == State::TypesAtOffset(offset) {
                        self.state = State::Waiting;
                        self.types_at_offset = Some(result);
                        dirty = true;
                    }
                }
            }
        }
        dirty
    }

    pub fn types_at_offset(&mut self, offset: usize, line: Range<usize>) {
        self.types_at_offset = None;
        self.state = State::TypesAtOffset(offset);
        let _ = self.req_tx.send(Req::TypesAtOffset(offset, line));
    }
}
<commit_msg>Fix rustc support after repeated rustup.<commit_after>extern crate syntax;
extern crate rustc;
extern crate rustc_front;
extern crate rustc_driver;
extern crate rustc_resolve as resolve;
extern crate rustc_typeck as typeck;

use self::syntax::{codemap, diagnostic};
pub use self::syntax::diagnostic::Level;
use self::rustc::front::map as hir_map;
use self::rustc::front::map::NodePrinter;
use self::rustc_front::lowering::{lower_crate, LoweringContext};
use self::rustc_front::print::pprust;
use self::rustc::session::{self, config};
use self::rustc::metadata::creader::LocalCrateReader;
use self::rustc::middle::{self, stability, ty};
use self::rustc_driver::driver;

//use std::cell::RefCell;
use std::env;
use std::collections::HashMap;
use std::ops::Range;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str;
use std::sync::{Arc, Weak};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread;

#[cfg(windows)]
const EXE_SUFFIX: &'static str = "exe";
#[cfg(not(windows))]
const EXE_SUFFIX: &'static str = "";

fn get_rustc_dir_path() -> PathBuf {
    if cfg!(windows) {
        env::current_exe().unwrap().parent().unwrap().to_path_buf()
    } else {
        let out = Command::new("which").arg("rustc").output().unwrap();
        if !out.status.success() {
            panic!("Failed to get rustc path: {}", String::from_utf8(out.stderr).unwrap());
        }
        Path::new(str::from_utf8(&out.stdout).unwrap().trim()).parent().unwrap().to_path_buf()
    }
}

pub fn init_env() {
    if cfg!(windows) {
        // Set up %PATH% to be able to run the bundled `rustc.exe`.
        if let Some(path) = env::var_os("PATH") {
            let mut paths = env::split_paths(&path).collect::<Vec<_>>();
            paths.push(get_rustc_dir_path());
            let new_path = env::join_paths(paths.iter()).unwrap();
            env::set_var("PATH", &new_path);
        }
    }
}

pub fn compile_and_run(path: &Path) {
    let path = env::current_dir().unwrap().join(path);
    assert!(path.is_absolute());
    let exe = path.with_extension(EXE_SUFFIX);

    // There seems to be a bug that Rust programs (including `rustc.exe`) ran with inherited
    // std{in,out,err} via `.status()` or `.spawn()` produce a "`xyz.exe` has stopped working"
    // message unconditionally.
    if cfg!(windows) {
        let out = Command::new("rustc").arg(&path).arg("-o").arg(&exe).output().unwrap();
        println!("{}\n{}", String::from_utf8(out.stdout).unwrap(), String::from_utf8(out.stderr).unwrap());
        if !out.status.success() {
            println!("compilation failed");
        } else {
            match Command::new(&exe).output() {
                Err(e) => {
                    println!("failed to execute `{:?}`: {}", exe, e);
                }
                Ok(out) => {
                    println!("{}\n{}", String::from_utf8(out.stdout).unwrap(),
                                       String::from_utf8(out.stderr).unwrap());
                }
            }
        }
    } else {
        if let Ok(status) = Command::new("rustc").arg(&path).arg("-o").arg(&exe).status() {
            if status.success() {
                if let Err(e) = Command::new(&exe).spawn() {
                    println!("failed to execute `{:?}`: {}", exe, e);
                }
            }
        }
    }
}

enum Req {
    TypesAtOffset(usize, Range<usize>)
}

enum Res {
    Done,
    Aborted,
    Diagnostic(Diagnostic),
    TypesAtOffset(usize, Vec<(Range<usize>, String)>)
}

struct Diagnostic {
    line: usize,
    col: usize,
    level: Level,
    message: String
}

struct ErrorLogger {
    tx: Sender<Res>,
    file_end: usize
}

impl diagnostic::Emitter for ErrorLogger {
    fn emit(&mut self,
            cmsp: Option<(&codemap::CodeMap, codemap::Span)>,
            msg: &str, _code: Option<&str>, lvl: Level) {
        if msg.starts_with("aborting due to ") {
            return;
        }
        let (line, col) = match cmsp {
            Some((codemap, sp)) => {
                if sp.hi.0 as usize <= self.file_end {
                    let pos = codemap.lookup_char_pos(sp.lo);
                    (pos.line - 1, pos.col.0)
                } else {
                    (0, 0)
                }
            }
            None => (0, 0)
        };
        let _ = self.tx.send(Res::Diagnostic(Diagnostic {
            line: line,
            col: col,
            level: lvl,
            message: msg.to_owned()
        }));
    }

    fn custom_emit(&mut self, cm: &codemap::CodeMap,
                   sp: diagnostic::RenderSpan, msg: &str, lvl: Level) {
        let sp = match sp {
            diagnostic::FullSpan(s) | diagnostic::FileLine(s) |
            diagnostic::EndSpan(s) | diagnostic::Suggestion(s, _)  => s
        };
        self.emit(Some((cm, sp)), msg, None, lvl);
    }
}

fn rustc_thread(input: String, mut lifeline: Arc<()>, rx: Receiver<Req>, tx: Sender<Res>, emitter: ErrorLogger) {
    macro_rules! still_alive {
        () => (lifeline = match Weak::upgrade(&Arc::downgrade(&{lifeline})) {
                Some(x) => x, None => return
        })
    }
    let input = config::Input::Str(input);

    let rustc_dir_path = get_rustc_dir_path();

    let sessopts = config::Options {
        maybe_sysroot: Some(rustc_dir_path.parent().unwrap().to_path_buf()),
        ..config::basic_options().clone()
    };

    let codemap = codemap::CodeMap::new();
    let diagnostic_handler = diagnostic::Handler::with_emitter(true, Box::new(emitter));
    let span_diagnostic_handler = diagnostic::SpanHandler::new(diagnostic_handler, codemap);

    let sess = session::build_session_(sessopts,
                                       None,
                                       span_diagnostic_handler);

    let cfg = config::build_configuration(&sess);

    still_alive!();
    let krate = driver::phase_1_parse_input(&sess, cfg, &input);

    still_alive!();
    let krate = driver::phase_2_configure_and_expand(&sess, krate, "r3", None)
        .expect("phase_2_configure_and_expand aborted");

    still_alive!();
    let krate = driver::assign_node_ids(&sess, krate);

    let lcx = LoweringContext::new(&sess, Some(&krate));
    let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate));
    let arenas = ty::CtxtArenas::new();

    still_alive!();
    let hir_map = hir_map::map_crate(&mut hir_forest);
    let krate = hir_map.krate();

    still_alive!();
    LocalCrateReader::new(&sess, &hir_map).read_crates(krate);
    let lang_items = middle::lang_items::collect_language_items(&sess, &hir_map);

    still_alive!();
    let resolve::CrateMap {
        def_map,
        freevars,
        trait_map,
        ..
    } = resolve::resolve_crate(&sess,
                               &hir_map,
                               resolve::MakeGlobMap::No);

    // Discard MTWT tables that aren't required past resolution.
    syntax::ext::mtwt::clear_tables();

    still_alive!();
    let named_region_map = middle::resolve_lifetime::krate(&sess, krate, &def_map.borrow());

    still_alive!();
    let region_map = middle::region::resolve_crate(&sess, krate);

    //middle::check_loop::check_crate(&sess, krate);

    //middle::check_static_recursion::check_crate(&sess, krate, &def_map, &hir_map);

    still_alive!();
    ty::ctxt::create_and_enter(&sess,
                               &arenas,
                               def_map,
                               named_region_map,
                               hir_map,
                               freevars,
                               region_map,
                               lang_items,
                               stability::Index::new(krate), |tcx| {
        /*typeck::collect::collect_item_types(tcx);
        tcx.sess.abort_if_errors();

        still_alive!();
        typeck::variance::infer_variance(tcx);

        still_alive!();
        let ccx = typeck::CrateCtxt {
            trait_map: trait_map,
            all_traits: RefCell::new(None),
            tcx: tcx
        };
        typeck::coherence::check_coherence(&ccx);*/
        typeck::check_crate(tcx, trait_map);

        let _ = tx.send(Res::Done);

        for req in rx.iter() {
            still_alive!();
            match req {
                Req::TypesAtOffset(offset, line) => {
                    let mut out = vec![];
                    for (&id, ty) in tcx.node_types().iter() {
                        let node =  if let Some(node) = tcx.map.find(id) {
                            node
                        } else {
                            continue;
                        };
                        // Avoid statements, they're always ().
                        if let hir_map::NodeStmt(_) = node {
                            continue;
                        }
                        if let Some(sp) = tcx.map.opt_span(id) {
                            /*
                            // Avoid peeking at macro expansions.
                            if sp.expn_id != codemap::NO_EXPANSION {
                                continue;
                            }*/

                            let (lo, hi) = (sp.lo.0 as usize, sp.hi.0 as usize);
                            if line.start <= lo && lo <= offset && offset <= hi && hi <= line.end {
                                match node {
                                    // These cannot be reliably printed.
                                    hir_map::NodeLocal(_) | hir_map::NodeStructCtor(_) => {}
                                    // There is an associated NodeExpr(ExprBlock) where this actually matters.
                                    hir_map::NodeBlock(_) => continue,
                                    _ => {
                                        let node_string = pprust::to_string(|s| s.print_node(&node));
                                        let span_string = tcx.sess.codemap().span_to_snippet(sp).unwrap();
                                        let is_macro = regex!(r"^\w+\s*!\s*[\(\[\{]").is_match(&span_string);
                                        if !is_macro && node_string.replace(" ", "") != span_string.replace(" ", "") {
                                            continue;
                                        }
                                    }
                                }
                                let clean = regex!(concat![r"\b(",
                                    "core::(option::Option|result::Result)|",
                                    "collections::(vec::Vec|string::String)",
                                r")\b"]);
                                let ty_string = clean.replace_all(&ty.to_string(), |c: &::regex::Captures| {
                                    c.at(0).unwrap().split(':').next_back().unwrap().to_owned()
                                });
                                out.push((lo-line.start..hi-line.start, ty_string));
                            }
                        }
                    }
                    let _ = tx.send(Res::TypesAtOffset(offset, out));
                }
            }
        }
    });
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub enum State {
    Compiling,
    Aborted,
    Waiting,
    TypesAtOffset(usize)
}

pub struct Rustc {
    pub file_end: usize,
    _lifeline: Arc<()>,
    req_tx: Sender<Req>,
    res_rx: Receiver<Res>,
    pub state: State,
    // True if error.
    pub diagnostics: HashMap<usize, Vec<(Level, usize, String)>>,
    pub errors: usize,
    pub types_at_offset: Option<Vec<(Range<usize>, String)>>
}

impl Rustc {
    pub fn start(input: String) -> Rustc {
        let lifeline = Arc::new(());
        let lifeline2 = lifeline.clone();
        let (req_tx, req_rx) = channel();
        let (res_tx, res_rx) = channel();
        let input_len = input.len();
        thread::spawn(move || {
            let res_tx2 = res_tx.clone();
            let res = thread::catch_panic(move || {
                rustc_thread(input, lifeline2, req_rx, res_tx.clone(), ErrorLogger {
                    tx: res_tx,
                    file_end: input_len
                });
            });
            if res.is_err() {
                let _ = res_tx2.send(Res::Aborted);
            }
        });
        Rustc {
            file_end: input_len,
            _lifeline: lifeline,
            req_tx: req_tx,
            res_rx: res_rx,
            state: State::Compiling,
            diagnostics: HashMap::new(),
            errors: 0,
            types_at_offset: None
        }
    }

    pub fn update(&mut self) -> bool {
        let mut dirty = false;
        while let Ok(res) = self.res_rx.try_recv() {
            match res {
                Res::Done => {
                    assert_eq!(self.state, State::Compiling);
                    self.state = State::Waiting;
                }
                Res::Aborted => {
                    assert!(self.errors > 0, "aborted without errors?!");
                    self.state = State::Aborted;
                }
                Res::Diagnostic(d) => {
                     match d.level {
                        Level::Bug | Level::Fatal | Level::Error => {
                            self.errors += 1;
                        }
                        _ => {}
                    }
                    self.diagnostics.entry(d.line).or_insert(vec![]).push((d.level, d.col, d.message));
                    dirty = true;
                }
                Res::TypesAtOffset(offset, result) => {
                    if self.state == State::TypesAtOffset(offset) {
                        self.state = State::Waiting;
                        self.types_at_offset = Some(result);
                        dirty = true;
                    }
                }
            }
        }
        dirty
    }

    pub fn types_at_offset(&mut self, offset: usize, line: Range<usize>) {
        self.types_at_offset = None;
        self.state = State::TypesAtOffset(offset);
        let _ = self.req_tx.send(Req::TypesAtOffset(offset, line));
    }
}
<|endoftext|>


<commit_before>use std::ops::{Add, Sub, Mul};
use libc::{c_char, c_int, c_ulong, c_long, c_double, c_void};
use std::ffi::*;
use std::cmp::{Ordering};
use std::slice;
use std::sync::{Once, ONCE_INIT};

static EXACTINIT: Once = ONCE_INIT;

#[repr(C)]
#[derive(Debug, Clone, PartialEq)]
pub struct Point2D {
    x: c_double,
    y: c_double,
}

impl Point2D {
    fn new(x: c_double, y: c_double) -> Point2D {
        Point2D { x: x, y: y }
    }
}

#[repr(C)]
#[derive(Debug, Clone, PartialEq)]
pub struct Point3D {
    x: c_double,
    y: c_double,
    z: c_double,
}

impl Point3D {
    fn new(x: c_double, y: c_double, z: c_double) -> Point3D {
        Point3D { x: x, y: y, z: z }
    }
}

#[link(name = "predicates")]
extern "C" {
    fn exactinit() -> c_void;
    fn insphere(pa: *const Point3D, pb: *const Point3D, pc: *const Point3D, pd: *const Point3D, pe: *const Point3D) -> c_double;
    fn incircle(pa: *const Point2D, pb: *const Point2D, pc: *const Point2D, pd: *const Point2D) -> c_double;
}

fn init_predicates() {
    EXACTINIT.call_once(|| {
        unsafe { exactinit() };
    });
}

#[derive(Debug, Eq, PartialEq)]
pub enum InCircleLocation {
    Inside,
    Outside,
    On
}

pub trait InCircle<P> {
    fn in_circle_test(&self, point: &P) -> Option<InCircleLocation>;
}

pub struct Triangle<P> {
    p1: P,
    p2: P,
    p3: P,
}

pub struct Tetrahedron<P> {
    p1: P,
    p2: P,
    p3: P,
    p4: P,
}

impl InCircle<Point2D> for Triangle<Point2D> {
    fn in_circle_test(&self, point: &Point2D) -> Option<InCircleLocation> {
        init_predicates();

        let incircle_det = unsafe { incircle(&self.p1, &self.p2, &self.p3, point) };

        match 0.0.partial_cmp(&incircle_det) {
            Some(Ordering::Greater) => { Some(InCircleLocation::Inside) }
            Some(Ordering::Less) => { Some(InCircleLocation::Outside) }
            Some(Ordering::Equal) => { Some(InCircleLocation::On) }
            None => { None }
        }
    }
}

impl InCircle<Point3D> for Tetrahedron<Point3D> {
    fn in_circle_test(&self, point: &Point3D) -> Option<InCircleLocation> {
        init_predicates();

        let incircle_det = unsafe { insphere(&self.p1, &self.p2, &self.p3, &self.p4, point) };

        match 0.0.partial_cmp(&incircle_det) {
            Some(Ordering::Less) => { Some(InCircleLocation::Inside) }
            Some(Ordering::Greater) => { Some(InCircleLocation::Outside) }
            Some(Ordering::Equal) => { Some(InCircleLocation::On) }
            None => { None }
        }
    }
}

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

    use quickcheck::{TestResult, quickcheck};
    use std::f64::consts::{SQRT_2};

    #[test]
    fn in_circle_2d() {
        let p1 = Point2D::new(0.0, 0.0);
        let p2 = Point2D::new(0.0, 1.0);
        let p3 = Point2D::new(1.0, 1.0);
        let d_inside = Point2D::new(0.5, 0.5);
        let d_outside = Point2D::new(2.0, 0.0);
        let d_on = Point2D::new(1.0, 1.0);

        let t = Triangle { p1: p1, p2: p2, p3: p3 };

        assert_eq!(t.in_circle_test(&d_inside), Some(InCircleLocation::Inside));
        assert_eq!(t.in_circle_test(&d_outside), Some(InCircleLocation::Outside));
        assert_eq!(t.in_circle_test(&d_on), Some(InCircleLocation::On));
    }

    #[test]
    fn in_circle_3d() {
        let p1 = Point3D::new(-1.0,  1.0, -1.0);
        let p2 = Point3D::new( 1.0,  1.0, -1.0);
        let p3 = Point3D::new( 0.0, -1.0, -1.0);
        let p4 = Point3D::new( 0.0,  0.0,  1.0);
        let d_inside = Point3D::new(0.0, 0.0, 0.0);
        let d_outside = Point3D::new(10.0, 10.0, 10.0);
        let d_on = Point3D::new(0.0, 0.0, 1.0);

        let t = Tetrahedron { p1: p1, p2: p2, p3: p3, p4: p4 };

        assert_eq!(t.in_circle_test(&d_inside), Some(InCircleLocation::Inside));
        assert_eq!(t.in_circle_test(&d_outside), Some(InCircleLocation::Outside));
        assert_eq!(t.in_circle_test(&d_on), Some(InCircleLocation::On));
    }

}
<commit_msg>Renamed InCircle trait<commit_after>use std::ops::{Add, Sub, Mul};
use libc::{c_char, c_int, c_ulong, c_long, c_double, c_void};
use std::ffi::*;
use std::cmp::{Ordering};
use std::slice;
use std::sync::{Once, ONCE_INIT};

static EXACTINIT: Once = ONCE_INIT;

#[repr(C)]
#[derive(Debug, Clone, PartialEq)]
pub struct Point2D {
    x: c_double,
    y: c_double,
}

impl Point2D {
    fn new(x: c_double, y: c_double) -> Point2D {
        Point2D { x: x, y: y }
    }
}

#[repr(C)]
#[derive(Debug, Clone, PartialEq)]
pub struct Point3D {
    x: c_double,
    y: c_double,
    z: c_double,
}

impl Point3D {
    fn new(x: c_double, y: c_double, z: c_double) -> Point3D {
        Point3D { x: x, y: y, z: z }
    }
}

#[link(name = "predicates")]
extern "C" {
    fn exactinit() -> c_void;
    fn insphere(pa: *const Point3D, pb: *const Point3D, pc: *const Point3D, pd: *const Point3D, pe: *const Point3D) -> c_double;
    fn incircle(pa: *const Point2D, pb: *const Point2D, pc: *const Point2D, pd: *const Point2D) -> c_double;
}

fn init_predicates() {
    EXACTINIT.call_once(|| {
        unsafe { exactinit() };
    });
}

#[derive(Debug, Eq, PartialEq)]
pub enum InCircleLocation {
    Inside,
    Outside,
    On
}

pub trait InCircleTestable<P> {
    fn in_circle_test(&self, point: &P) -> Option<InCircleLocation>;
}

pub struct Triangle<P> {
    p1: P,
    p2: P,
    p3: P,
}

pub struct Tetrahedron<P> {
    p1: P,
    p2: P,
    p3: P,
    p4: P,
}

impl InCircleTestable<Point2D> for Triangle<Point2D> {
    fn in_circle_test(&self, point: &Point2D) -> Option<InCircleLocation> {
        init_predicates();

        let incircle_det = unsafe { incircle(&self.p1, &self.p2, &self.p3, point) };

        match 0.0.partial_cmp(&incircle_det) {
            Some(Ordering::Greater) => { Some(InCircleLocation::Inside) }
            Some(Ordering::Less) => { Some(InCircleLocation::Outside) }
            Some(Ordering::Equal) => { Some(InCircleLocation::On) }
            None => { None }
        }
    }
}

impl InCircleTestable<Point3D> for Tetrahedron<Point3D> {
    fn in_circle_test(&self, point: &Point3D) -> Option<InCircleLocation> {
        init_predicates();

        let incircle_det = unsafe { insphere(&self.p1, &self.p2, &self.p3, &self.p4, point) };

        match 0.0.partial_cmp(&incircle_det) {
            Some(Ordering::Less) => { Some(InCircleLocation::Inside) }
            Some(Ordering::Greater) => { Some(InCircleLocation::Outside) }
            Some(Ordering::Equal) => { Some(InCircleLocation::On) }
            None => { None }
        }
    }
}

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

    use quickcheck::{TestResult, quickcheck};
    use std::f64::consts::{SQRT_2};

    #[test]
    fn in_circle_2d() {
        let p1 = Point2D::new(0.0, 0.0);
        let p2 = Point2D::new(0.0, 1.0);
        let p3 = Point2D::new(1.0, 1.0);
        let d_inside = Point2D::new(0.5, 0.5);
        let d_outside = Point2D::new(2.0, 0.0);
        let d_on = Point2D::new(1.0, 1.0);

        let t = Triangle { p1: p1, p2: p2, p3: p3 };

        assert_eq!(t.in_circle_test(&d_inside), Some(InCircleLocation::Inside));
        assert_eq!(t.in_circle_test(&d_outside), Some(InCircleLocation::Outside));
        assert_eq!(t.in_circle_test(&d_on), Some(InCircleLocation::On));
    }

    #[test]
    fn in_circle_3d() {
        let p1 = Point3D::new(-1.0,  1.0, -1.0);
        let p2 = Point3D::new( 1.0,  1.0, -1.0);
        let p3 = Point3D::new( 0.0, -1.0, -1.0);
        let p4 = Point3D::new( 0.0,  0.0,  1.0);
        let d_inside = Point3D::new(0.0, 0.0, 0.0);
        let d_outside = Point3D::new(10.0, 10.0, 10.0);
        let d_on = Point3D::new(0.0, 0.0, 1.0);

        let t = Tetrahedron { p1: p1, p2: p2, p3: p3, p4: p4 };

        assert_eq!(t.in_circle_test(&d_inside), Some(InCircleLocation::Inside));
        assert_eq!(t.in_circle_test(&d_outside), Some(InCircleLocation::Outside));
        assert_eq!(t.in_circle_test(&d_on), Some(InCircleLocation::On));
    }

}
<|endoftext|>


<commit_before>extern crate rustbox;

use buffer::{Line, Buffer};
use cursor::Direction;
use cursor::Cursor;
use input::Input;
use uibuf::UIBuffer;

use utils;

pub struct CursorGuard<'a> {
    linenum: &'a mut uint,
    offset: &'a mut uint,
    cursor: Cursor<'a>,
}

impl<'a> Deref<Cursor<'a>> for CursorGuard<'a> {
    fn deref(&self) -> &Cursor<'a> {
        &self.cursor
    }
}

impl<'a> DerefMut<Cursor<'a>> for CursorGuard<'a> {
    fn deref_mut(&mut self) -> &mut Cursor<'a> {
        &mut self.cursor
    }
}

#[unsafe_destructor]
impl<'a> Drop for CursorGuard<'a> {
    fn drop(&mut self) {
        // Update line number and offset
        *self.linenum = self.cursor.get_linenum();
        *self.offset = self.cursor.get_offset();
    }
}

/// A View is an abstract Window (into a Buffer).
///
/// It draws a portion of a Buffer to a UIBuffer which in turn is drawn to the
/// screen. It maintains the status bar for the current view, the "dirty status"
/// which is whether the buffer has been modified or not and a number of other
/// pieces of information.
pub struct View<'v> {
    pub buffer: Buffer,
    // the line number of the topmost `Line` for the View to render
    pub top_line_num: uint,
    pub linenum: uint,
    pub offset: uint,

    uibuf: UIBuffer,
    threshold: int,
}

impl<'v> View<'v> {
    pub fn new(source: Input) -> View<'v> {
        let buffer = match source {
            Input::Filename(path) => {
                match path {
                    Some(s) => Buffer::new_from_file(Path::new(s)),
                    None    => Buffer::new_empty(),
                }
            },
            Input::Stdin(reader) => {
                Buffer::new_from_reader(reader)
            },
        };

        let height: uint = utils::get_term_height();
        let width: uint = utils::get_term_width();

        // NOTE(greg): this may not play well with resizing
        let uibuf = UIBuffer::new(width, height);

        View {
            buffer: buffer,
            top_line_num: 0,
            uibuf: uibuf,
            threshold: 5,
            linenum: 0,
            offset: 0,
        }
    }

    pub fn cursor<'b>(&'b mut self) -> CursorGuard<'b> {
        let View {ref mut buffer, ref mut offset, ref mut linenum, .. } = *self;
        let mut cursor = Cursor::new();
        cursor.set_line(Some(&mut buffer.lines[*linenum]));
        cursor.set_offset(*offset);
        CursorGuard { cursor: cursor, offset: offset, linenum: linenum }
    }

    /// Clear the buffer
    ///
    /// Fills every cell in the UIBuffer with the space (' ') char.
    pub fn clear(&mut self) {
        self.uibuf.fill(' ');
        self.uibuf.draw_everything();
    }

    pub fn get_height(&self) -> uint {
        // NOTE(greg): when the status bar needs to move up, this value should be changed
        self.uibuf.get_height() -1
    }

    pub fn get_width(&self) -> uint {
        self.uibuf.get_width()
    }

    pub fn draw(&mut self) {
        let end_line = self.get_height();
        let num_lines = self.buffer.lines.len();
        let lines_to_draw = self.buffer.lines.slice(self.top_line_num, num_lines);

        for (index, line) in lines_to_draw.iter().enumerate() {
            if index < end_line {
                draw_line(&mut self.uibuf, line, self.top_line_num)
            }
        }

        self.uibuf.draw_everything();
    }

    pub fn draw_status(&mut self) {
        let buffer_status = self.buffer.get_status_text();
        let cursor_status = self.cursor().get_status_text();
        let status_text = format!("{} {}", buffer_status, cursor_status).into_bytes();
        let status_text_len = status_text.len();
        let width = self.get_width();
        let height = self.get_height();

        for index in range(0, width) {
            let mut ch: char = ' ';
            if index < status_text_len {
                ch = status_text[index] as char;
            }
            self.uibuf.update_cell(index, height, ch, rustbox::Color::Black, rustbox::Color::Blue);
        }

        self.uibuf.draw_range(height, height+1);
    }

    pub fn draw_cursor(&mut self) {
        let offset = self.cursor().get_visible_offset();
        let linenum = self.cursor().get_linenum();

        utils::draw_cursor(offset, linenum-self.top_line_num);
    }

    pub fn resize(&mut self) {
        let width = self.uibuf.get_width();
        self.clear();
        self.uibuf = UIBuffer::new(width, 15);
    }

    pub fn move_cursor(&mut self, direction: Direction) {
        match direction {
            Direction::Up    => { self.move_cursor_up(); },
            Direction::Down  => { self.move_cursor_down(); },
            Direction::Right => { self.move_cursor_right(); },
            Direction::Left  => { self.cursor().move_left(); },
        }
    }

    fn move_cursor_right(&mut self) {
        let cursor_offset = self.cursor().get_visible_offset();
        let next_offset = cursor_offset + 1;
        let width = self.get_width() - 1;

        if next_offset < width {
            self.cursor().move_right()
        }
    }

    // TODO(greg): refactor this method with move_cursor_down
    pub fn move_cursor_up(&mut self) {
        let cursor_linenum = self.cursor().get_linenum();

        if cursor_linenum == 0 { return }
        let prev_linenum = cursor_linenum - 1;

        let num_lines = self.buffer.lines.len() - 1;
        if prev_linenum > num_lines { return }

        self.set_cursor_line(prev_linenum);

        let cursor_linenum = self.cursor().get_linenum() as int;
        let cursor_offset = cursor_linenum - self.top_line_num as int;

        if cursor_offset < self.threshold {
            let times = cursor_offset - self.threshold;
            self.move_top_line_n_times(times);
        }

    }

    // TODO(greg): refactor this method with move_cursor_up
    pub fn move_cursor_down(&mut self) {
        let cursor_linenum = self.cursor().get_linenum();
        let next_linenum = cursor_linenum + 1;

        let num_lines = self.buffer.lines.len() - 1;
        if next_linenum > num_lines { return }

        self.set_cursor_line(next_linenum);

        let cursor_linenum = self.cursor().get_linenum() as int;
        let cursor_offset = cursor_linenum - self.top_line_num as int;
        let height = self.get_height() as int;

        if cursor_offset >= (height - self.threshold) {
            let times = cursor_offset - (height - self.threshold) + 1;
            self.move_top_line_n_times(times);
        }
    }

    fn set_cursor_line<'b>(&'b mut self, linenum: uint) {
        self.linenum = linenum;
    }

    fn move_top_line_n_times(&mut self, mut num_times: int) {
        if num_times == 0 { return }

        // moving down
        if num_times > 0 {
            while num_times > 0 {
                self.top_line_num += 1;
                num_times -= 1;
            }
            return
        }

        // moving up
        if num_times < 0 {
            while num_times < 0 {
                if self.top_line_num == 0 { return }
                self.top_line_num -= 1;
                num_times += 1;
            }
            return
        }
    }

    pub fn delete_char(&mut self, direction: Direction) {
        let (offset, line_num) = self.cursor().get_position();

        if offset == 0 && direction.is_left() {
            // Must move the cursor up first so we aren't pointing at dangling memory
            self.move_cursor_up();
            let offset = self.buffer.join_line_with_previous(offset, line_num);
            self.cursor().set_offset(offset);
            return
        }

        let line_len = self.cursor().get_line_length();
        if offset == line_len && direction.is_right() {
            // try to join the next line with the current line
            // if there is no next line, nothing will happen
            self.buffer.join_line_with_previous(offset, line_num+1);
            return
        }

        match direction {
            Direction::Left  => self.cursor().delete_backward_char(),
            Direction::Right => self.cursor().delete_forward_char(),
            _                => {}
        }
    }

    pub fn insert_tab(&mut self) {
        // A tab is just 4 spaces
        for _ in range(0i, 4) {
            self.insert_char(' ');
        }
    }

    pub fn insert_char(&mut self, ch: char) {
        self.cursor().insert_char(ch);
    }

    pub fn insert_line(&mut self) {
        let (offset, line_num) = self.cursor().get_position();
        self.buffer.insert_line(offset, line_num);

        self.move_cursor_down();
        self.cursor().set_offset(0);
    }
}

pub fn draw_line(buf: &mut UIBuffer, line: &Line, top_line_num: uint) {
    let width = buf.get_width() -1;
    let index = line.linenum - top_line_num;
    let mut internal_index = 0;
    for ch in line.data.chars() {
        if internal_index < width {
            match ch {
                '\t' => {
                    // todo(greg): draw four spaces
                    // need to update how the cursor is rendered before doing this
                    // think about what will happen if the cursor sees a single '\t' char
                    // in the line, however this is represented as four chars to the user
                    // the actual cursor position will become separated from the drawn
                    // cursor position.
                    rustbox::shutdown();
                    panic!("found tab chars - can't process these right now")
                }
                _ => {
                    // draw the character
                    buf.update_cell_content(internal_index, index, ch);
                }
            }
            internal_index += ch.width(false).unwrap_or(1);
        }

        // if the line is longer than the width of the view, draw a special char
        if internal_index == width {
            buf.update_cell_content(internal_index, index, '→');
            break;
        }
    }
}

#[cfg(test)]
mod tests {

    use buffer::{Line, Buffer};
    use cursor::{Direction};
    use view::View;
    use uibuf::UIBuffer;
    use utils::data_from_str;

    fn setup_view<'v>() -> View<'v> {
        let mut view = View {
            buffer: Buffer::new(),
            top_line_num: 0,
            linenum: 0,
            offset: 0,
            uibuf: UIBuffer::new(50, 50),
            threshold: 5,
        };

        let first_line = Line::new(data_from_str("test"), 0);
        let second_line = Line::new(data_from_str("second"), 1);

        view.buffer.lines = vec!(first_line, second_line);
        view.set_cursor_line(0);

        return view
    }

    #[test]
    fn test_move_cursor_down() {
        let mut view = setup_view();
        view.move_cursor_down();

        assert_eq!(view.cursor().get_linenum(), 1);
        assert_eq!(view.cursor().get_line().data, data_from_str("second"));
    }

    #[test]
    fn test_move_cursor_up() {
        let mut view = setup_view();
        view.move_cursor_down();
        view.move_cursor_up();
        assert_eq!(view.cursor().get_linenum(), 0);
        assert_eq!(view.cursor().get_line().data, data_from_str("test"));
    }

    #[test]
    fn test_insert_line() {
        let mut view = setup_view();
        view.cursor().move_right();
        view.insert_line();

        assert_eq!(view.buffer.lines.len(), 3);
        assert_eq!(view.cursor().get_offset(), 0);
        assert_eq!(view.cursor().get_line().linenum, 1);
    }

    #[test]
    fn test_insert_char() {
        let mut view = setup_view();
        view.insert_char('t');

        assert_eq!(view.cursor().get_line().data, data_from_str("ttest"));
    }

    #[test]
    fn test_delete_char_to_right() {
        let mut view = setup_view();
        view.delete_char(Direction::Right);

        assert_eq!(view.cursor().get_line().data, data_from_str("est"));
    }

    #[test]
    fn test_delete_char_to_left() {
        let mut view = setup_view();
        view.cursor().move_right();
        view.delete_char(Direction::Left);

        assert_eq!(view.cursor().get_line().data, data_from_str("est"));
    }

    #[test]
    fn test_delete_char_at_start_of_line() {
        let mut view = setup_view();
        view.move_cursor_down();
        view.delete_char(Direction::Left);

        assert_eq!(view.cursor().get_line().data, data_from_str("testsecond"));
    }

    #[test]
    fn test_delete_char_at_end_of_line() {
        let mut view = setup_view();
        view.offset = 4;
        view.delete_char(Direction::Right);

        assert_eq!(view.cursor().get_line().data, data_from_str("testsecond"));
    }

    #[test]
    fn delete_char_when_line_is_empty_does_nothing() {
        let mut view = setup_view();
        view.buffer.lines = vec!(Line::new(String::new(), 0));
        view.linenum = 0;
        view.delete_char(Direction::Right);
        assert_eq!(view.cursor().get_line().data, data_from_str(""));
    }

    #[test]
    fn deleting_backward_at_start_of_first_line_does_nothing() {
        let mut view = setup_view();
        view.delete_char(Direction::Left);

        assert_eq!(view.buffer.lines.len(), 2);
        assert_eq!(view.cursor().get_line().data, data_from_str("test"));
    }
}
<commit_msg>Making sure offset is not greater than line width.<commit_after>extern crate rustbox;

use buffer::{Line, Buffer};
use cursor::Direction;
use cursor::Cursor;
use input::Input;
use uibuf::UIBuffer;

use utils;

pub struct CursorGuard<'a> {
    linenum: &'a mut uint,
    offset: &'a mut uint,
    cursor: Cursor<'a>,
}

impl<'a> Deref<Cursor<'a>> for CursorGuard<'a> {
    fn deref(&self) -> &Cursor<'a> {
        &self.cursor
    }
}

impl<'a> DerefMut<Cursor<'a>> for CursorGuard<'a> {
    fn deref_mut(&mut self) -> &mut Cursor<'a> {
        &mut self.cursor
    }
}

#[unsafe_destructor]
impl<'a> Drop for CursorGuard<'a> {
    fn drop(&mut self) {
        // Update line number and offset
        *self.linenum = self.cursor.get_linenum();
        *self.offset = self.cursor.get_offset();
    }
}

/// A View is an abstract Window (into a Buffer).
///
/// It draws a portion of a Buffer to a UIBuffer which in turn is drawn to the
/// screen. It maintains the status bar for the current view, the "dirty status"
/// which is whether the buffer has been modified or not and a number of other
/// pieces of information.
pub struct View<'v> {
    pub buffer: Buffer,
    // the line number of the topmost `Line` for the View to render
    pub top_line_num: uint,
    pub linenum: uint,
    pub offset: uint,

    uibuf: UIBuffer,
    threshold: int,
}

impl<'v> View<'v> {
    pub fn new(source: Input) -> View<'v> {
        let buffer = match source {
            Input::Filename(path) => {
                match path {
                    Some(s) => Buffer::new_from_file(Path::new(s)),
                    None    => Buffer::new_empty(),
                }
            },
            Input::Stdin(reader) => {
                Buffer::new_from_reader(reader)
            },
        };

        let height: uint = utils::get_term_height();
        let width: uint = utils::get_term_width();

        // NOTE(greg): this may not play well with resizing
        let uibuf = UIBuffer::new(width, height);

        View {
            buffer: buffer,
            top_line_num: 0,
            uibuf: uibuf,
            threshold: 5,
            linenum: 0,
            offset: 0,
        }
    }

    pub fn cursor<'b>(&'b mut self) -> CursorGuard<'b> {
        let View {ref mut buffer, ref mut offset, ref mut linenum, .. } = *self;
        let mut cursor = Cursor::new();
        cursor.set_offset(*offset);
        cursor.set_line(Some(&mut buffer.lines[*linenum]));
        CursorGuard { cursor: cursor, offset: offset, linenum: linenum }
    }

    /// Clear the buffer
    ///
    /// Fills every cell in the UIBuffer with the space (' ') char.
    pub fn clear(&mut self) {
        self.uibuf.fill(' ');
        self.uibuf.draw_everything();
    }

    pub fn get_height(&self) -> uint {
        // NOTE(greg): when the status bar needs to move up, this value should be changed
        self.uibuf.get_height() -1
    }

    pub fn get_width(&self) -> uint {
        self.uibuf.get_width()
    }

    pub fn draw(&mut self) {
        let end_line = self.get_height();
        let num_lines = self.buffer.lines.len();
        let lines_to_draw = self.buffer.lines.slice(self.top_line_num, num_lines);

        for (index, line) in lines_to_draw.iter().enumerate() {
            if index < end_line {
                draw_line(&mut self.uibuf, line, self.top_line_num)
            }
        }

        self.uibuf.draw_everything();
    }

    pub fn draw_status(&mut self) {
        let buffer_status = self.buffer.get_status_text();
        let cursor_status = self.cursor().get_status_text();
        let status_text = format!("{} {}", buffer_status, cursor_status).into_bytes();
        let status_text_len = status_text.len();
        let width = self.get_width();
        let height = self.get_height();

        for index in range(0, width) {
            let mut ch: char = ' ';
            if index < status_text_len {
                ch = status_text[index] as char;
            }
            self.uibuf.update_cell(index, height, ch, rustbox::Color::Black, rustbox::Color::Blue);
        }

        self.uibuf.draw_range(height, height+1);
    }

    pub fn draw_cursor(&mut self) {
        let offset = self.cursor().get_visible_offset();
        let linenum = self.cursor().get_linenum();

        utils::draw_cursor(offset, linenum-self.top_line_num);
    }

    pub fn resize(&mut self) {
        let width = self.uibuf.get_width();
        self.clear();
        self.uibuf = UIBuffer::new(width, 15);
    }

    pub fn move_cursor(&mut self, direction: Direction) {
        match direction {
            Direction::Up    => { self.move_cursor_up(); },
            Direction::Down  => { self.move_cursor_down(); },
            Direction::Right => { self.move_cursor_right(); },
            Direction::Left  => { self.cursor().move_left(); },
        }
    }

    fn move_cursor_right(&mut self) {
        let cursor_offset = self.cursor().get_visible_offset();
        let next_offset = cursor_offset + 1;
        let width = self.get_width() - 1;

        if next_offset < width {
            self.cursor().move_right()
        }
    }

    // TODO(greg): refactor this method with move_cursor_down
    pub fn move_cursor_up(&mut self) {
        let cursor_linenum = self.cursor().get_linenum();

        if cursor_linenum == 0 { return }
        let prev_linenum = cursor_linenum - 1;

        let num_lines = self.buffer.lines.len() - 1;
        if prev_linenum > num_lines { return }

        self.set_cursor_line(prev_linenum);

        let cursor_linenum = self.cursor().get_linenum() as int;
        let cursor_offset = cursor_linenum - self.top_line_num as int;

        if cursor_offset < self.threshold {
            let times = cursor_offset - self.threshold;
            self.move_top_line_n_times(times);
        }

    }

    // TODO(greg): refactor this method with move_cursor_up
    pub fn move_cursor_down(&mut self) {
        let cursor_linenum = self.cursor().get_linenum();
        let next_linenum = cursor_linenum + 1;

        let num_lines = self.buffer.lines.len() - 1;
        if next_linenum > num_lines { return }

        self.set_cursor_line(next_linenum);

        let cursor_linenum = self.cursor().get_linenum() as int;
        let cursor_offset = cursor_linenum - self.top_line_num as int;
        let height = self.get_height() as int;

        if cursor_offset >= (height - self.threshold) {
            let times = cursor_offset - (height - self.threshold) + 1;
            self.move_top_line_n_times(times);
        }
    }

    fn set_cursor_line<'b>(&'b mut self, linenum: uint) {
        self.linenum = linenum;
    }

    fn move_top_line_n_times(&mut self, mut num_times: int) {
        if num_times == 0 { return }

        // moving down
        if num_times > 0 {
            while num_times > 0 {
                self.top_line_num += 1;
                num_times -= 1;
            }
            return
        }

        // moving up
        if num_times < 0 {
            while num_times < 0 {
                if self.top_line_num == 0 { return }
                self.top_line_num -= 1;
                num_times += 1;
            }
            return
        }
    }

    pub fn delete_char(&mut self, direction: Direction) {
        let (offset, line_num) = self.cursor().get_position();

        if offset == 0 && direction.is_left() {
            // Must move the cursor up first so we aren't pointing at dangling memory
            self.move_cursor_up();
            let offset = self.buffer.join_line_with_previous(offset, line_num);
            self.cursor().set_offset(offset);
            return
        }

        let line_len = self.cursor().get_line_length();
        if offset == line_len && direction.is_right() {
            // try to join the next line with the current line
            // if there is no next line, nothing will happen
            self.buffer.join_line_with_previous(offset, line_num+1);
            return
        }

        match direction {
            Direction::Left  => self.cursor().delete_backward_char(),
            Direction::Right => self.cursor().delete_forward_char(),
            _                => {}
        }
    }

    pub fn insert_tab(&mut self) {
        // A tab is just 4 spaces
        for _ in range(0i, 4) {
            self.insert_char(' ');
        }
    }

    pub fn insert_char(&mut self, ch: char) {
        self.cursor().insert_char(ch);
    }

    pub fn insert_line(&mut self) {
        let (offset, line_num) = self.cursor().get_position();
        self.buffer.insert_line(offset, line_num);

        self.move_cursor_down();
        self.cursor().set_offset(0);
    }
}

pub fn draw_line(buf: &mut UIBuffer, line: &Line, top_line_num: uint) {
    let width = buf.get_width() -1;
    let index = line.linenum - top_line_num;
    let mut internal_index = 0;
    for ch in line.data.chars() {
        if internal_index < width {
            match ch {
                '\t' => {
                    // todo(greg): draw four spaces
                    // need to update how the cursor is rendered before doing this
                    // think about what will happen if the cursor sees a single '\t' char
                    // in the line, however this is represented as four chars to the user
                    // the actual cursor position will become separated from the drawn
                    // cursor position.
                    rustbox::shutdown();
                    panic!("found tab chars - can't process these right now")
                }
                _ => {
                    // draw the character
                    buf.update_cell_content(internal_index, index, ch);
                }
            }
            internal_index += ch.width(false).unwrap_or(1);
        }

        // if the line is longer than the width of the view, draw a special char
        if internal_index == width {
            buf.update_cell_content(internal_index, index, '→');
            break;
        }
    }
}

#[cfg(test)]
mod tests {

    use buffer::{Line, Buffer};
    use cursor::{Direction};
    use view::View;
    use uibuf::UIBuffer;
    use utils::data_from_str;

    fn setup_view<'v>() -> View<'v> {
        let mut view = View {
            buffer: Buffer::new(),
            top_line_num: 0,
            linenum: 0,
            offset: 0,
            uibuf: UIBuffer::new(50, 50),
            threshold: 5,
        };

        let first_line = Line::new(data_from_str("test"), 0);
        let second_line = Line::new(data_from_str("second"), 1);

        view.buffer.lines = vec!(first_line, second_line);
        view.set_cursor_line(0);

        return view
    }

    #[test]
    fn test_move_cursor_down() {
        let mut view = setup_view();
        view.move_cursor_down();

        assert_eq!(view.cursor().get_linenum(), 1);
        assert_eq!(view.cursor().get_line().data, data_from_str("second"));
    }

    #[test]
    fn test_move_cursor_up() {
        let mut view = setup_view();
        view.move_cursor_down();
        view.move_cursor_up();
        assert_eq!(view.cursor().get_linenum(), 0);
        assert_eq!(view.cursor().get_line().data, data_from_str("test"));
    }

    #[test]
    fn test_insert_line() {
        let mut view = setup_view();
        view.cursor().move_right();
        view.insert_line();

        assert_eq!(view.buffer.lines.len(), 3);
        assert_eq!(view.cursor().get_offset(), 0);
        assert_eq!(view.cursor().get_line().linenum, 1);
    }

    #[test]
    fn test_insert_char() {
        let mut view = setup_view();
        view.insert_char('t');

        assert_eq!(view.cursor().get_line().data, data_from_str("ttest"));
    }

    #[test]
    fn test_delete_char_to_right() {
        let mut view = setup_view();
        view.delete_char(Direction::Right);

        assert_eq!(view.cursor().get_line().data, data_from_str("est"));
    }

    #[test]
    fn test_delete_char_to_left() {
        let mut view = setup_view();
        view.cursor().move_right();
        view.delete_char(Direction::Left);

        assert_eq!(view.cursor().get_line().data, data_from_str("est"));
    }

    #[test]
    fn test_delete_char_at_start_of_line() {
        let mut view = setup_view();
        view.move_cursor_down();
        view.delete_char(Direction::Left);

        assert_eq!(view.cursor().get_line().data, data_from_str("testsecond"));
    }

    #[test]
    fn test_delete_char_at_end_of_line() {
        let mut view = setup_view();
        view.offset = 4;
        view.delete_char(Direction::Right);

        assert_eq!(view.cursor().get_line().data, data_from_str("testsecond"));
    }

    #[test]
    fn delete_char_when_line_is_empty_does_nothing() {
        let mut view = setup_view();
        view.buffer.lines = vec!(Line::new(String::new(), 0));
        view.linenum = 0;
        view.delete_char(Direction::Right);
        assert_eq!(view.cursor().get_line().data, data_from_str(""));
    }

    #[test]
    fn deleting_backward_at_start_of_first_line_does_nothing() {
        let mut view = setup_view();
        view.delete_char(Direction::Left);

        assert_eq!(view.buffer.lines.len(), 2);
        assert_eq!(view.cursor().get_line().data, data_from_str("test"));
    }
}
<|endoftext|>


<commit_before>use key::Key;
#[cfg(feature = "ansi")]
use std::io::Stdin;
#[cfg(feature = "ansi")]
use std::io::prelude::*;

/// Key state
pub struct KeyState {
    pub ctrl: bool,
    pub alt: bool,
    pub shift: bool,
}

impl KeyState {
    pub fn new() -> KeyState {
        KeyState {
            ctrl: false,
            alt: false,
            shift: false,
        }
    }

    /// Feed the keystate
    #[cfg(feature = "orbital")]
    pub fn feed(&mut self, k: KeyEvent) -> Option<Key> {
        use orbital::{
            KeyEvent,
            K_ALT,
            K_CTRL,
            K_LEFT_SHIFT,
            K_RIGHT_SHIFT
        };

        let c = k.character;
        match c {
            '\0' => {
                // "I once lived here" - bug
                match k.scancode {
                    K_ALT => self.alt = k.pressed,
                    K_CTRL => self.ctrl = k.pressed,
                    K_LEFT_SHIFT | K_RIGHT_SHIFT => self.shift = k.pressed,
                    _ if k.pressed => {
                        return Some(Key::from_event(k));
                    }
                    _ => {}
                }
            }
            _ if k.pressed => {
                return Some(Key::from_event(k));
            }
            _ => {}
        }

        None
    }

    #[cfg(feature = "ansi")]
    pub fn feed(&mut self, stdin: &mut Stdin) -> Option<Key> {
        match c {
            '\0' => {
                // "I once lived here" - bug
                match k.scancode {
                    K_ALT => self.alt = k.pressed,
                    K_CTRL => self.ctrl = k.pressed,
                    K_LEFT_SHIFT | K_RIGHT_SHIFT => self.shift = k.pressed,
                    _ if k.pressed => {
                        return Some(Key::from_event(k));
                    }
                    _ => {}
                }
            }
            _ if k.pressed => {
                return Some(Key::from_event(k));
            }
            _ => {}
        }

        None
    }
}
<commit_msg>Fix import<commit_after>use key::Key;
#[cfg(feature = "orbital")]
use orbital::KeyEvent;

#[cfg(feature = "ansi")]
use std::io::Stdin;
#[cfg(feature = "ansi")]
use std::io::prelude::*;

/// Key state
pub struct KeyState {
    pub ctrl: bool,
    pub alt: bool,
    pub shift: bool,
}

impl KeyState {
    pub fn new() -> KeyState {
        KeyState {
            ctrl: false,
            alt: false,
            shift: false,
        }
    }

    /// Feed the keystate
    #[cfg(feature = "orbital")]
    pub fn feed(&mut self, k: KeyEvent) -> Option<Key> {
        use orbital::{
            K_ALT,
            K_CTRL,
            K_LEFT_SHIFT,
            K_RIGHT_SHIFT
        };

        let c = k.character;
        match c {
            '\0' => {
                // "I once lived here" - bug
                match k.scancode {
                    K_ALT => self.alt = k.pressed,
                    K_CTRL => self.ctrl = k.pressed,
                    K_LEFT_SHIFT | K_RIGHT_SHIFT => self.shift = k.pressed,
                    _ if k.pressed => {
                        return Some(Key::from_event(k));
                    }
                    _ => {}
                }
            }
            _ if k.pressed => {
                return Some(Key::from_event(k));
            }
            _ => {}
        }

        None
    }

    #[cfg(feature = "ansi")]
    pub fn feed(&mut self, stdin: &mut Stdin) -> Option<Key> {
        match c {
            '\0' => {
                // "I once lived here" - bug
                match k.scancode {
                    K_ALT => self.alt = k.pressed,
                    K_CTRL => self.ctrl = k.pressed,
                    K_LEFT_SHIFT | K_RIGHT_SHIFT => self.shift = k.pressed,
                    _ if k.pressed => {
                        return Some(Key::from_event(k));
                    }
                    _ => {}
                }
            }
            _ if k.pressed => {
                return Some(Key::from_event(k));
            }
            _ => {}
        }

        None
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 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.

// Crate that exports a const fn. Used for testing cross-crate.

#![crate_type="rlib"]
#![stable(feature = "rust1", since = "1.0.0")]

#![feature(rustc_const_unstable, const_fn)]
#![feature(staged_api)]

#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature="foo")]
pub const fn foo() -> u32 { 42 }<commit_msg>Satisfy tidy<commit_after>// Copyright 2015 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.

// Crate that exports a const fn. Used for testing cross-crate.

#![crate_type="rlib"]
#![stable(feature = "rust1", since = "1.0.0")]

#![feature(rustc_const_unstable, const_fn)]
#![feature(staged_api)]

#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature="foo")]
pub const fn foo() -> u32 { 42 }
<|endoftext|>


<commit_before>// compile-flags: -Zmiri-disable-isolation

use std::time::{SystemTime, Instant};

fn main() {
    let now1 = SystemTime::now();
    // Do some work to make time pass.
    for _ in 0..10 { drop(vec![42]); }
    let now2 = SystemTime::now();
    assert!(now2 > now1);
    let diff = now2.duration_since(now1).unwrap();
    assert!(diff.as_micros() > 0);
    assert_eq!(now1 + diff, now2);
    assert_eq!(now2 - diff, now1);

    #[cfg(not(windows))] // `Instant` shims not yet implemented on Windows
    {
        let now1 = Instant::now();
        // Do some work to make time pass.
        for _ in 0..10 { drop(vec![42]); }
        let now2 = Instant::now();
        assert!(now2 > now1);

        #[cfg(target_os = "linux")] // TODO: macOS does not support Instant subtraction
        {
            let diff = now2.duration_since(now1);
            assert!(diff.as_micros() > 0);
            assert_eq!(now1 + diff, now2);
            assert_eq!(now2 - diff, now1);
        }
    }
}
<commit_msg>sanity check time values a bit more<commit_after>// compile-flags: -Zmiri-disable-isolation

use std::time::{SystemTime, Instant};

fn main() {
    // Check `SystemTime`.
    let now1 = SystemTime::now();
    // Do some work to make time pass.
    for _ in 0..10 { drop(vec![42]); }
    let now2 = SystemTime::now();
    assert!(now2 > now1);
    let diff = now2.duration_since(now1).unwrap();
    assert_eq!(now1 + diff, now2);
    assert_eq!(now2 - diff, now1);
    // Sanity-check the time we got.
    let seconds_since_epoch = now1.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs();
    let years_since_epoch = seconds_since_epoch / 3600 / 24 / 365;
    let year = 1970 + years_since_epoch;
    assert!(2020 <= year && year < 2100);

    // Check `Instant`.
    #[cfg(not(windows))] // `Instant` shims not yet implemented on Windows
    {
        let now1 = Instant::now();
        // Do some work to make time pass.
        for _ in 0..10 { drop(vec![42]); }
        let now2 = Instant::now();
        assert!(now2 > now1);

        #[cfg(target_os = "linux")] // TODO: macOS does not support Instant subtraction
        {
            let diff = now2.duration_since(now1);
            assert_eq!(now1 + diff, now2);
            assert_eq!(now2 - diff, now1);
            // Sanity-check the difference we got.
            assert!(diff.as_micros() > 1);
            assert!(diff.as_micros() < 1_000_000);
        }
    }
}
<|endoftext|>