<commit_before>// Copyright 2017 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::usize;
use std::time;
use std::sync::{Arc, Condvar, Mutex};
use std::thread::{Builder, JoinHandle};
use std::boxed::FnBox;
use std::collections::VecDeque;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrdering};
use std::fmt::Write;

pub const DEFAULT_TASKS_PER_TICK: usize = 10000;
const WORKER_WAIT_TIME: u64 = 2000; // ms
const DEFAULT_QUEUE_CAPACITY: usize = 1000;
const QUEUE_MAX_CAPACITY: usize = 8 * DEFAULT_QUEUE_CAPACITY;

pub trait Context: Send {
    fn on_task_started(&mut self);
    fn on_task_finished(&mut self);
    fn on_tick(&mut self);
}

pub trait ContextFactory<Ctx: Context> {
    fn create(&self) -> Ctx;
}

pub struct Task<C> {
    task: Box<FnBox(&mut C) + Send>,
}

impl<C: Context> Task<C> {
    fn new<F>(job: F) -> Task<C>
    where
        for<'r> F: FnOnce(&'r mut C) + Send + 'static,
    {
        Task {
            task: Box::new(job),
        }
    }
}

// First in first out queue.
pub struct FifoQueue<C> {
    queue: VecDeque<Task<C>>,
}

impl<C: Context> FifoQueue<C> {
    fn new() -> FifoQueue<C> {
        FifoQueue {
            queue: VecDeque::with_capacity(DEFAULT_QUEUE_CAPACITY),
        }
    }

    fn push(&mut self, task: Task<C>) {
        self.queue.push_back(task);
    }

    fn pop(&mut self) -> Option<Task<C>> {
        let task = self.queue.pop_front();

        if self.queue.is_empty() && self.queue.capacity() > QUEUE_MAX_CAPACITY {
            self.queue = VecDeque::with_capacity(DEFAULT_QUEUE_CAPACITY);
        }

        task
    }
}

/// `ThreadPool` is used to execute tasks in parallel.
/// Each task would be pushed into the pool, and when a thread
/// is ready to process a task, it will get a task from the pool
/// according to the `ScheduleQueue` provided in initialization.
pub struct ThreadPool<Ctx> {
    stop_flag: Arc<AtomicBool>,
    task_pool: Arc<(Mutex<FifoQueue<Ctx>>, Condvar)>,
    threads: Vec<JoinHandle<()>>,
    task_count: Arc<AtomicUsize>,
}

impl<Ctx> ThreadPool<Ctx>
where
    Ctx: Context + 'static,
{
    pub fn new<C: ContextFactory<Ctx>>(
        name: String,
        num_threads: usize,
        tasks_per_tick: usize,
        f: C,
    ) -> ThreadPool<Ctx> {
        assert!(num_threads >= 1);
        let task_pool = Arc::new((Mutex::new(FifoQueue::new()), Condvar::new()));
        let mut threads = Vec::with_capacity(num_threads);
        let task_count = Arc::new(AtomicUsize::new(0));
        let stop_flag = Arc::new(AtomicBool::new(false));
        // Threadpool threads
        for _ in 0..num_threads {
            let tasks = task_pool.clone();
            let task_num = task_count.clone();
            let ctx = f.create();
            let stop = stop_flag.clone();
            let thread = Builder::new()
                .name(name.clone())
                .spawn(move || {
                    let mut worker = Worker::new(tasks, task_num, tasks_per_tick, stop, ctx);
                    worker.run();
                })
                .unwrap();
            threads.push(thread);
        }

        ThreadPool {
            task_pool: task_pool,
            stop_flag: stop_flag,
            threads: threads,
            task_count: task_count,
        }
    }

    pub fn execute<F>(&mut self, job: F)
    where
        F: FnOnce(&mut Ctx) + Send + 'static,
        Ctx: Context,
    {
        if self.stop_flag.load(AtomicOrdering::SeqCst) {
            return;
        }
        let task = Task::new(job);
        let &(ref lock, ref cvar) = &*self.task_pool;
        let mut queue = lock.lock().unwrap();
        queue.push(task);
        cvar.notify_one();
        self.task_count.fetch_add(1, AtomicOrdering::SeqCst);
    }

    #[inline]
    pub fn get_task_count(&self) -> usize {
        self.task_count.load(AtomicOrdering::SeqCst)
    }

    pub fn stop(&mut self) -> Result<(), String> {
        self.stop_flag.store(true, AtomicOrdering::SeqCst);
        let &(_, ref cvar) = &*self.task_pool;
        cvar.notify_all();
        let mut err_msg = String::new();
        for t in self.threads.drain(..) {
            if let Err(e) = t.join() {
                write!(&mut err_msg, "Failed to join thread with err: {:?};", e).unwrap();
            }
        }
        if !err_msg.is_empty() {
            return Err(err_msg);
        }
        Ok(())
    }
}

// Each thread has a worker.
struct Worker<C> {
    stop_flag: Arc<AtomicBool>,
    task_queue: Arc<(Mutex<FifoQueue<C>>, Condvar)>,
    task_count: Arc<AtomicUsize>,
    tasks_per_tick: usize,
    task_counter: usize,
    ctx: C,
}

impl<C> Worker<C>
where
    C: Context,
{
    fn new(
        task_queue: Arc<(Mutex<FifoQueue<C>>, Condvar)>,
        task_count: Arc<AtomicUsize>,
        tasks_per_tick: usize,
        stop_flag: Arc<AtomicBool>,
        ctx: C,
    ) -> Worker<C> {
        Worker {
            stop_flag: stop_flag,
            task_queue: task_queue,
            task_count: task_count,
            tasks_per_tick: tasks_per_tick,
            task_counter: 0,
            ctx: ctx,
        }
    }

    fn get_task_timeout(&mut self, timeout: time::Duration) -> Option<Task<C>> {
        let &(ref lock, ref cvar) = &*self.task_queue;
        let mut task_queue = lock.lock().unwrap();

        if let Some(task) = task_queue.pop() {
            return Some(task);
        }
        let (mut q, _) = cvar.wait_timeout(task_queue, timeout).unwrap();
        q.pop()
    }

    fn run(&mut self) {
        while !self.stop_flag.load(AtomicOrdering::SeqCst) {
            if let Some(t) = self.get_task_timeout(time::Duration::from_millis(WORKER_WAIT_TIME)) {
                self.ctx.on_task_started();
                (t.task).call_once((&mut self.ctx,));
                self.ctx.on_task_finished();
                self.task_count.fetch_sub(1, AtomicOrdering::SeqCst);
                self.task_counter += 1;
                if self.task_counter == self.tasks_per_tick {
                    self.task_counter = 0;
                    self.ctx.on_tick();
                }
            } else {
                self.task_counter = 0;
                self.ctx.on_tick();
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Context, ContextFactory, ThreadPool, DEFAULT_TASKS_PER_TICK};
    use std::time::Duration;
    use std::sync::mpsc::{channel, Sender};
    use std::sync::{Arc, Mutex};
    use std::sync::atomic::{AtomicIsize, Ordering};

    #[derive(Clone)]
    struct DummyContext {}

    unsafe impl Send for DummyContext {}

    impl Context for DummyContext {
        fn on_task_started(&mut self) {}
        fn on_task_finished(&mut self) {}
        fn on_tick(&mut self) {}
    }

    struct DummyContextFactory {}

    impl ContextFactory<DummyContext> for DummyContextFactory {
        fn create(&self) -> DummyContext {
            DummyContext {}
        }
    }

    #[test]
    fn test_get_task_count() {
        let name = thd_name!("test_get_task_count");
        let concurrency = 1;
        let f = DummyContextFactory {};
        let mut task_pool = ThreadPool::new(name, concurrency, DEFAULT_TASKS_PER_TICK, f);
        let (tx, rx) = channel();
        let (ftx, frx) = channel();
        let receiver = Arc::new(Mutex::new(rx));
        let timeout = Duration::from_secs(2);
        let group_num = 4;
        let mut task_num = 0;
        for gid in 0..group_num {
            let rxer = receiver.clone();
            let ftx = ftx.clone();
            task_pool.execute(move |_: &mut DummyContext| {
                let rx = rxer.lock().unwrap();
                let id = rx.recv_timeout(timeout).unwrap();
                assert_eq!(id, gid);
                ftx.send(true).unwrap();
            });
            task_num += 1;
            assert_eq!(task_pool.get_task_count(), task_num);
        }

        for gid in 0..group_num {
            tx.send(gid).unwrap();
            frx.recv_timeout(timeout).unwrap();
            let left_num = task_pool.get_task_count();
            // current task may be still running.
            assert!(
                left_num == task_num || left_num == task_num - 1,
                format!("left_num {},task_num {}", left_num, task_num)
            );
            task_num -= 1;
        }
        task_pool.stop().unwrap();
    }

    #[test]
    fn test_task_context() {
        struct TestContext {
            counter: Arc<AtomicIsize>,
            tx: Sender<isize>,
        }

        unsafe impl Send for TestContext {}

        impl Context for TestContext {
            fn on_task_started(&mut self) {
                self.counter.fetch_add(1, Ordering::SeqCst);
            }
            fn on_task_finished(&mut self) {
                self.counter.fetch_add(1, Ordering::SeqCst);
                self.tx.send(self.counter.load(Ordering::SeqCst)).unwrap();
            }
            fn on_tick(&mut self) {}
        }

        struct TestContextFactory {
            counter: Arc<AtomicIsize>,
            tx: Sender<isize>,
        }

        impl ContextFactory<TestContext> for TestContextFactory {
            fn create(&self) -> TestContext {
                TestContext {
                    counter: self.counter.clone(),
                    tx: self.tx.clone(),
                }
            }
        }

        let (tx, rx) = channel();

        let f = TestContextFactory {
            counter: Arc::new(AtomicIsize::new(0)),
            tx: tx,
        };

        let name = thd_name!("test_tasks_with_contexts");
        let concurrency = 5;
        let mut task_pool = ThreadPool::new(name, concurrency, DEFAULT_TASKS_PER_TICK, f);

        for _ in 0..10 {
            task_pool.execute(move |_: &mut TestContext| {});
        }
        let mut fin: isize = -1;
        let mut count = 0;
        while count != 10 {
            fin = rx.recv_timeout(Duration::from_millis(20)).unwrap();
            count += 1;
        }
        task_pool.stop().unwrap();
        assert_eq!(fin, 20);
    }

    #[test]
    fn test_task_tick() {
        struct TestContext {
            counter: Arc<AtomicIsize>,
            tx: Sender<isize>,
        }

        unsafe impl Send for TestContext {}

        impl Context for TestContext {
            fn on_task_started(&mut self) {}
            fn on_task_finished(&mut self) {}
            fn on_tick(&mut self) {
                self.counter.fetch_add(1, Ordering::SeqCst);
                self.tx.send(self.counter.load(Ordering::SeqCst)).unwrap();
            }
        }

        struct TestContextFactory {
            counter: Arc<AtomicIsize>,
            tx: Sender<isize>,
        }

        impl ContextFactory<TestContext> for TestContextFactory {
            fn create(&self) -> TestContext {
                TestContext {
                    counter: self.counter.clone(),
                    tx: self.tx.clone(),
                }
            }
        }

        let (tx, rx) = channel();

        let f = TestContextFactory {
            counter: Arc::new(AtomicIsize::new(0)),
            tx: tx,
        };

        let name = thd_name!("test_tasks_tick");
        let concurrency = 1;
        let mut task_pool = ThreadPool::new(name, concurrency, 1, f);

        for _ in 0..10 {
            task_pool.execute(move |_: &mut TestContext| {});
        }
        let mut fin: isize = -1;
        for _ in 0..10 {
            fin = rx.recv_timeout(Duration::from_millis(20)).unwrap();
        }
        task_pool.stop().unwrap();
        assert_eq!(fin, 10);
    }
}
<commit_msg>util/threadpool: fix test_task_context and test_task_tick (#2242)<commit_after>// Copyright 2017 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::usize;
use std::time;
use std::sync::{Arc, Condvar, Mutex};
use std::thread::{Builder, JoinHandle};
use std::boxed::FnBox;
use std::collections::VecDeque;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrdering};
use std::fmt::Write;

pub const DEFAULT_TASKS_PER_TICK: usize = 10000;
const WORKER_WAIT_TIME: u64 = 2000; // ms
const DEFAULT_QUEUE_CAPACITY: usize = 1000;
const QUEUE_MAX_CAPACITY: usize = 8 * DEFAULT_QUEUE_CAPACITY;

pub trait Context: Send {
    fn on_task_started(&mut self);
    fn on_task_finished(&mut self);
    fn on_tick(&mut self);
}

pub trait ContextFactory<Ctx: Context> {
    fn create(&self) -> Ctx;
}

pub struct Task<C> {
    task: Box<FnBox(&mut C) + Send>,
}

impl<C: Context> Task<C> {
    fn new<F>(job: F) -> Task<C>
    where
        for<'r> F: FnOnce(&'r mut C) + Send + 'static,
    {
        Task {
            task: Box::new(job),
        }
    }
}

// First in first out queue.
pub struct FifoQueue<C> {
    queue: VecDeque<Task<C>>,
}

impl<C: Context> FifoQueue<C> {
    fn new() -> FifoQueue<C> {
        FifoQueue {
            queue: VecDeque::with_capacity(DEFAULT_QUEUE_CAPACITY),
        }
    }

    fn push(&mut self, task: Task<C>) {
        self.queue.push_back(task);
    }

    fn pop(&mut self) -> Option<Task<C>> {
        let task = self.queue.pop_front();

        if self.queue.is_empty() && self.queue.capacity() > QUEUE_MAX_CAPACITY {
            self.queue = VecDeque::with_capacity(DEFAULT_QUEUE_CAPACITY);
        }

        task
    }
}

/// `ThreadPool` is used to execute tasks in parallel.
/// Each task would be pushed into the pool, and when a thread
/// is ready to process a task, it will get a task from the pool
/// according to the `ScheduleQueue` provided in initialization.
pub struct ThreadPool<Ctx> {
    stop_flag: Arc<AtomicBool>,
    task_pool: Arc<(Mutex<FifoQueue<Ctx>>, Condvar)>,
    threads: Vec<JoinHandle<()>>,
    task_count: Arc<AtomicUsize>,
}

impl<Ctx> ThreadPool<Ctx>
where
    Ctx: Context + 'static,
{
    pub fn new<C: ContextFactory<Ctx>>(
        name: String,
        num_threads: usize,
        tasks_per_tick: usize,
        f: C,
    ) -> ThreadPool<Ctx> {
        assert!(num_threads >= 1);
        let task_pool = Arc::new((Mutex::new(FifoQueue::new()), Condvar::new()));
        let mut threads = Vec::with_capacity(num_threads);
        let task_count = Arc::new(AtomicUsize::new(0));
        let stop_flag = Arc::new(AtomicBool::new(false));
        // Threadpool threads
        for _ in 0..num_threads {
            let tasks = task_pool.clone();
            let task_num = task_count.clone();
            let ctx = f.create();
            let stop = stop_flag.clone();
            let thread = Builder::new()
                .name(name.clone())
                .spawn(move || {
                    let mut worker = Worker::new(tasks, task_num, tasks_per_tick, stop, ctx);
                    worker.run();
                })
                .unwrap();
            threads.push(thread);
        }

        ThreadPool {
            task_pool: task_pool,
            stop_flag: stop_flag,
            threads: threads,
            task_count: task_count,
        }
    }

    pub fn execute<F>(&mut self, job: F)
    where
        F: FnOnce(&mut Ctx) + Send + 'static,
        Ctx: Context,
    {
        if self.stop_flag.load(AtomicOrdering::SeqCst) {
            return;
        }
        let task = Task::new(job);
        let &(ref lock, ref cvar) = &*self.task_pool;
        let mut queue = lock.lock().unwrap();
        queue.push(task);
        cvar.notify_one();
        self.task_count.fetch_add(1, AtomicOrdering::SeqCst);
    }

    #[inline]
    pub fn get_task_count(&self) -> usize {
        self.task_count.load(AtomicOrdering::SeqCst)
    }

    pub fn stop(&mut self) -> Result<(), String> {
        self.stop_flag.store(true, AtomicOrdering::SeqCst);
        let &(_, ref cvar) = &*self.task_pool;
        cvar.notify_all();
        let mut err_msg = String::new();
        for t in self.threads.drain(..) {
            if let Err(e) = t.join() {
                write!(&mut err_msg, "Failed to join thread with err: {:?};", e).unwrap();
            }
        }
        if !err_msg.is_empty() {
            return Err(err_msg);
        }
        Ok(())
    }
}

// Each thread has a worker.
struct Worker<C> {
    stop_flag: Arc<AtomicBool>,
    task_queue: Arc<(Mutex<FifoQueue<C>>, Condvar)>,
    task_count: Arc<AtomicUsize>,
    tasks_per_tick: usize,
    task_counter: usize,
    ctx: C,
}

impl<C> Worker<C>
where
    C: Context,
{
    fn new(
        task_queue: Arc<(Mutex<FifoQueue<C>>, Condvar)>,
        task_count: Arc<AtomicUsize>,
        tasks_per_tick: usize,
        stop_flag: Arc<AtomicBool>,
        ctx: C,
    ) -> Worker<C> {
        Worker {
            stop_flag: stop_flag,
            task_queue: task_queue,
            task_count: task_count,
            tasks_per_tick: tasks_per_tick,
            task_counter: 0,
            ctx: ctx,
        }
    }

    fn get_task_timeout(&mut self, timeout: time::Duration) -> Option<Task<C>> {
        let &(ref lock, ref cvar) = &*self.task_queue;
        let mut task_queue = lock.lock().unwrap();

        if let Some(task) = task_queue.pop() {
            return Some(task);
        }
        let (mut q, _) = cvar.wait_timeout(task_queue, timeout).unwrap();
        q.pop()
    }

    fn run(&mut self) {
        while !self.stop_flag.load(AtomicOrdering::SeqCst) {
            if let Some(t) = self.get_task_timeout(time::Duration::from_millis(WORKER_WAIT_TIME)) {
                self.ctx.on_task_started();
                (t.task).call_once((&mut self.ctx,));
                self.ctx.on_task_finished();
                self.task_count.fetch_sub(1, AtomicOrdering::SeqCst);
                self.task_counter += 1;
                if self.task_counter == self.tasks_per_tick {
                    self.task_counter = 0;
                    self.ctx.on_tick();
                }
            } else {
                self.task_counter = 0;
                self.ctx.on_tick();
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Context, ContextFactory, ThreadPool, DEFAULT_TASKS_PER_TICK};
    use std::time::Duration;
    use std::sync::mpsc::{channel, Sender};
    use std::sync::{Arc, Mutex};
    use std::sync::atomic::{AtomicIsize, Ordering};

    #[derive(Clone)]
    struct DummyContext {}

    unsafe impl Send for DummyContext {}

    impl Context for DummyContext {
        fn on_task_started(&mut self) {}
        fn on_task_finished(&mut self) {}
        fn on_tick(&mut self) {}
    }

    struct DummyContextFactory {}

    impl ContextFactory<DummyContext> for DummyContextFactory {
        fn create(&self) -> DummyContext {
            DummyContext {}
        }
    }

    #[test]
    fn test_get_task_count() {
        let name = thd_name!("test_get_task_count");
        let concurrency = 1;
        let f = DummyContextFactory {};
        let mut task_pool = ThreadPool::new(name, concurrency, DEFAULT_TASKS_PER_TICK, f);
        let (tx, rx) = channel();
        let (ftx, frx) = channel();
        let receiver = Arc::new(Mutex::new(rx));
        let timeout = Duration::from_secs(2);
        let group_num = 4;
        let mut task_num = 0;
        for gid in 0..group_num {
            let rxer = receiver.clone();
            let ftx = ftx.clone();
            task_pool.execute(move |_: &mut DummyContext| {
                let rx = rxer.lock().unwrap();
                let id = rx.recv_timeout(timeout).unwrap();
                assert_eq!(id, gid);
                ftx.send(true).unwrap();
            });
            task_num += 1;
            assert_eq!(task_pool.get_task_count(), task_num);
        }

        for gid in 0..group_num {
            tx.send(gid).unwrap();
            frx.recv_timeout(timeout).unwrap();
            let left_num = task_pool.get_task_count();
            // current task may be still running.
            assert!(
                left_num == task_num || left_num == task_num - 1,
                format!("left_num {},task_num {}", left_num, task_num)
            );
            task_num -= 1;
        }
        task_pool.stop().unwrap();
    }

    #[test]
    fn test_task_context() {
        struct TestContext {
            counter: Arc<AtomicIsize>,
            tx: Sender<()>,
        }

        unsafe impl Send for TestContext {}

        impl Context for TestContext {
            fn on_task_started(&mut self) {
                self.counter.fetch_add(1, Ordering::SeqCst);
            }
            fn on_task_finished(&mut self) {
                self.counter.fetch_add(1, Ordering::SeqCst);
                self.tx.send(()).unwrap();
            }
            fn on_tick(&mut self) {}
        }

        struct TestContextFactory {
            counter: Arc<AtomicIsize>,
            tx: Sender<()>,
        }

        impl ContextFactory<TestContext> for TestContextFactory {
            fn create(&self) -> TestContext {
                TestContext {
                    counter: self.counter.clone(),
                    tx: self.tx.clone(),
                }
            }
        }

        let (tx, rx) = channel();

        let f = TestContextFactory {
            counter: Arc::new(AtomicIsize::new(0)),
            tx: tx,
        };
        let ctx = f.create();
        let name = thd_name!("test_tasks_with_contexts");
        let concurrency = 5;
        let mut task_pool = ThreadPool::new(name, concurrency, DEFAULT_TASKS_PER_TICK, f);

        for _ in 0..10 {
            task_pool.execute(move |_: &mut TestContext| {});
        }
        for _ in 0..10 {
            rx.recv_timeout(Duration::from_millis(20)).unwrap();
        }
        task_pool.stop().unwrap();
        assert_eq!(ctx.counter.load(Ordering::SeqCst), 20);
    }

    #[test]
    fn test_task_tick() {
        struct TestContext {
            counter: Arc<AtomicIsize>,
            tx: Sender<()>,
        }

        unsafe impl Send for TestContext {}

        impl Context for TestContext {
            fn on_task_started(&mut self) {}
            fn on_task_finished(&mut self) {}
            fn on_tick(&mut self) {
                self.counter.fetch_add(1, Ordering::SeqCst);
                let _ = self.tx.send(());
            }
        }

        struct TestContextFactory {
            counter: Arc<AtomicIsize>,
            tx: Sender<()>,
        }

        impl ContextFactory<TestContext> for TestContextFactory {
            fn create(&self) -> TestContext {
                TestContext {
                    counter: self.counter.clone(),
                    tx: self.tx.clone(),
                }
            }
        }

        let (tx, rx) = channel();

        let f = TestContextFactory {
            counter: Arc::new(AtomicIsize::new(0)),
            tx: tx,
        };
        let ctx = f.create();
        let name = thd_name!("test_tasks_tick");
        let concurrency = 5;
        let mut task_pool = ThreadPool::new(name, concurrency, 1, f);

        for _ in 0..10 {
            task_pool.execute(move |_: &mut TestContext| {});
        }
        for _ in 0..10 {
            rx.recv_timeout(Duration::from_millis(20)).unwrap();
        }
        task_pool.stop().unwrap();
        // `on_tick` may be called even if there is no task.
        assert!(ctx.counter.load(Ordering::SeqCst) >= 10);
    }
}
<|endoftext|>


<commit_before>/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Joseph Crail <jbcrail@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

// Based on the pattern using by Cargo, I created a shim over the
// standard PathExt trait, so that the unstable path methods could
// be backported to stable (<= 1.1). This will likely be dropped
// when the path trait stabilizes.

#[cfg(unix)]
use super::libc;
use std::env;
use std::fs;
use std::io::{Error, ErrorKind, Result};
use std::path::{Component, Path, PathBuf};

pub trait UUPathExt {
    fn uu_exists(&self) -> bool;
    fn uu_is_file(&self) -> bool;
    fn uu_is_dir(&self) -> bool;
    fn uu_metadata(&self) -> Result<fs::Metadata>;
}

impl UUPathExt for Path {
    fn uu_exists(&self) -> bool {
        fs::metadata(self).is_ok()
    }

    fn uu_is_file(&self) -> bool {
        fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
    }

    fn uu_is_dir(&self) -> bool {
        fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
    }

    fn uu_metadata(&self) -> Result<fs::Metadata> {
        fs::metadata(self)
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalizeMode {
    None,
    Normal,
    Existing,
    Missing,
}

fn resolve<P: AsRef<Path>>(original: P) -> Result<PathBuf> {
    const MAX_LINKS_FOLLOWED: u32 = 255;
    let mut followed = 0;
    let mut result = original.as_ref().to_path_buf();
    loop {
        if followed == MAX_LINKS_FOLLOWED {
            return Err(Error::new(ErrorKind::InvalidInput, "maximum links followed"));
        }

        match fs::metadata(&result) {
            Err(e) => return Err(e),
            Ok(ref m) if !m.file_type().is_symlink() => break,
            Ok(..) => {
                followed += 1;
                match fs::read_link(&result) {
                    Ok(path) => {
                        result.pop();
                        result.push(path);
                    },
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
        }
    }
    Ok(result)
}

pub fn canonicalize<P: AsRef<Path>>(original: P, can_mode: CanonicalizeMode) -> Result<PathBuf> {
    // Create an absolute path
    let original = original.as_ref();
    let original = if original.is_absolute() {
        original.to_path_buf()
    } else {
        env::current_dir().unwrap().join(original)
    };

    let mut result = PathBuf::new();
    let mut parts = vec!();

    // Split path by directory separator; add prefix (Windows-only) and root
    // directory to final path buffer; add remaining parts to temporary
    // vector for canonicalization.
    for part in original.components() {
        match part {
            Component::Prefix(_) | Component::RootDir => {
                result.push(part.as_os_str());
            },
            Component::CurDir => {},
            Component::ParentDir => {
                parts.pop();
            },
            Component::Normal(_) => {
                parts.push(part.as_os_str());
            }
        }
    }

    // Resolve the symlinks where possible
    if parts.len() > 0 {
        for part in parts[..parts.len()-1].iter() {
            result.push(part);

            if can_mode == CanonicalizeMode::None {
                continue;
            }

            match resolve(&result) {
                Err(e) => match can_mode {
                    CanonicalizeMode::Missing => continue,
                    _ => return Err(e)
                },
                Ok(path) => {
                    result.pop();
                    result.push(path);
                }
            }
        }

        result.push(parts.last().unwrap());

        match resolve(&result) {
            Err(e) => { if can_mode == CanonicalizeMode::Existing { return Err(e); } },
            Ok(path) => {
                result.pop();
                result.push(path);
            }
        }
    }
    Ok(result)
}

#[cfg(unix)]
pub fn is_stdin_interactive() -> bool {
    unsafe { libc::isatty(libc::STDIN_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdin_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stdout_interactive() -> bool {
    unsafe { libc::isatty(libc::STDOUT_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdout_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stderr_interactive() -> bool {
    unsafe { libc::isatty(libc::STDERR_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stderr_interactive() -> bool {
    false
}
<commit_msg>Remove trait shim needed before Path stabilized<commit_after>/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Joseph Crail <jbcrail@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#[cfg(unix)]
use super::libc;
use std::env;
use std::fs;
use std::io::{Error, ErrorKind, Result};
use std::path::{Component, Path, PathBuf};

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalizeMode {
    None,
    Normal,
    Existing,
    Missing,
}

fn resolve<P: AsRef<Path>>(original: P) -> Result<PathBuf> {
    const MAX_LINKS_FOLLOWED: u32 = 255;
    let mut followed = 0;
    let mut result = original.as_ref().to_path_buf();
    loop {
        if followed == MAX_LINKS_FOLLOWED {
            return Err(Error::new(ErrorKind::InvalidInput, "maximum links followed"));
        }

        match fs::metadata(&result) {
            Err(e) => return Err(e),
            Ok(ref m) if !m.file_type().is_symlink() => break,
            Ok(..) => {
                followed += 1;
                match fs::read_link(&result) {
                    Ok(path) => {
                        result.pop();
                        result.push(path);
                    },
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
        }
    }
    Ok(result)
}

pub fn canonicalize<P: AsRef<Path>>(original: P, can_mode: CanonicalizeMode) -> Result<PathBuf> {
    // Create an absolute path
    let original = original.as_ref();
    let original = if original.is_absolute() {
        original.to_path_buf()
    } else {
        env::current_dir().unwrap().join(original)
    };

    let mut result = PathBuf::new();
    let mut parts = vec!();

    // Split path by directory separator; add prefix (Windows-only) and root
    // directory to final path buffer; add remaining parts to temporary
    // vector for canonicalization.
    for part in original.components() {
        match part {
            Component::Prefix(_) | Component::RootDir => {
                result.push(part.as_os_str());
            },
            Component::CurDir => {},
            Component::ParentDir => {
                parts.pop();
            },
            Component::Normal(_) => {
                parts.push(part.as_os_str());
            }
        }
    }

    // Resolve the symlinks where possible
    if parts.len() > 0 {
        for part in parts[..parts.len()-1].iter() {
            result.push(part);

            if can_mode == CanonicalizeMode::None {
                continue;
            }

            match resolve(&result) {
                Err(e) => match can_mode {
                    CanonicalizeMode::Missing => continue,
                    _ => return Err(e)
                },
                Ok(path) => {
                    result.pop();
                    result.push(path);
                }
            }
        }

        result.push(parts.last().unwrap());

        match resolve(&result) {
            Err(e) => { if can_mode == CanonicalizeMode::Existing { return Err(e); } },
            Ok(path) => {
                result.pop();
                result.push(path);
            }
        }
    }
    Ok(result)
}

#[cfg(unix)]
pub fn is_stdin_interactive() -> bool {
    unsafe { libc::isatty(libc::STDIN_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdin_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stdout_interactive() -> bool {
    unsafe { libc::isatty(libc::STDOUT_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdout_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stderr_interactive() -> bool {
    unsafe { libc::isatty(libc::STDERR_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stderr_interactive() -> bool {
    false
}
<|endoftext|>


<commit_before>#![feature(core,io)]
#![allow(dead_code)]
//! library with code shared by all generated implementations
extern crate hyper;
extern crate mime;
extern crate "rustc-serialize" as rustc_serialize;
extern crate "yup-oauth2" as oauth2;

// just pull it in the check if it compiles
mod cmn;

/// This module is for testing only, its code is used in mako templates
#[cfg(test)]
mod tests {
    extern crate "yup-hyper-mock" as hyper_mock;
    use super::cmn::*;
    use self::hyper_mock::*;
    use std::io::Read;
    use std::default::Default;

    #[test]
    fn multi_part_reader() {
        let mut r1 = MockStream::with_input(b"foo");
        let mut r2 = MockStream::with_input(b"bar");
        let mut mpr: MultiPartReader = Default::default();

        mpr.add_part(&mut r1, 50, &"application/json".parse().unwrap())
           .add_part(&mut r2, 25, &"application/plain".parse().unwrap());

        let mut res = String::new();
        let r = mpr.read_to_string(&mut res);
        assert_eq!(res.len(), r.clone().unwrap());
        println!("{}", res);

        let expected =
"\r\n--MDuXWGyeE33QFXGchb2VFWc4Z7945d\r\n\
Content-Length: 50\r\n\
Content-Type: application/json\r\n\
\r\n\
foo\r\n\
--MDuXWGyeE33QFXGchb2VFWc4Z7945d\r\n\
Content-Length: 25\r\n\
Content-Type: application/plain\r\n\
\r\n\
bar\r\n\
--MDuXWGyeE33QFXGchb2VFWc4Z7945d";
        // NOTE: This CAN fail, as the underlying header hashmap is not sorted
        // As the test is just for dev, and doesn't run on travis, we are fine,
        // for now. Possible solution would be to omit the size field (make it
        // optional)
        assert_eq!(res, expected);
        assert_eq!(r, Ok(221));
    }
}<commit_msg>feat(common): multibytereader single byte test<commit_after>#![feature(core,io,old_path)]
#![allow(dead_code, deprecated, unused_features)]
//! library with code shared by all generated implementations
extern crate hyper;
extern crate mime;
extern crate "rustc-serialize" as rustc_serialize;
extern crate "yup-oauth2" as oauth2;

// just pull it in the check if it compiles
mod cmn;

/// This module is for testing only, its code is used in mako templates
#[cfg(test)]
mod tests {
    extern crate "yup-hyper-mock" as hyper_mock;
    use super::cmn::*;
    use self::hyper_mock::*;
    use std::io::Read;
    use std::default::Default;
    use std::old_path::BytesContainer;

    const EXPECTED: &'static str =
"\r\n--MDuXWGyeE33QFXGchb2VFWc4Z7945d\r\n\
Content-Length: 50\r\n\
Content-Type: application/json\r\n\
\r\n\
foo\r\n\
--MDuXWGyeE33QFXGchb2VFWc4Z7945d\r\n\
Content-Length: 25\r\n\
Content-Type: application/plain\r\n\
\r\n\
bar\r\n\
--MDuXWGyeE33QFXGchb2VFWc4Z7945d";

    const EXPECTED_LEN: usize= 221;

    #[test]
    fn multi_part_reader() {
        let mut r1 = MockStream::with_input(b"foo");
        let mut r2 = MockStream::with_input(b"bar");
        let mut mpr: MultiPartReader = Default::default();

        mpr.add_part(&mut r1, 50, &"application/json".parse().unwrap())
           .add_part(&mut r2, 25, &"application/plain".parse().unwrap());

        let mut res = String::new();
        let r = mpr.read_to_string(&mut res);
        assert_eq!(res.len(), r.clone().unwrap());

        // NOTE: This CAN fail, as the underlying header hashmap is not sorted
        // As the test is just for dev, and doesn't run on travis, we are fine,
        // for now. Possible solution would be to omit the size field (make it
        // optional)
        // assert_eq!(res, EXPECTED);
        assert_eq!(r, Ok(EXPECTED_LEN));
    }

    #[test]
    fn multi_part_reader_single_byte_read() {
        let mut r1 = MockStream::with_input(b"foo");
        let mut r2 = MockStream::with_input(b"bar");
        let mut mpr: MultiPartReader = Default::default();

        mpr.add_part(&mut r1, 50, &"application/json".parse().unwrap())
           .add_part(&mut r2, 25, &"application/plain".parse().unwrap());

        let mut buf = &mut [0u8];
        let mut v = Vec::<u8>::new();
        while let Ok(br) = mpr.read(buf) {
            if br == 0 {
                break;
            }
            v.push(buf[0]);
        }
        println!("{:?}", v.len());
        println!("{:?}", v.container_as_str().unwrap());
        assert_eq!(v.len(), EXPECTED_LEN);
        assert_eq!(v.container_as_str().unwrap(), EXPECTED);
    }
}<|endoftext|>


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

#[doc(keyword = "as")]
//
/// The type coercion keyword.
///
/// `as` is most commonly used to turn primitive types into other primitive types, but it has other
/// uses that include turning pointers into addresses, addresses into pointers, and pointers into
/// other pointers.
///
/// ```rust
/// let thing1: u8 = 89.0 as u8;
/// assert_eq!('B' as u32, 66);
/// assert_eq!(thing1 as char, 'Y');
/// let thing2: f32 = thing1 as f32 + 10.5;
/// assert_eq!(true as u8 + thing2 as u8, 100);
/// ```
///
/// In general, any coercion that can be performed via writing out type hints can also be done
/// using `as`, so instead of writing `let x: u32 = 123`, you can write `let x = 123 as u32` (Note:
/// `let x = 123u32` would be best in that situation). The same is not true in the other direction,
/// however, explicitly using `as` allows a few more coercions that aren't allowed implicitly, such
/// as changing the type of a raw pointer or turning closures into raw pointers.
///
/// For more information on what `as` is capable of, see the [Reference]
///
/// [Reference]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions
mod as_keyword { }

#[doc(keyword = "const")]
//
/// The keyword for defining constants.
///
/// Sometimes a certain value is used many times throughout a program, and it can become
/// inconvenient to copy it over and over. What's more, it's not always possible or desirable to
/// make it a variable that gets carried around to each function that needs it. In these cases, the
/// `const` keyword provides a convenient alternative to code duplication.
///
/// ```rust
/// const THING: u32 = 0xABAD1DEA;
///
/// let foo = 123 + THING;
/// ```
///
/// Constants must be explicitly typed, unlike with `let` you can't ignore its type and let the
/// compiler figure it out. Any constant value can be defined in a const, which in practice happens
/// to be most things that would be reasonable to have a constant. For example, you can't have a
/// File as a `const`.
///
/// The only lifetime allowed in a constant is 'static, which is the lifetime that encompasses all
/// others in a Rust program. For example, if you wanted to define a constant string, it would look
/// like this:
///
/// ```rust
/// const WORDS: &'static str = "hello rust!";
/// ```
///
/// Thanks to static lifetime elision, you usually don't have to explicitly use 'static:
///
/// ```rust
/// const WORDS: &str = "hello convenience!";
/// ```
///
/// `const` items looks remarkably similar to [`static`] items, which introduces some confusion as
/// to which one should be used at which times. To put it simply, constants are inlined wherever
/// they're used, making using them identical to simply replacing the name of the const with its
/// value. Static variables on the other hand point to a single location in memory, which all
/// accesses share. This means that, unlike with constants, they can't have destructors, but it
/// also means that (via unsafe code) they can be mutable, which is useful for the rare situations
/// in which you can't avoid using global state.
///
/// Constants, as with statics, should always be in SCREAMING_SNAKE_CASE.
///
/// The `const` keyword is also used in raw pointers in combination with `mut`, as seen in `*const
/// T` and `*mut T`. More about that can be read at the [pointer] primitive part of the Rust docs.
///
/// For more detail on `const`, see the [Rust Book] or the [Reference]
///
/// [`static`]: keyword.static.html
/// [pointer]: primitive.pointer.html
/// [Rust Book]: https://doc.rust-lang.org/stable/book/2018-edition/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
/// [Reference]: https://doc.rust-lang.org/reference/items/constant-items.html
mod const_keyword { }

#[doc(keyword = "fn")]
//
/// The `fn` keyword.
///
/// The `fn` keyword is used to declare a function.
///
/// Example:
///
/// ```rust
/// fn some_function() {
///     // code goes in here
/// }
/// ```
///
/// For more information about functions, take a look at the [Rust Book][book].
///
/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html
mod fn_keyword { }

#[doc(keyword = "let")]
//
/// The `let` keyword.
///
/// The `let` keyword is used to declare a variable.
///
/// Example:
///
/// ```rust
/// # #![allow(unused_assignments)]
/// let x = 3; // We create a variable named `x` with the value `3`.
/// ```
///
/// By default, all variables are **not** mutable. If you want a mutable variable,
/// you'll have to use the `mut` keyword.
///
/// Example:
///
/// ```rust
/// # #![allow(unused_assignments)]
/// let mut x = 3; // We create a mutable variable named `x` with the value `3`.
///
/// x += 4; // `x` is now equal to `7`.
/// ```
///
/// For more information about the `let` keyword, take a look at the [Rust Book][book].
///
/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-01-variables-and-mutability.html
mod let_keyword { }

#[doc(keyword = "struct")]
//
/// The keyword used to define structs.
///
/// Structs in Rust come in three flavours: Regular structs, tuple structs,
/// and empty structs.
///
/// ```rust
/// struct Regular {
///     field1: f32,
///     field2: String,
///     pub field3: bool
/// }
///
/// struct Tuple(u32, String);
///
/// struct Empty;
/// ```
///
/// Regular structs are the most commonly used. Each field defined within them has a name and a
/// type, and once defined can be accessed using `example_struct.field` syntax. The fields of a
/// struct share its mutability, so `foo.bar = 2;` would only be valid if `foo` was mutable. Adding
/// `pub` to a field makes it visible to code in other modules, as well as allowing it to be
/// directly accessed and modified.
///
/// Tuple structs are similar to regular structs, but its fields have no names. They are used like
/// tuples, with deconstruction possible via `let TupleStruct(x, y) = foo;` syntax.  For accessing
/// individual variables, the same syntax is used as with regular tuples, namely `foo.0`, `foo.1`,
/// etc, starting at zero.
///
/// Empty structs, or unit-like structs, are most commonly used as markers, for example
/// [`PhantomData`]. Empty structs have a size of zero bytes, but unlike empty enums they can be
/// instantiated, making them similar to the unit type `()`. Unit-like structs are useful when you
/// need to implement a trait on something, but don't need to store any data inside it.
///
/// # Instantiation
///
/// Structs can be instantiated in a manner of different ways, each of which can be mixed and
/// matched as needed. The most common way to make a new struct is via a constructor method such as
/// `new()`, but when that isn't available (or you're writing the constructor itself), struct
/// literal syntax is used:
///
/// ```rust
/// # struct Foo { field1: f32, field2: String, etc: bool }
/// let example = Foo {
///     field1: 42.0,
///     field2: "blah".to_string(),
///     etc: true,
/// };
/// ```
///
/// It's only possible to directly instantiate a struct using struct literal syntax when all of its
/// fields are visible to you.
///
/// There are a handful of shortcuts provided to make writing constructors more convenient, most
/// common of which is the Field Init shorthand. When there is a variable and a field of the same
/// name, the assignment can be simplified from `field: field` into simply `field`. The following
/// example of a hypothetical constructor demonstrates this:
///
/// ```rust
/// struct User {
///     name: String,
///     admin: bool,
/// }
///
/// impl User {
///     pub fn new(name: String) -> Self {
///         Self {
///             name,
///             admin: false,
///         }
///     }
/// }
/// ```
///
/// Another shortcut for struct instantiation is available, used when you need to make a new
/// struct that has the same values as most of a previous struct of the same type, called struct
/// update syntax:
///
/// ```rust
/// # struct Foo { field1: String, field2: () }
/// # let thing = Foo { field1: "".to_string(), field2: () };
/// let updated_thing = Foo {
///     field1: "a new value".to_string(),
///     ..thing
/// };
/// ```
///
/// Tuple structs are instantiated in the same way as tuples themselves, except with the struct's
/// name as a prefix: `Foo(123, false, 0.1)`.
///
/// Empty structs are instantiated with just their name, and don't need anything else. `let thing =
/// EmptyStruct;`
///
/// # Style conventions
///
/// Structs are always written in CamelCase, with few exceptions. While the trailing comma on a
/// struct's list of fields can be omitted, it's usually kept for convenience in adding and
/// removing fields down the line.
///
/// For more information on structs, take a look at the [Rust Book][book] or the
/// [Reference][reference].
///
/// [`PhantomData`]: marker/struct.PhantomData.html
/// [book]: https://doc.rust-lang.org/book/second-edition/ch05-01-defining-structs.html
/// [reference]: https://doc.rust-lang.org/reference/items/structs.html
mod struct_keyword { }
<commit_msg>Add docs for `crate` keyword<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[doc(keyword = "as")]
//
/// The type coercion keyword.
///
/// `as` is most commonly used to turn primitive types into other primitive types, but it has other
/// uses that include turning pointers into addresses, addresses into pointers, and pointers into
/// other pointers.
///
/// ```rust
/// let thing1: u8 = 89.0 as u8;
/// assert_eq!('B' as u32, 66);
/// assert_eq!(thing1 as char, 'Y');
/// let thing2: f32 = thing1 as f32 + 10.5;
/// assert_eq!(true as u8 + thing2 as u8, 100);
/// ```
///
/// In general, any coercion that can be performed via writing out type hints can also be done
/// using `as`, so instead of writing `let x: u32 = 123`, you can write `let x = 123 as u32` (Note:
/// `let x = 123u32` would be best in that situation). The same is not true in the other direction,
/// however, explicitly using `as` allows a few more coercions that aren't allowed implicitly, such
/// as changing the type of a raw pointer or turning closures into raw pointers.
///
/// For more information on what `as` is capable of, see the [Reference]
///
/// [Reference]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions
mod as_keyword { }

#[doc(keyword = "const")]
//
/// The keyword for defining constants.
///
/// Sometimes a certain value is used many times throughout a program, and it can become
/// inconvenient to copy it over and over. What's more, it's not always possible or desirable to
/// make it a variable that gets carried around to each function that needs it. In these cases, the
/// `const` keyword provides a convenient alternative to code duplication.
///
/// ```rust
/// const THING: u32 = 0xABAD1DEA;
///
/// let foo = 123 + THING;
/// ```
///
/// Constants must be explicitly typed, unlike with `let` you can't ignore its type and let the
/// compiler figure it out. Any constant value can be defined in a const, which in practice happens
/// to be most things that would be reasonable to have a constant. For example, you can't have a
/// File as a `const`.
///
/// The only lifetime allowed in a constant is 'static, which is the lifetime that encompasses all
/// others in a Rust program. For example, if you wanted to define a constant string, it would look
/// like this:
///
/// ```rust
/// const WORDS: &'static str = "hello rust!";
/// ```
///
/// Thanks to static lifetime elision, you usually don't have to explicitly use 'static:
///
/// ```rust
/// const WORDS: &str = "hello convenience!";
/// ```
///
/// `const` items looks remarkably similar to [`static`] items, which introduces some confusion as
/// to which one should be used at which times. To put it simply, constants are inlined wherever
/// they're used, making using them identical to simply replacing the name of the const with its
/// value. Static variables on the other hand point to a single location in memory, which all
/// accesses share. This means that, unlike with constants, they can't have destructors, but it
/// also means that (via unsafe code) they can be mutable, which is useful for the rare situations
/// in which you can't avoid using global state.
///
/// Constants, as with statics, should always be in SCREAMING_SNAKE_CASE.
///
/// The `const` keyword is also used in raw pointers in combination with `mut`, as seen in `*const
/// T` and `*mut T`. More about that can be read at the [pointer] primitive part of the Rust docs.
///
/// For more detail on `const`, see the [Rust Book] or the [Reference]
///
/// [`static`]: keyword.static.html
/// [pointer]: primitive.pointer.html
/// [Rust Book]: https://doc.rust-lang.org/stable/book/2018-edition/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
/// [Reference]: https://doc.rust-lang.org/reference/items/constant-items.html
mod const_keyword { }

#[doc(keyword = "crate")]
//
/// The `crate` keyword.
///
/// The primary use of the `crate` keyword is as a part of `extern crate` declarations, which are
/// used to specify a dependency on a crate external to the one it's declared in. Crates are the
/// fundamental compilation unit of Rust code, and can be seen as libraries or projects. More can
/// be read about crates in the [Reference].
///
/// ```rust ignore
/// extern crate rand;
/// extern crate my_crate as thing;
/// extern crate std; // implicitly added to the root of every Rust project
/// ```
///
/// The `as` keyword can be used to change what the crate is referred to as in your project. If a
/// crate name includes a dash, it is implicitly imported with the dashes replaced by underscores.
///
/// `crate` is also used as in conjunction with [`pub`] to signify that the item it's attached to
/// is public only to other members of the same crate it's in.
///
/// ```rust
/// # #[allow(unused_imports)]
/// pub(crate) use std::io::Error as IoError;
/// pub(crate) enum CoolMarkerType { }
/// pub struct PublicThing {
///     pub(crate) semi_secret_thing: bool,
/// }
/// ```
///
/// [Reference]: https://doc.rust-lang.org/reference/items/extern-crates.html
/// [`pub`]: keyword.pub.html
mod crate_keyword { }

#[doc(keyword = "fn")]
//
/// The `fn` keyword.
///
/// The `fn` keyword is used to declare a function.
///
/// Example:
///
/// ```rust
/// fn some_function() {
///     // code goes in here
/// }
/// ```
///
/// For more information about functions, take a look at the [Rust Book][book].
///
/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html
mod fn_keyword { }

#[doc(keyword = "let")]
//
/// The `let` keyword.
///
/// The `let` keyword is used to declare a variable.
///
/// Example:
///
/// ```rust
/// # #![allow(unused_assignments)]
/// let x = 3; // We create a variable named `x` with the value `3`.
/// ```
///
/// By default, all variables are **not** mutable. If you want a mutable variable,
/// you'll have to use the `mut` keyword.
///
/// Example:
///
/// ```rust
/// # #![allow(unused_assignments)]
/// let mut x = 3; // We create a mutable variable named `x` with the value `3`.
///
/// x += 4; // `x` is now equal to `7`.
/// ```
///
/// For more information about the `let` keyword, take a look at the [Rust Book][book].
///
/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-01-variables-and-mutability.html
mod let_keyword { }

#[doc(keyword = "struct")]
//
/// The keyword used to define structs.
///
/// Structs in Rust come in three flavours: Regular structs, tuple structs,
/// and empty structs.
///
/// ```rust
/// struct Regular {
///     field1: f32,
///     field2: String,
///     pub field3: bool
/// }
///
/// struct Tuple(u32, String);
///
/// struct Empty;
/// ```
///
/// Regular structs are the most commonly used. Each field defined within them has a name and a
/// type, and once defined can be accessed using `example_struct.field` syntax. The fields of a
/// struct share its mutability, so `foo.bar = 2;` would only be valid if `foo` was mutable. Adding
/// `pub` to a field makes it visible to code in other modules, as well as allowing it to be
/// directly accessed and modified.
///
/// Tuple structs are similar to regular structs, but its fields have no names. They are used like
/// tuples, with deconstruction possible via `let TupleStruct(x, y) = foo;` syntax.  For accessing
/// individual variables, the same syntax is used as with regular tuples, namely `foo.0`, `foo.1`,
/// etc, starting at zero.
///
/// Empty structs, or unit-like structs, are most commonly used as markers, for example
/// [`PhantomData`]. Empty structs have a size of zero bytes, but unlike empty enums they can be
/// instantiated, making them similar to the unit type `()`. Unit-like structs are useful when you
/// need to implement a trait on something, but don't need to store any data inside it.
///
/// # Instantiation
///
/// Structs can be instantiated in a manner of different ways, each of which can be mixed and
/// matched as needed. The most common way to make a new struct is via a constructor method such as
/// `new()`, but when that isn't available (or you're writing the constructor itself), struct
/// literal syntax is used:
///
/// ```rust
/// # struct Foo { field1: f32, field2: String, etc: bool }
/// let example = Foo {
///     field1: 42.0,
///     field2: "blah".to_string(),
///     etc: true,
/// };
/// ```
///
/// It's only possible to directly instantiate a struct using struct literal syntax when all of its
/// fields are visible to you.
///
/// There are a handful of shortcuts provided to make writing constructors more convenient, most
/// common of which is the Field Init shorthand. When there is a variable and a field of the same
/// name, the assignment can be simplified from `field: field` into simply `field`. The following
/// example of a hypothetical constructor demonstrates this:
///
/// ```rust
/// struct User {
///     name: String,
///     admin: bool,
/// }
///
/// impl User {
///     pub fn new(name: String) -> Self {
///         Self {
///             name,
///             admin: false,
///         }
///     }
/// }
/// ```
///
/// Another shortcut for struct instantiation is available, used when you need to make a new
/// struct that has the same values as most of a previous struct of the same type, called struct
/// update syntax:
///
/// ```rust
/// # struct Foo { field1: String, field2: () }
/// # let thing = Foo { field1: "".to_string(), field2: () };
/// let updated_thing = Foo {
///     field1: "a new value".to_string(),
///     ..thing
/// };
/// ```
///
/// Tuple structs are instantiated in the same way as tuples themselves, except with the struct's
/// name as a prefix: `Foo(123, false, 0.1)`.
///
/// Empty structs are instantiated with just their name, and don't need anything else. `let thing =
/// EmptyStruct;`
///
/// # Style conventions
///
/// Structs are always written in CamelCase, with few exceptions. While the trailing comma on a
/// struct's list of fields can be omitted, it's usually kept for convenience in adding and
/// removing fields down the line.
///
/// For more information on structs, take a look at the [Rust Book][book] or the
/// [Reference][reference].
///
/// [`PhantomData`]: marker/struct.PhantomData.html
/// [book]: https://doc.rust-lang.org/book/second-edition/ch05-01-defining-structs.html
/// [reference]: https://doc.rust-lang.org/reference/items/structs.html
mod struct_keyword { }
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::mem;

use llvm_sys::core;
use llvm_sys::prelude::{
  LLVMBuilderRef,
  LLVMValueRef
};
use libc::{c_char, c_uint};

use types::Ty;
use block::BasicBlock;
use value::{Function, Value, PhiNode};

static NULL_NAME:[c_char; 1] = [0];

pub struct Builder(pub LLVMBuilderRef);
impl_dispose!(Builder, core::LLVMDisposeBuilder);

impl Builder {

  pub fn get_insert_block(&self) -> BasicBlock
  {
    BasicBlock(unsafe { core::LLVMGetInsertBlock(self.0)})
  }

  /// Position the builder at `instr` within `block`.
  pub fn position_at(&self, block: &BasicBlock, instr: &Value)
  {
    unsafe { core::LLVMPositionBuilder(self.0, block.0, instr.0) }
  }

  /// Position the builder at the end of `block`.
  pub fn position_at_end(&self, block: &BasicBlock)
  {
    unsafe { core::LLVMPositionBuilderAtEnd(self.0, block.0) }
  }

  /// Build an instruction that returns from the function with void.
  pub fn create_ret_void(&self) -> Value
  {
    Value(unsafe {core::LLVMBuildRetVoid(self.0)})
  }

  /// Build an instruction that returns from the function with `value`.
  pub fn create_ret(&self, value: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildRet(self.0, value.0)})
  }

  /// Build an instruction that allocates an array with the element type `elem` and
  /// the size `size`.
  ///
  /// The size of this array will be the size of `elem` times `size`.
  pub fn build_array_alloca(&self, elem: &Ty, size: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildArrayAlloca(self.0,
    														 elem.0,
    														 size.0,
    														 NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that allocates a pointer to fit the size of `ty` then returns this
  /// pointer.
  ///
  /// Make sure to call `build_free` with the pointer value when you're done with it, or you're
  /// gonna have a bad time.
  pub fn create_alloca(&self, ty: &Ty) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildAlloca(self.0,
    												ty.0,
    												NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that frees the `val`, which _MUST_ be a pointer that was returned
  /// from `build_alloca`.
  pub fn create_free(&self, val: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildFree(self.0, val.0) })
  }

  /// Build an instruction that store the value `val` in the pointer `ptr`.
  pub fn create_store(&self, val: &Value, ptr: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildStore(self.0, val.0, ptr.0) })
  }

  /// Build an instruction that branches to the block `dest`.
  pub fn create_br(&self, dest: &BasicBlock) -> Value
  {
    Value(unsafe { core::LLVMBuildBr(self.0, dest.0)})
  }

  /// Build an instruction that branches to `if_block` if `cond` evaluates to true, and
  /// `else_block` otherwise.
  pub fn create_cond_br(&self, cond: &Value,
  	                    if_block: &BasicBlock, else_block: Option<&BasicBlock>) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildCondBr(self.0,
    		                    cond.0,
    		                    if_block.0,
    		                    mem::transmute(else_block))
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  fn create_call_internal(&self, func: &Function, args: &[&Value], tail_call: bool) -> Value
  {
    let ref_array = to_llvmref_array!(args, LLVMValueRef);

    Value(unsafe {
        let call = core::LLVMBuildCall(self.0,
        	                             func.0,
                                       ref_array.as_ptr() as *mut LLVMValueRef,
        	                             args.len() as c_uint,
        	                             NULL_NAME.as_ptr());
        core::LLVMSetTailCall(call, if tail_call {1} else {0});
        call.into()
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, false)
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_tail_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, true)
  }

  /// Build an instruction that yields to `true_val` if `cond` is equal to `1`, and `false_val`
  /// otherwise.
  pub fn create_select(&self, cond: &Value, true_val: &Value, false_val: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildSelect(self.0,
    		                    cond.0,
    		                    true_val.0,
    		                    false_val.0,
    		                    NULL_NAME.as_ptr()) })
  }

  /// Build an instruction that casts a value into a certain type.
  pub fn create_bit_cast(&self, value: &Value, dest: &Ty) -> Value
  {
    Value(unsafe { core::LLVMBuildBitCast(
    		self.0,
    		value.0,
    		dest.0,
    		NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that inserts a value into an aggregate data value.
  pub fn create_insert_value(&self, agg: &Value, elem: &Value, index: usize) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildInsertValue(self.0,
    		                         agg.0,
    		                         elem.0,
    		                         index as c_uint,
    		                         NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that extracts a value from an aggregate type.
	pub fn create_extract_value(&self, agg: &Value, index: usize) -> Value {
    Value(unsafe {
    	core::LLVMBuildExtractValue(self.0,
    		                          agg.0,
    		                          index as c_uint,
    		                          NULL_NAME.as_ptr())
   	})
  }

  /// Build an instruction that computes the address of a subelement of an aggregate data
  /// structure.
  ///
  /// Basically type-safe pointer arithmetic.
  pub fn create_gep(&self, pointer: &Value, indices: &[&Value]) -> Value
  {
    let ref_array = to_llvmref_array!(indices, LLVMValueRef);

    Value(unsafe {
    	core::LLVMBuildInBoundsGEP(self.0,
    	                           pointer.0,
    	                           ref_array.as_ptr() as *mut LLVMValueRef,
    	                           indices.len() as c_uint,
    	                           NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction to select a value depending on the predecessor of the current block.
  pub fn create_phi(&self, ty: &Ty, name: &str) -> PhiNode
  {
	  PhiNode(unsafe {
	  	core::LLVMBuildPhi(self.0, ty.0, ::util::chars::from_str(name))
  	})
  }

  /// Build an instruction that runs whichever block matches the value, or `default` if none of
  /// them matched it.
  pub fn create_switch(&self,
  	                   value: &Value,
  	                   default: &BasicBlock,
  	                   cases: &[(&Value, &BasicBlock)]) -> Value {
    Value(unsafe {
      let switch = core::LLVMBuildSwitch(self.0,
      	                                 value.0,
      	                                 default.0,
      	                                 cases.len() as c_uint);
      for case in cases {
        core::LLVMAddCase(switch, (case.0).0, (case.1).0);
      }

      switch
    })
  }
}

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

	#[test]
	pub fn test_cond_br()
	{
		let jit = JitCompiler::new("test1").ok().unwrap();
    let ctx = jit.context();

    let func_ty = jit.create_func_ty(&f64::llvm_ty(ctx), &[&f64::llvm_ty(ctx)]);
    let func = jit.add_func("fib", &func_ty);
    let value = func.arg(0);

    let entry = func.append("entry");
    let then_bb = func.append("then_block");
    let else_bb = func.append("else_block");
    let merge_bb = func.append("merge_block");

    let builder = jit.builder();
    builder.position_at_end(&entry);

    let local = builder.create_alloca(&u64::llvm_ty(&ctx));

    let cond = builder.create_cmp(&value, 5u64.to_value(&ctx), Predicate::LessThan);
	}
}<commit_msg>Add create_cmp() and create_ucmp() to Builder.<commit_after>#![allow(dead_code)]

use std::mem;

use llvm_sys::{core, LLVMIntPredicate, LLVMRealPredicate};
use llvm_sys::prelude::{
  LLVMBuilderRef,
  LLVMValueRef
};
use libc::{c_char, c_uint};

use types::Ty;
use block::BasicBlock;
use value::{Function, Value, ValueRef, Predicate, PhiNode};

static NULL_NAME:[c_char; 1] = [0];

pub struct Builder(pub LLVMBuilderRef);
impl_dispose!(Builder, core::LLVMDisposeBuilder);

impl Builder {

  pub fn get_insert_block(&self) -> BasicBlock
  {
    BasicBlock(unsafe { core::LLVMGetInsertBlock(self.0)})
  }

  /// Position the builder at `instr` within `block`.
  pub fn position_at(&self, block: &BasicBlock, instr: &Value)
  {
    unsafe { core::LLVMPositionBuilder(self.0, block.0, instr.0) }
  }

  /// Position the builder at the end of `block`.
  pub fn position_at_end(&self, block: &BasicBlock)
  {
    unsafe { core::LLVMPositionBuilderAtEnd(self.0, block.0) }
  }

  /// Build an instruction that returns from the function with void.
  pub fn create_ret_void(&self) -> Value
  {
    Value(unsafe {core::LLVMBuildRetVoid(self.0)})
  }

  /// Build an instruction that returns from the function with `value`.
  pub fn create_ret(&self, value: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildRet(self.0, value.0)})
  }

  /// Build an instruction that allocates an array with the element type `elem` and
  /// the size `size`.
  ///
  /// The size of this array will be the size of `elem` times `size`.
  pub fn build_array_alloca(&self, elem: &Ty, size: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildArrayAlloca(self.0,
    														 elem.0,
    														 size.0,
    														 NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that allocates a pointer to fit the size of `ty` then returns this
  /// pointer.
  ///
  /// Make sure to call `build_free` with the pointer value when you're done with it, or you're
  /// gonna have a bad time.
  pub fn create_alloca(&self, ty: &Ty) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildAlloca(self.0,
    												ty.0,
    												NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that frees the `val`, which _MUST_ be a pointer that was returned
  /// from `build_alloca`.
  pub fn create_free(&self, val: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildFree(self.0, val.0) })
  }

  /// Build an instruction that store the value `val` in the pointer `ptr`.
  pub fn create_store(&self, val: &Value, ptr: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildStore(self.0, val.0, ptr.0) })
  }

  /// Build an instruction that branches to the block `dest`.
  pub fn create_br(&self, dest: &BasicBlock) -> Value
  {
    Value(unsafe { core::LLVMBuildBr(self.0, dest.0)})
  }

  /// Build an instruction that branches to `if_block` if `cond` evaluates to true, and
  /// `else_block` otherwise.
  pub fn create_cond_br(&self, cond: &Value,
  	                    if_block: &BasicBlock, else_block: Option<&BasicBlock>) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildCondBr(self.0,
    		                    cond.0,
    		                    if_block.0,
    		                    mem::transmute(else_block))
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  fn create_call_internal(&self, func: &Function, args: &[&Value], tail_call: bool) -> Value
  {
    let ref_array = to_llvmref_array!(args, LLVMValueRef);

    Value(unsafe {
        let call = core::LLVMBuildCall(self.0,
        	                             func.0,
                                       ref_array.as_ptr() as *mut LLVMValueRef,
        	                             args.len() as c_uint,
        	                             NULL_NAME.as_ptr());
        core::LLVMSetTailCall(call, if tail_call {1} else {0});
        call.into()
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, false)
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_tail_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, true)
  }

  /// Build an instruction that yields to `true_val` if `cond` is equal to `1`, and `false_val`
  /// otherwise.
  pub fn create_select(&self, cond: &Value, true_val: &Value, false_val: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildSelect(self.0,
    		                    cond.0,
    		                    true_val.0,
    		                    false_val.0,
    		                    NULL_NAME.as_ptr()) })
  }

  /// Build an instruction that casts a value into a certain type.
  pub fn create_bit_cast(&self, value: &Value, dest: &Ty) -> Value
  {
    Value(unsafe { core::LLVMBuildBitCast(
    		self.0,
    		value.0,
    		dest.0,
    		NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that inserts a value into an aggregate data value.
  pub fn create_insert_value(&self, agg: &Value, elem: &Value, index: usize) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildInsertValue(self.0,
    		                         agg.0,
    		                         elem.0,
    		                         index as c_uint,
    		                         NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that extracts a value from an aggregate type.
	pub fn create_extract_value(&self, agg: &Value, index: usize) -> Value {
    Value(unsafe {
    	core::LLVMBuildExtractValue(self.0,
    		                          agg.0,
    		                          index as c_uint,
    		                          NULL_NAME.as_ptr())
   	})
  }

  /// Build an instruction to compare two values with the predicate given.
  pub fn create_cmp(&self, l: &Value, r: &Value, pred: Predicate) -> Value
  {
    self.create_cmp_internal(l, r, pred, true)
  }

  /// Build an instruction to compare two values with the predicate given.
  pub fn create_ucmp(&self, l: &Value, r: &Value, pred: Predicate) -> Value
  {
    self.create_cmp_internal(l, r, pred, false)
  }

  fn create_cmp_internal(&self, l: &Value, r: &Value,
  											 pred: Predicate, signed: bool) -> Value {
  	let (lhs_ty, rhs_ty) = (l.ty(), r.ty());
    assert_eq!(lhs_ty, rhs_ty);

    if lhs_ty.is_integer() {
	    let p = match (pred, signed) {
	    	(Predicate::Eq,    _)   => LLVMIntPredicate::LLVMIntEQ,
	    	(Predicate::NotEq, _)   => LLVMIntPredicate::LLVMIntNE,
	    	(Predicate::Lth, true)  => LLVMIntPredicate::LLVMIntSLT,
	    	(Predicate::Lth, false) => LLVMIntPredicate::LLVMIntULT,
	    	(Predicate::Leq, true)  => LLVMIntPredicate::LLVMIntSLE,
	    	(Predicate::Leq, false) => LLVMIntPredicate::LLVMIntULE,
	    	(Predicate::Gth, true)  => LLVMIntPredicate::LLVMIntSGT,
	    	(Predicate::Gth, false) => LLVMIntPredicate::LLVMIntUGT,
	    	(Predicate::Geq, true)  => LLVMIntPredicate::LLVMIntSGE,
	    	(Predicate::Geq, false) => LLVMIntPredicate::LLVMIntUGE,
	    };

	    Value(unsafe {
		    core::LLVMBuildICmp(self.0,
	    		                  p,
	     		                  l.0, r.0,
	     		                  NULL_NAME.as_ptr())
	    })

    } else if lhs_ty.is_float() {
    	let p = match pred {
        Predicate::Eq    => LLVMRealPredicate::LLVMRealOEQ,
        Predicate::NotEq => LLVMRealPredicate::LLVMRealONE,
        Predicate::Gth   => LLVMRealPredicate::LLVMRealOGT,
        Predicate::Geq   => LLVMRealPredicate::LLVMRealOGE,
        Predicate::Lth   => LLVMRealPredicate::LLVMRealOLT,
        Predicate::Leq   => LLVMRealPredicate::LLVMRealOLE
      };

   	  Value(unsafe {
      	core::LLVMBuildFCmp(self.0,
      		                 p, l.0, r.0,
      		                 NULL_NAME.as_ptr())
      })

    } else {
      panic!("expected numbers, got {:?}", lhs_ty)
    }
  }

  /// Build an instruction that computes the address of a subelement of an aggregate data
  /// structure.
  ///
  /// Basically type-safe pointer arithmetic.
  pub fn create_gep(&self, pointer: &Value, indices: &[&Value]) -> Value
  {
    let ref_array = to_llvmref_array!(indices, LLVMValueRef);

    Value(unsafe {
    	core::LLVMBuildInBoundsGEP(self.0,
    	                           pointer.0,
    	                           ref_array.as_ptr() as *mut LLVMValueRef,
    	                           indices.len() as c_uint,
    	                           NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction to select a value depending on the predecessor of the current block.
  pub fn create_phi(&self, ty: &Ty, name: &str) -> PhiNode
  {
	  PhiNode(unsafe {
	  	core::LLVMBuildPhi(self.0, ty.0, ::util::chars::from_str(name))
  	})
  }

  /// Build an instruction that runs whichever block matches the value, or `default` if none of
  /// them matched it.
  pub fn create_switch(&self,
  	                   value: &Value,
  	                   default: &BasicBlock,
  	                   cases: &[(&Value, &BasicBlock)]) -> Value {
    Value(unsafe {
      let switch = core::LLVMBuildSwitch(self.0,
      	                                 value.0,
      	                                 default.0,
      	                                 cases.len() as c_uint);
      for case in cases {
        core::LLVMAddCase(switch, (case.0).0, (case.1).0);
      }

      switch
    })
  }
}

#[cfg(test)]
mod tests {
	use super::*;
  use super::super::*;
  use types::LLVMTy;
  use value::{Predicate, ToValue};

	#[test]
	pub fn test_cond_br()
	{
		let jit = JitCompiler::new("test1").ok().unwrap();
    let ctx = jit.context();

    let func_ty = jit.create_func_ty(&f64::llvm_ty(ctx), &[&f64::llvm_ty(ctx)]);
    let func = jit.add_func("fib", &func_ty);
    let value = func.arg(0);

    let entry = func.append("entry");
    let then_bb = func.append("then_block");
    let else_bb = func.append("else_block");
    let merge_bb = func.append("merge_block");

    let builder = jit.builder();
    builder.position_at_end(&entry);

    let local = builder.create_alloca(&u64::llvm_ty(ctx));

    let cond = builder.create_cmp(&value.into(), &5.0f64.to_value(ctx), Predicate::Lth);
	}
}<|endoftext|>


<commit_before>use std::collections::{VecDeque, HashMap};

use memory::{StaticAllocator, MemoryBlock};

use super::item_type::ItemType;

/// Represents a single level of scope
pub type Scope = HashMap<String, (ItemType, MemoryBlock)>;

pub struct ScopeStack {
    stack: VecDeque<Scope>,
    allocator: StaticAllocator,
}

impl ScopeStack {
    pub fn new() -> ScopeStack {
        ScopeStack {
            stack: {
                let mut queue = VecDeque::new();
                queue.push_back(Scope::new());
                queue
            },
            allocator: StaticAllocator::new(),
        }
    }

    /// Pushes a new level of scope onto the stack
    /// This scope will become the current scope
    pub fn push_scope(&mut self) {
        self.stack.push_back(Scope::new());
    }

    /// Removes and returns the top level scope (current scope)
    ///
    /// # Panics
    /// Panics if there is no scope in the stack
    pub fn pop_scope(&mut self) -> Scope {
        self.stack.pop_back().unwrap()
    }

    /// Looks up a name starting at the current scope
    pub fn lookup(&self, name: &str) -> Option<&(ItemType, MemoryBlock)> {
        self.stack.iter().rev().map(|sc| sc.get(name)).find(|r| r.is_some()).unwrap_or(None)
    }

    /// Declares a name with the given type, allocates enough space for that type
    /// The name is declared in the "current" scope which is at the top of the stack
    /// Returns the allocated memory block
    pub fn declare(&mut self, name: String, typ: &ItemType) -> MemoryBlock {
        let mem = self.allocate(typ);
        // It's OK to overwrite existing names because we support rebinding
        if let Some(scope) = self.stack.back_mut() {
            scope.insert(name, (typ.clone(), mem));
        }
        else {
            panic!("Attempt to declare name despite having no current scope");
        }

        mem
    }

    /// Allocate a memory block that is large enough for the given type
    /// Does not associate memory block with a name which means it cannot be looked up later
    /// Returns the allocated memory block
    pub fn allocate(&mut self, typ: &ItemType) -> MemoryBlock {
        let size = typ.required_size(self);
        self.allocator.allocate(size)
    }
}
<commit_msg>Modifying scope so that lookup returns all definitions in every scope<commit_after>use std::collections::{VecDeque, HashMap};

use memory::{StaticAllocator, MemoryBlock};

use super::item_type::ItemType;

/// Represents a single level of scope
pub type Scope = HashMap<String, (ItemType, MemoryBlock)>;

pub struct ScopeStack {
    stack: VecDeque<Scope>,
    allocator: StaticAllocator,
}

impl ScopeStack {
    pub fn new() -> ScopeStack {
        ScopeStack {
            stack: {
                let mut queue = VecDeque::new();
                queue.push_back(Scope::new());
                queue
            },
            allocator: StaticAllocator::new(),
        }
    }

    /// Pushes a new level of scope onto the stack
    /// This scope will become the current scope
    pub fn push_scope(&mut self) {
        self.stack.push_back(Scope::new());
    }

    /// Removes and returns the top level scope (current scope)
    ///
    /// # Panics
    /// Panics if there is no scope in the stack
    pub fn pop_scope(&mut self) -> Scope {
        self.stack.pop_back().unwrap()
    }

    /// Looks up a name starting at the current scope
    /// Returns ALL matches so that the caller can determine which definition is
    /// the correct one
    /// Definitions are returned in order from latest definition to oldest
    /// Always use the first definition that matches the type you are looking for
    pub fn lookup(&self, name: &str) -> Vec<&(ItemType, MemoryBlock)> {
        self.stack.iter().rev().map(|sc| sc.get(name)).fold(Vec::new(), |mut acc, r| match r {
            Some(def) => {
                acc.push(def);
                acc
            },
            None => acc,
        })
    }

    /// Declares a name with the given type, allocates enough space for that type
    /// The name is declared in the "current" scope which is at the top of the stack
    /// Returns the allocated memory block
    pub fn declare(&mut self, name: String, typ: &ItemType) -> MemoryBlock {
        let mem = self.allocate(typ);
        // It's OK to overwrite existing names because we support rebinding
        if let Some(scope) = self.stack.back_mut() {
            scope.insert(name, (typ.clone(), mem));
        }
        else {
            panic!("Attempt to declare name despite having no current scope");
        }

        mem
    }

    /// Allocate a memory block that is large enough for the given type
    /// Does not associate memory block with a name which means it cannot be looked up later
    /// Returns the allocated memory block
    pub fn allocate(&mut self, typ: &ItemType) -> MemoryBlock {
        let size = typ.required_size(self);
        self.allocator.allocate(size)
    }
}

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

    #[test]
    fn multiple_definitions() {
        let mut scope = ScopeStack::new();
        assert_eq!(scope.lookup("foo").len(), 0);

        scope.declare("foo".to_owned(), unimplemented!());
        assert_eq!(scope.lookup("foo").len(), 1);

        // Declaring the same name in the same scope should overwrite the
        // definition
        scope.declare("foo".to_owned(), unimplemented!());
        assert_eq!(scope.lookup("foo").len(), 1);

        scope.push_scope();
        // Declaring foo in another scope should add a definition
        scope.declare("foo".to_owned(), unimplemented!());
        assert_eq!(scope.lookup("foo").len(), 2);

        // Declaring the same name in the same scope should overwrite the
        // definition
        scope.declare("foo".to_owned(), unimplemented!());
        assert_eq!(scope.lookup("foo").len(), 2);
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "multipart")]
use super::multipart::Form;
/// dox
use bytes::Bytes;
use js_sys::{Array, Uint8Array};
use std::fmt;
use wasm_bindgen::JsValue;

/// The body of a `Request`.
///
/// In most cases, this is not needed directly, as the
/// [`RequestBuilder.body`][builder] method uses `Into<Body>`, which allows
/// passing many things (like a string or vector of bytes).
///
/// [builder]: ./struct.RequestBuilder.html#method.body
pub struct Body {
    inner: Inner,
}

enum Inner {
    Bytes(Bytes),
    #[cfg(feature = "multipart")]
    Multipart(Form),
}

impl Body {
    pub(crate) fn to_js_value(&self) -> crate::Result<JsValue> {
        match &self.inner {
            Inner::Bytes(body_bytes) => {
                let body_bytes: &[u8] = body_bytes.as_ref();
                let body_uint8_array: Uint8Array = body_bytes.into();
                let body_array = Array::new();
                body_array.push(&body_uint8_array);
                let js_value: &JsValue = body_array.as_ref();
                Ok(js_value.to_owned())
            }
            #[cfg(feature = "multipart")]
            Inner::Multipart(form) => {
                let form_data = form.to_form_data()?;
                let js_value: &JsValue = form_data.as_ref();
                Ok(js_value.to_owned())
            }
        }
    }

    #[inline]
    #[cfg(feature = "multipart")]
    pub(crate) fn from_form(f: Form) -> Body {
        Self {
            inner: Inner::Multipart(f),
        }
    }

    pub(crate) fn is_empty(&self) -> bool {
        match &self.inner {
            Inner::Bytes(bytes) => bytes.is_empty(),
            #[cfg(feature = "multipart")]
            Inner::Multipart(form) => form.is_empty(),
        }
    }

    pub(crate) fn try_clone(&self) -> Option<Body> {
        match &self.inner {
            Inner::Bytes(bytes) => Some(Self {
                inner: Inner::Bytes(bytes.clone()),
            }),
            #[cfg(feature = "multipart")]
            Inner::Multipart(_) => None,
        }
    }
}

impl From<Bytes> for Body {
    #[inline]
    fn from(bytes: Bytes) -> Body {
        Body {
            inner: Inner::Bytes(bytes),
        }
    }
}

impl From<Vec<u8>> for Body {
    #[inline]
    fn from(vec: Vec<u8>) -> Body {
        Body {
            inner: Inner::Bytes(vec.into()),
        }
    }
}

impl From<&'static [u8]> for Body {
    #[inline]
    fn from(s: &'static [u8]) -> Body {
        Body {
            inner: Inner::Bytes(Bytes::from_static(s)),
        }
    }
}

impl From<String> for Body {
    #[inline]
    fn from(s: String) -> Body {
        Body {
            inner: Inner::Bytes(s.into()),
        }
    }
}

impl From<&'static str> for Body {
    #[inline]
    fn from(s: &'static str) -> Body {
        s.as_bytes().into()
    }
}

impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Body").finish()
    }
}
<commit_msg>wasm: add missing `as_bytes` method to `Body` implementation (#1270)<commit_after>#[cfg(feature = "multipart")]
use super::multipart::Form;
/// dox
use bytes::Bytes;
use js_sys::{Array, Uint8Array};
use std::fmt;
use wasm_bindgen::JsValue;

/// The body of a `Request`.
///
/// In most cases, this is not needed directly, as the
/// [`RequestBuilder.body`][builder] method uses `Into<Body>`, which allows
/// passing many things (like a string or vector of bytes).
///
/// [builder]: ./struct.RequestBuilder.html#method.body
pub struct Body {
    inner: Inner,
}

enum Inner {
    Bytes(Bytes),
    #[cfg(feature = "multipart")]
    Multipart(Form),
}

impl Body {
    /// Returns a reference to the internal data of the `Body`.
    ///
    /// `None` is returned, if the underlying data is a multipart form.
    #[inline]
    pub fn as_bytes(&self) -> Option<&[u8]> {
        match &self.inner {
            Inner::Bytes(bytes) => Some(bytes.as_ref()),
            #[cfg(feature = "multipart")]
            Inner::Multipart(_) => None,
        }
    }
    pub(crate) fn to_js_value(&self) -> crate::Result<JsValue> {
        match &self.inner {
            Inner::Bytes(body_bytes) => {
                let body_bytes: &[u8] = body_bytes.as_ref();
                let body_uint8_array: Uint8Array = body_bytes.into();
                let body_array = Array::new();
                body_array.push(&body_uint8_array);
                let js_value: &JsValue = body_array.as_ref();
                Ok(js_value.to_owned())
            }
            #[cfg(feature = "multipart")]
            Inner::Multipart(form) => {
                let form_data = form.to_form_data()?;
                let js_value: &JsValue = form_data.as_ref();
                Ok(js_value.to_owned())
            }
        }
    }

    #[inline]
    #[cfg(feature = "multipart")]
    pub(crate) fn from_form(f: Form) -> Body {
        Self {
            inner: Inner::Multipart(f),
        }
    }

    pub(crate) fn is_empty(&self) -> bool {
        match &self.inner {
            Inner::Bytes(bytes) => bytes.is_empty(),
            #[cfg(feature = "multipart")]
            Inner::Multipart(form) => form.is_empty(),
        }
    }

    pub(crate) fn try_clone(&self) -> Option<Body> {
        match &self.inner {
            Inner::Bytes(bytes) => Some(Self {
                inner: Inner::Bytes(bytes.clone()),
            }),
            #[cfg(feature = "multipart")]
            Inner::Multipart(_) => None,
        }
    }
}

impl From<Bytes> for Body {
    #[inline]
    fn from(bytes: Bytes) -> Body {
        Body {
            inner: Inner::Bytes(bytes),
        }
    }
}

impl From<Vec<u8>> for Body {
    #[inline]
    fn from(vec: Vec<u8>) -> Body {
        Body {
            inner: Inner::Bytes(vec.into()),
        }
    }
}

impl From<&'static [u8]> for Body {
    #[inline]
    fn from(s: &'static [u8]) -> Body {
        Body {
            inner: Inner::Bytes(Bytes::from_static(s)),
        }
    }
}

impl From<String> for Body {
    #[inline]
    fn from(s: String) -> Body {
        Body {
            inner: Inner::Bytes(s.into()),
        }
    }
}

impl From<&'static str> for Body {
    #[inline]
    fn from(s: &'static str) -> Body {
        s.as_bytes().into()
    }
}

impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Body").finish()
    }
}
<|endoftext|>