<commit_before>//! This code might still contain bugs. In either case it's very inefficient because we
//! want to avoid reading invalid memory at all costs. Note that the implementation from
//! 1024cores does not handle ABA!

use std::{ptr, mem};
use std::num::{UnsignedInt, Int};
use std::sync::atomic::{AtomicUsize, AtomicBool};
use std::sync::atomic::Ordering::{SeqCst};
use std::sync::{Mutex, Condvar};
use std::rt::heap::{allocate, deallocate};
use std::cell::{Cell};

use select::{_Selectable, WaitQueue, Payload};
use alloc::{oom};
use {Error, Sendable};

#[cfg(target_pointer_width = "64")]
type HalfPointer = u32;
#[cfg(target_pointer_width = "32")]
type HalfPointer = u16;

const HALF_POINTER_BITS: usize = ::std::usize::BITS / 2;

fn decompose_pointer(val: usize) -> (HalfPointer, HalfPointer) {
    let lower = val as HalfPointer;
    let higher = (val >> HALF_POINTER_BITS) as HalfPointer;
    (lower, higher)
}

fn compose_pointer(lower: HalfPointer, higher: HalfPointer) -> usize {
    (lower as usize) | ((higher as usize) << HALF_POINTER_BITS)
}

pub struct Packet<'a, T: Sendable+'a> {
    // The id of this channel. The address of the `arc::Inner` that contains this channel.
    id: Cell<usize>,

    // The buffer we store the massages in.
    buf: *mut T,
    // One less than the capacity of the channel. Note that the capacity is a power of
    // two.
    cap_mask: HalfPointer,

    // read_start and next_write HalfPointer variables encoded in one usize. read_start is
    // the id before which all elements in the buffer have been read. next_write is the
    // next place that's free for writing.
    //
    // Note that this implies that, next_write - read_start <= capacity at all times.
    read_start_next_write: AtomicUsize,
    // write_end and next_read HalfPointer variables encoded in one usize. write_end is
    // the id before which all elements in the buffer have been written. next_read is the
    // next place that's free for reading.
    //
    // Note that this implies that, ignoring overflow, next_read <= write_end.
    //
    // See the docs below for why we have to store these four variables this way.
    write_end_next_read:   AtomicUsize,

    // Number of senders that are currently sleeping.
    sleeping_senders: AtomicUsize,
    // Condvar the senders are sleeping on.
    send_condvar:     Condvar,

    // Number of receivers that are currently sleeping.
    sleeping_receivers: AtomicUsize,
    // Condvar the senders are sleeping on.
    recv_condvar:       Condvar,

    // Mutex that protects the two atomic variables above and the one below.
    sleep_mutex: Mutex<()>,
    // Number of peers that are awake.
    peers_awake: AtomicUsize,

    // Is any one selecting on this channel?
    wait_queue_used: AtomicBool,
    wait_queue: Mutex<WaitQueue<'a>>,
}

impl<'a, T: Sendable+'a> Packet<'a, T> {
    pub fn new(buf_size: usize) -> Packet<'a, T> {
        if buf_size > 1 << (HALF_POINTER_BITS - 1) {
            panic!("capacity overflow");
        }
        let cap = buf_size.next_power_of_two();
        let size = cap.checked_mul(mem::size_of::<T>()).unwrap_or(!0);
        if size > !0 >> 1 {
            panic!("capacity overflow");
        }
        let buf = if mem::size_of::<T>() == 0 {
            1 as *mut u8
        } else {
            unsafe { allocate(size, mem::min_align_of::<T>()) }
        };
        if buf.is_null() {
            oom();
        }
        Packet {
            id: Cell::new(0),

            buf: buf as *mut T,
            cap_mask: (cap - 1) as HalfPointer,

            read_start_next_write: AtomicUsize::new(0),
            write_end_next_read:   AtomicUsize::new(0),

            sleeping_senders: AtomicUsize::new(0),
            send_condvar:     Condvar::new(),

            sleeping_receivers: AtomicUsize::new(0),
            recv_condvar:       Condvar::new(),

            sleep_mutex: Mutex::new(()),
            peers_awake: AtomicUsize::new(1),

            wait_queue_used: AtomicBool::new(false),
            wait_queue: Mutex::new(WaitQueue::new()),
        }
    }

    /// Call this function before any other.
    pub fn set_id(&self, id: usize) {
        self.id.set(id);
        self.wait_queue.lock().unwrap().set_id(id);
    }

    /// Call this function when the channel is cloned.
    pub fn add_peer(&self) {
        self.peers_awake.fetch_add(1, SeqCst);
    }

    /// Call this function when a peer is dropped.
    pub fn remove_peer(&self) {
        if self.peers_awake.fetch_sub(1, SeqCst) == 1 {
            let _guard = self.sleep_mutex.lock().unwrap();
            if self.sleeping_receivers.load(SeqCst) > 0 {
                self.recv_condvar.notify_one();
            } else {
                self.send_condvar.notify_one();
            }
            self.notify_wait_queue();
        }
    }

    fn notify_wait_queue(&self) {
        if self.wait_queue_used.load(SeqCst) {
            let mut wait_queue = self.wait_queue.lock().unwrap();
            if wait_queue.notify() == 0 {
                self.wait_queue_used.store(false, SeqCst);
            }
        }
    }

    /// Get a position to write to if the queue isn't full
    fn get_write_pos(&self) -> Option<HalfPointer> {
        // See the get_read_pos docs for details.
        loop {
            let rsnw = self.read_start_next_write.load(SeqCst);
            let (read_start, next_write) = decompose_pointer(rsnw);
            if next_write - read_start == self.cap_mask + 1 {
                return None;
            }
            let rsnw_new = compose_pointer(read_start, next_write + 1);
            if self.read_start_next_write.compare_and_swap(rsnw, rsnw_new,
                                                           SeqCst) == rsnw {
                return Some(next_write);
            }
        }
    }

    /// `pos` is the position we've written to
    fn set_write_end(&self, pos: HalfPointer) {
        // See the get_read_pos docs for details.
        loop {
            let wenr = self.write_end_next_read.load(SeqCst);
            let (write_end, next_read) = decompose_pointer(wenr);
            if write_end != pos {
                continue;
            }
            let wenr_new = compose_pointer(pos + 1, next_read);
            if self.write_end_next_read.compare_and_swap(wenr, wenr_new,
                                                         SeqCst) == wenr {
                return;
            }
        }
    }

    fn set_mem(&self, pos: HalfPointer, val: T) {
        unsafe {
            ptr::write(self.buf.offset((pos & self.cap_mask) as isize), val);
        }
    }

    pub fn send_async(&self, val: T, have_lock: bool) -> Result<(), (T, Error)> {
        let write_pos = match self.get_write_pos() {
            Some(w) => w,
            _ => return Err((val, Error::Full)),
        };
        self.set_mem(write_pos, val);
        self.set_write_end(write_pos);

        if self.sleeping_receivers.load(SeqCst) > 0 {
            if have_lock {
                self.recv_condvar.notify_one();
            } else {
                let _guard = self.sleep_mutex.lock().unwrap();
                self.recv_condvar.notify_one();
            }
        }

        self.notify_wait_queue();

        Ok(())
    }

    pub fn send_sync(&self, mut val: T) -> Result<(), (T, Error)> {
        val = match self.send_async(val, false) {
            Err(v) => v.0,
            _ => return Ok(()),
        };

        let mut rv = Ok(());
        let mut guard = self.sleep_mutex.lock().unwrap();
        self.sleeping_senders.fetch_add(1, SeqCst);
        loop {
            val = match self.send_async(val, true) {
                Err(v) => v.0,
                _ => break,
            };
            // It is possible that all peers sleep at the same time, however, it can be
            // shown that, as long as not all of them sleep sending and not all of them
            // sleeping receiving, one of them will wake up again because the condition
            // variable has already been notified.
            if self.peers_awake.fetch_sub(1, SeqCst) == 1 &&
                    self.sleeping_receivers.load(SeqCst) == 0 {
                self.peers_awake.fetch_add(1, SeqCst);
                rv = Err((val, Error::Deadlock));
                break;
            } else {
                guard = self.send_condvar.wait(guard).unwrap();
                self.peers_awake.fetch_add(1, SeqCst);
            }
        }
        self.sleeping_senders.fetch_sub(1, SeqCst);

        rv
    }

    /// Get a position to read from if the queue isn't empty
    fn get_read_pos(&self) -> Option<HalfPointer> {
        // The write_end_next_read field contains two variables: write_end and next_read.
        //
        // next_read is the next position we can read from, write_end is the first
        // position we can not read from because it has not necessarily been written yet.
        //
        // We have to store both of them in the same variable because of ABA. Consider the
        // following events:
        //
        // - This thread reads next_read == 0 and write_end == 1 and therefore there is no
        // early return in the `if` below.
        // - This thread gets suspended right after the `if`.
        // - Other threads continuous read from and write to the channel until both
        // write_end and next_read overflow.
        // - next_read == 0 and write_end == 0 holds now.
        // - This thread wakes up again.
        // - If we store next_read in its own variable, then the CAS can only test
        // next_read. Since next_read is 0, the CAS succeeds and we arrive at next_read ==
        // 1 and write_end == 0.
        // - The function that called this function reads from position 0 even though
        // nothing has been written to that position yet.
        //
        // Therefore we store next_read and write_end in the same variable. The overflow
        // above can still happen but if write_end gets smaller (or changes in any way),
        // the CAS will fail and we can never read uninitialized memory.
        //
        // It's highly unlikely for this ABA to happen, and on 64bit one might even
        // consider it impossible. After a more careful analysis, a future implementation
        // might change the implementation.
        loop {
            let wenr = self.write_end_next_read.load(SeqCst);
            let (write_end, next_read) = decompose_pointer(wenr);
            if write_end == next_read {
                return None;
            }
            let wenr_new = compose_pointer(write_end, next_read + 1);
            if self.write_end_next_read.compare_and_swap(wenr, wenr_new,
                                                         SeqCst) == wenr {
                return Some(next_read);
            }
        }
    }

    /// `pos` is the position we've read from
    fn set_read_start(&self, pos: HalfPointer) {
        loop {
            let rsnw = self.read_start_next_write.load(SeqCst);
            let (read_start, next_write) = decompose_pointer(rsnw);
            if read_start != pos {
                continue;
            }
            let rsnw_new = compose_pointer(pos + 1, next_write);
            if self.read_start_next_write.compare_and_swap(rsnw, rsnw_new,
                                                           SeqCst) == rsnw {
                return;
            }
        }
    }

    fn get_mem(&self, pos: HalfPointer) -> T {
        unsafe {
            ptr::read(self.buf.offset((pos & self.cap_mask) as isize))
        }
    }

    pub fn recv_async(&self, have_lock: bool) -> Result<T, Error> {
        let read_pos = match self.get_read_pos() {
            Some(r) => r,
            _ => return Err(Error::Empty),
        };
        let val = self.get_mem(read_pos);
        self.set_read_start(read_pos);

        if self.sleeping_senders.load(SeqCst) > 0 {
            if have_lock {
                self.send_condvar.notify_one();
            } else {
                let _guard = self.sleep_mutex.lock().unwrap();
                self.send_condvar.notify_one();
            }
        }

        Ok(val)
    }

    pub fn recv_sync(&self) -> Result<T, Error> {
        let mut rv = self.recv_async(false);
        if rv.is_ok() {
            return rv;
        }

        let mut guard = self.sleep_mutex.lock().unwrap();
        self.sleeping_receivers.fetch_add(1, SeqCst);
        loop {
            rv = self.recv_async(true);
            if rv.is_ok() {
                break;
            }
            // See the docs in send_sync.
            if self.peers_awake.fetch_sub(1, SeqCst) == 1 &&
                    self.sleeping_senders.load(SeqCst) == 0 {
                self.peers_awake.fetch_add(1, SeqCst);
                rv = Err(Error::Deadlock);
                break;
            } else {
                guard = self.recv_condvar.wait(guard).unwrap();
                self.peers_awake.fetch_add(1, SeqCst);
            }
        }
        self.sleeping_receivers.fetch_sub(1, SeqCst);

        rv
    }
}

unsafe impl<'a, T: Sendable+'a> Send for Packet<'a, T> { }
unsafe impl<'a, T: Sendable+'a> Sync for Packet<'a, T> { }

#[unsafe_destructor]
impl<'a, T: Sendable+'a> Drop for Packet<'a, T> {
    fn drop(&mut self) {
        let wenr = self.write_end_next_read.load(SeqCst);
        let (write_end, read_start) = decompose_pointer(wenr);

        unsafe {
            for i in (0..write_end-read_start) {
                self.get_mem(read_start + i);
            }

            if mem::size_of::<T>() > 0 {
                deallocate(self.buf as *mut u8,
                           (self.cap_mask as usize + 1) * mem::size_of::<T>(),
                           mem::min_align_of::<T>());
            }
        }
    }
}

unsafe impl<'a, T: Sendable+'a> _Selectable<'a> for Packet<'a, T> {
    fn ready(&self) -> bool {
        if self.peers_awake.load(SeqCst) == 0 {
            return true;
        }
        let wenr = self.write_end_next_read.load(SeqCst);
        let (write_end, next_read) = decompose_pointer(wenr);
        write_end != next_read
    }

    fn register(&self, load: Payload<'a>) {
        let mut wait_queue = self.wait_queue.lock().unwrap();
        if wait_queue.add(load) > 0 {
            self.wait_queue_used.store(true, SeqCst);
        }
    }

    fn unregister(&self, id: usize) {
        let mut wait_queue = self.wait_queue.lock().unwrap();
        if wait_queue.remove(id) == 0 {
            self.wait_queue_used.store(false, SeqCst);
        }
    }
}
<commit_msg>update rust<commit_after>//! This code might still contain bugs. In either case it's very inefficient because we
//! want to avoid reading invalid memory at all costs. Note that the implementation from
//! 1024cores does not handle ABA!

use std::{ptr, mem};
use std::num::{UnsignedInt, Int};
use std::sync::atomic::{AtomicUsize, AtomicBool};
use std::sync::atomic::Ordering::{SeqCst};
use std::sync::{Mutex, Condvar};
use std::rt::heap::{allocate, deallocate};
use std::cell::{Cell};

use select::{_Selectable, WaitQueue, Payload};
use alloc::{oom};
use {Error, Sendable};

#[cfg(target_pointer_width = "64")]
type HalfPointer = u32;
#[cfg(target_pointer_width = "32")]
type HalfPointer = u16;

const HALF_POINTER_BITS: usize = ::std::usize::BITS as usize / 2;

fn decompose_pointer(val: usize) -> (HalfPointer, HalfPointer) {
    let lower = val as HalfPointer;
    let higher = (val >> HALF_POINTER_BITS) as HalfPointer;
    (lower, higher)
}

fn compose_pointer(lower: HalfPointer, higher: HalfPointer) -> usize {
    (lower as usize) | ((higher as usize) << HALF_POINTER_BITS)
}

pub struct Packet<'a, T: Sendable+'a> {
    // The id of this channel. The address of the `arc::Inner` that contains this channel.
    id: Cell<usize>,

    // The buffer we store the massages in.
    buf: *mut T,
    // One less than the capacity of the channel. Note that the capacity is a power of
    // two.
    cap_mask: HalfPointer,

    // read_start and next_write HalfPointer variables encoded in one usize. read_start is
    // the id before which all elements in the buffer have been read. next_write is the
    // next place that's free for writing.
    //
    // Note that this implies that, next_write - read_start <= capacity at all times.
    read_start_next_write: AtomicUsize,
    // write_end and next_read HalfPointer variables encoded in one usize. write_end is
    // the id before which all elements in the buffer have been written. next_read is the
    // next place that's free for reading.
    //
    // Note that this implies that, ignoring overflow, next_read <= write_end.
    //
    // See the docs below for why we have to store these four variables this way.
    write_end_next_read:   AtomicUsize,

    // Number of senders that are currently sleeping.
    sleeping_senders: AtomicUsize,
    // Condvar the senders are sleeping on.
    send_condvar:     Condvar,

    // Number of receivers that are currently sleeping.
    sleeping_receivers: AtomicUsize,
    // Condvar the senders are sleeping on.
    recv_condvar:       Condvar,

    // Mutex that protects the two atomic variables above and the one below.
    sleep_mutex: Mutex<()>,
    // Number of peers that are awake.
    peers_awake: AtomicUsize,

    // Is any one selecting on this channel?
    wait_queue_used: AtomicBool,
    wait_queue: Mutex<WaitQueue<'a>>,
}

impl<'a, T: Sendable+'a> Packet<'a, T> {
    pub fn new(buf_size: usize) -> Packet<'a, T> {
        if buf_size > 1 << (HALF_POINTER_BITS - 1) {
            panic!("capacity overflow");
        }
        let cap = buf_size.next_power_of_two();
        let size = cap.checked_mul(mem::size_of::<T>()).unwrap_or(!0);
        if size > !0 >> 1 {
            panic!("capacity overflow");
        }
        let buf = if mem::size_of::<T>() == 0 {
            1 as *mut u8
        } else {
            unsafe { allocate(size, mem::min_align_of::<T>()) }
        };
        if buf.is_null() {
            oom();
        }
        Packet {
            id: Cell::new(0),

            buf: buf as *mut T,
            cap_mask: (cap - 1) as HalfPointer,

            read_start_next_write: AtomicUsize::new(0),
            write_end_next_read:   AtomicUsize::new(0),

            sleeping_senders: AtomicUsize::new(0),
            send_condvar:     Condvar::new(),

            sleeping_receivers: AtomicUsize::new(0),
            recv_condvar:       Condvar::new(),

            sleep_mutex: Mutex::new(()),
            peers_awake: AtomicUsize::new(1),

            wait_queue_used: AtomicBool::new(false),
            wait_queue: Mutex::new(WaitQueue::new()),
        }
    }

    /// Call this function before any other.
    pub fn set_id(&self, id: usize) {
        self.id.set(id);
        self.wait_queue.lock().unwrap().set_id(id);
    }

    /// Call this function when the channel is cloned.
    pub fn add_peer(&self) {
        self.peers_awake.fetch_add(1, SeqCst);
    }

    /// Call this function when a peer is dropped.
    pub fn remove_peer(&self) {
        if self.peers_awake.fetch_sub(1, SeqCst) == 1 {
            let _guard = self.sleep_mutex.lock().unwrap();
            if self.sleeping_receivers.load(SeqCst) > 0 {
                self.recv_condvar.notify_one();
            } else {
                self.send_condvar.notify_one();
            }
            self.notify_wait_queue();
        }
    }

    fn notify_wait_queue(&self) {
        if self.wait_queue_used.load(SeqCst) {
            let mut wait_queue = self.wait_queue.lock().unwrap();
            if wait_queue.notify() == 0 {
                self.wait_queue_used.store(false, SeqCst);
            }
        }
    }

    /// Get a position to write to if the queue isn't full
    fn get_write_pos(&self) -> Option<HalfPointer> {
        // See the get_read_pos docs for details.
        loop {
            let rsnw = self.read_start_next_write.load(SeqCst);
            let (read_start, next_write) = decompose_pointer(rsnw);
            if next_write - read_start == self.cap_mask + 1 {
                return None;
            }
            let rsnw_new = compose_pointer(read_start, next_write + 1);
            if self.read_start_next_write.compare_and_swap(rsnw, rsnw_new,
                                                           SeqCst) == rsnw {
                return Some(next_write);
            }
        }
    }

    /// `pos` is the position we've written to
    fn set_write_end(&self, pos: HalfPointer) {
        // See the get_read_pos docs for details.
        loop {
            let wenr = self.write_end_next_read.load(SeqCst);
            let (write_end, next_read) = decompose_pointer(wenr);
            if write_end != pos {
                continue;
            }
            let wenr_new = compose_pointer(pos + 1, next_read);
            if self.write_end_next_read.compare_and_swap(wenr, wenr_new,
                                                         SeqCst) == wenr {
                return;
            }
        }
    }

    fn set_mem(&self, pos: HalfPointer, val: T) {
        unsafe {
            ptr::write(self.buf.offset((pos & self.cap_mask) as isize), val);
        }
    }

    pub fn send_async(&self, val: T, have_lock: bool) -> Result<(), (T, Error)> {
        let write_pos = match self.get_write_pos() {
            Some(w) => w,
            _ => return Err((val, Error::Full)),
        };
        self.set_mem(write_pos, val);
        self.set_write_end(write_pos);

        if self.sleeping_receivers.load(SeqCst) > 0 {
            if have_lock {
                self.recv_condvar.notify_one();
            } else {
                let _guard = self.sleep_mutex.lock().unwrap();
                self.recv_condvar.notify_one();
            }
        }

        self.notify_wait_queue();

        Ok(())
    }

    pub fn send_sync(&self, mut val: T) -> Result<(), (T, Error)> {
        val = match self.send_async(val, false) {
            Err(v) => v.0,
            _ => return Ok(()),
        };

        let mut rv = Ok(());
        let mut guard = self.sleep_mutex.lock().unwrap();
        self.sleeping_senders.fetch_add(1, SeqCst);
        loop {
            val = match self.send_async(val, true) {
                Err(v) => v.0,
                _ => break,
            };
            // It is possible that all peers sleep at the same time, however, it can be
            // shown that, as long as not all of them sleep sending and not all of them
            // sleeping receiving, one of them will wake up again because the condition
            // variable has already been notified.
            if self.peers_awake.fetch_sub(1, SeqCst) == 1 &&
                    self.sleeping_receivers.load(SeqCst) == 0 {
                self.peers_awake.fetch_add(1, SeqCst);
                rv = Err((val, Error::Deadlock));
                break;
            } else {
                guard = self.send_condvar.wait(guard).unwrap();
                self.peers_awake.fetch_add(1, SeqCst);
            }
        }
        self.sleeping_senders.fetch_sub(1, SeqCst);

        rv
    }

    /// Get a position to read from if the queue isn't empty
    fn get_read_pos(&self) -> Option<HalfPointer> {
        // The write_end_next_read field contains two variables: write_end and next_read.
        //
        // next_read is the next position we can read from, write_end is the first
        // position we can not read from because it has not necessarily been written yet.
        //
        // We have to store both of them in the same variable because of ABA. Consider the
        // following events:
        //
        // - This thread reads next_read == 0 and write_end == 1 and therefore there is no
        // early return in the `if` below.
        // - This thread gets suspended right after the `if`.
        // - Other threads continuous read from and write to the channel until both
        // write_end and next_read overflow.
        // - next_read == 0 and write_end == 0 holds now.
        // - This thread wakes up again.
        // - If we store next_read in its own variable, then the CAS can only test
        // next_read. Since next_read is 0, the CAS succeeds and we arrive at next_read ==
        // 1 and write_end == 0.
        // - The function that called this function reads from position 0 even though
        // nothing has been written to that position yet.
        //
        // Therefore we store next_read and write_end in the same variable. The overflow
        // above can still happen but if write_end gets smaller (or changes in any way),
        // the CAS will fail and we can never read uninitialized memory.
        //
        // It's highly unlikely for this ABA to happen, and on 64bit one might even
        // consider it impossible. After a more careful analysis, a future implementation
        // might change the implementation.
        loop {
            let wenr = self.write_end_next_read.load(SeqCst);
            let (write_end, next_read) = decompose_pointer(wenr);
            if write_end == next_read {
                return None;
            }
            let wenr_new = compose_pointer(write_end, next_read + 1);
            if self.write_end_next_read.compare_and_swap(wenr, wenr_new,
                                                         SeqCst) == wenr {
                return Some(next_read);
            }
        }
    }

    /// `pos` is the position we've read from
    fn set_read_start(&self, pos: HalfPointer) {
        loop {
            let rsnw = self.read_start_next_write.load(SeqCst);
            let (read_start, next_write) = decompose_pointer(rsnw);
            if read_start != pos {
                continue;
            }
            let rsnw_new = compose_pointer(pos + 1, next_write);
            if self.read_start_next_write.compare_and_swap(rsnw, rsnw_new,
                                                           SeqCst) == rsnw {
                return;
            }
        }
    }

    fn get_mem(&self, pos: HalfPointer) -> T {
        unsafe {
            ptr::read(self.buf.offset((pos & self.cap_mask) as isize))
        }
    }

    pub fn recv_async(&self, have_lock: bool) -> Result<T, Error> {
        let read_pos = match self.get_read_pos() {
            Some(r) => r,
            _ => return Err(Error::Empty),
        };
        let val = self.get_mem(read_pos);
        self.set_read_start(read_pos);

        if self.sleeping_senders.load(SeqCst) > 0 {
            if have_lock {
                self.send_condvar.notify_one();
            } else {
                let _guard = self.sleep_mutex.lock().unwrap();
                self.send_condvar.notify_one();
            }
        }

        Ok(val)
    }

    pub fn recv_sync(&self) -> Result<T, Error> {
        let mut rv = self.recv_async(false);
        if rv.is_ok() {
            return rv;
        }

        let mut guard = self.sleep_mutex.lock().unwrap();
        self.sleeping_receivers.fetch_add(1, SeqCst);
        loop {
            rv = self.recv_async(true);
            if rv.is_ok() {
                break;
            }
            // See the docs in send_sync.
            if self.peers_awake.fetch_sub(1, SeqCst) == 1 &&
                    self.sleeping_senders.load(SeqCst) == 0 {
                self.peers_awake.fetch_add(1, SeqCst);
                rv = Err(Error::Deadlock);
                break;
            } else {
                guard = self.recv_condvar.wait(guard).unwrap();
                self.peers_awake.fetch_add(1, SeqCst);
            }
        }
        self.sleeping_receivers.fetch_sub(1, SeqCst);

        rv
    }
}

unsafe impl<'a, T: Sendable+'a> Send for Packet<'a, T> { }
unsafe impl<'a, T: Sendable+'a> Sync for Packet<'a, T> { }

#[unsafe_destructor]
impl<'a, T: Sendable+'a> Drop for Packet<'a, T> {
    fn drop(&mut self) {
        let wenr = self.write_end_next_read.load(SeqCst);
        let (write_end, read_start) = decompose_pointer(wenr);

        unsafe {
            for i in (0..write_end-read_start) {
                self.get_mem(read_start + i);
            }

            if mem::size_of::<T>() > 0 {
                deallocate(self.buf as *mut u8,
                           (self.cap_mask as usize + 1) * mem::size_of::<T>(),
                           mem::min_align_of::<T>());
            }
        }
    }
}

unsafe impl<'a, T: Sendable+'a> _Selectable<'a> for Packet<'a, T> {
    fn ready(&self) -> bool {
        if self.peers_awake.load(SeqCst) == 0 {
            return true;
        }
        let wenr = self.write_end_next_read.load(SeqCst);
        let (write_end, next_read) = decompose_pointer(wenr);
        write_end != next_read
    }

    fn register(&self, load: Payload<'a>) {
        let mut wait_queue = self.wait_queue.lock().unwrap();
        if wait_queue.add(load) > 0 {
            self.wait_queue_used.store(true, SeqCst);
        }
    }

    fn unregister(&self, id: usize) {
        let mut wait_queue = self.wait_queue.lock().unwrap();
        if wait_queue.remove(id) == 0 {
            self.wait_queue_used.store(false, SeqCst);
        }
    }
}
<|endoftext|>


<commit_before>use std::mem::swap;

static TRIANGLE: &[&[i32]] = include!("p067_triangle.rs");

fn main() {
    let mut row = TRIANGLE.len() - 1;
    let mut values = TRIANGLE[row].to_vec();
    let mut next = Vec::with_capacity(TRIANGLE[row].len() - 1);

    while row > 0 {
        row -= 1;

        next.extend_from_slice(TRIANGLE[row]);

        for (i, parent) in next.iter_mut().enumerate() {
            if values[i] >= values[i + 1] {
                *parent += values[i];
            } else {
                *parent += values[i + 1];
            }
        }

        swap(&mut values, &mut next);
        next.clear();
    }

    println!("{}", values[0]);
}
<commit_msg>Slightly more elegant<commit_after>use std::cmp::max;
use std::mem::swap;

static TRIANGLE: &[&[i32]] = include!("p067_triangle.rs");

fn main() {
    let mut row = TRIANGLE.len() - 1;
    let mut values = TRIANGLE[row].to_vec();
    let mut next = Vec::with_capacity(TRIANGLE[row].len() - 1);

    while row > 0 {
        row -= 1;

        next.extend_from_slice(TRIANGLE[row]);

        for (i, parent) in next.iter_mut().enumerate() {
            *parent += max(values[i], values[i + 1]);
        }

        swap(&mut values, &mut next);
        next.clear();
    }

    println!("{}", values[0]);
}
<|endoftext|>


<commit_before>//! A module for OFS abstractions

use alloc::arc::Arc;

use core::mem;

use concurrency::StaticSemaphore;
use io::block::{BlockDevice, BlockDataBuffer};
use io::ide::{IDE, IDEBuf, SECTOR_SIZE};
use super::hw::*;

/// A handle on the file system for all needed operations.
pub struct OFS<B: BlockDevice> {
    device: Arc<B>,

    // metadata
    meta: Metadata,

    // lock
    lock: StaticSemaphore,
}

/// A handle on the file for all needed operations.
pub struct File<B: BlockDevice> {
    inode_num: usize,
    inode: Inode,
    offset: usize,
    device: Arc<B>,
}

impl<B: BlockDevice> OFS<B> {
    /// Create a new handle on the device using the device
    pub fn new(mut device: B) -> OFS<B> {
        let mut buf = IDEBuf::new(SECTOR_SIZE);

        device.read_fully(0, &mut buf);

        // get the metadata sector
        let meta = unsafe { buf.get_ref::<Metadata>(0) };

        // check the magic
        if &*meta.get_magic_str() != "OFS\x00" {
            panic!("This is not an OFS volume!");
        }

        OFS {
            device: device,
            meta: meta.clone(),
            lock: StaticSemaphore::new(1),
        }
    }

    /// Open the file with the given inode number and
    /// return a handle to it.
    pub fn open(&mut self, inode: usize) -> File<B> {
        File {
            inode_num: inode,
            inode: self.get_inode(inode),
        }
    }

    /// Get the sector number of the first inode
    fn get_inode_start_sector(&self) -> usize {
        let inode_map_bytes = self.meta.num_inode / 8;
        let inode_map_sectors = if inode_map_bytes % SECTOR_SIZE > 0 {
            inode_map_bytes / SECTOR_SIZE + 1
        } else {
            inode_map_bytes / SECTOR_SIZE
        };

        let dnode_map_bytes = self.meta.num_dnode / 8;
        let dnode_map_sectors = if dnode_map_bytes % SECTOR_SIZE > 0 {
            dnode_map_bytes / SECTOR_SIZE + 1
        } else {
            dnode_map_bytes / SECTOR_SIZE
        };

        1 + inode_map_sectors + dnode_map_sectors
    }

    /// Get the sector number of the first dnode
    fn get_dnode_start_sector(&self) -> usize {
        self.get_inode_start_sector() + self.meta.num_inode
    }

    /// Get the `i`th inode
    pub fn get_inode(&mut self, i: usize) -> Inode {
        let inode_sector = self.get_inode_start_sector() + i/Inode::inodes_per_sector();
        let inode_mod = i % Inode::inodes_per_sector();

        // read from disk
        let inode_size = mem::size_of::<Inode>();
        let mut buf = IDEBuf::new(inode_size);
        self.device.read_fully(inode_sector*SECTOR_SIZE+inode_mod*inode_size, &mut buf);

        unsafe {
            buf.get_ref::<Inode>(inode_mod).clone()
        }
    }

    /// Get the `d`th dnode
    fn get_dnode(&mut self, d: usize) -> Dnode {
        let dnode_sector = self.get_dnode_start_sector() + d/Dnode::dnodes_per_sector();
        let dnode_mod = d % Dnode::dnodes_per_sector();

        // read from disk
        let dnode_size = mem::size_of::<Dnode>();
        let mut buf = IDEBuf::new(dnode_size);
        self.device.read_fully(dnode_sector*SECTOR_SIZE+dnode_mod*dnode_size, &mut buf);

        unsafe {
            buf.get_ref::<Dnode>(dnode_mod).clone()
        }
    }
}

impl<B: BlockDevice> File<B> {
    // TODO: fix this

    pub fn read(&mut self) -> usize {

    }
}
<commit_msg>Minor changes<commit_after>//! A module for OFS abstractions

use alloc::arc::Arc;

use core::mem;

use sync::StaticSemaphore;
use io::block::{BlockDevice, BlockDataBuffer};
use io::ide::{IDE, SECTOR_SIZE};
use super::hw::*;

/// A handle on the file system for all needed operations.
pub struct OFS<B: BlockDevice> {
    device: Arc<B>,

    // metadata
    meta: Metadata,

    // lock
    lock: StaticSemaphore,
}

/// A handle on the file for all needed operations.
pub struct File<B: BlockDevice> {
    inode_num: usize,
    inode: Inode,
    offset: usize,
    device: Arc<B>,
}

impl<B: BlockDevice> OFS<B> {
    /// Create a new handle on the device using the device
    pub fn new(mut device: B) -> OFS<B> {
        let mut buf = BlockDataBuffer::new(SECTOR_SIZE);

        device.read_fully(0, &mut buf);

        // get the metadata sector
        let meta = unsafe { buf.get_ref::<Metadata>(0) };

        // check the magic
        if &*meta.get_magic_str() != "OFS\x00" {
            panic!("This is not an OFS volume!");
        }

        OFS {
            device: device,
            meta: meta.clone(),
            lock: StaticSemaphore::new(1),
        }
    }

    /// Open the file with the given inode number and
    /// return a handle to it.
    pub fn open(&mut self, inode: usize) -> File<B> {
        File {
            inode_num: inode,
            inode: self.get_inode(inode),
        }
    }

    /// Get the sector number of the first inode
    fn get_inode_start_sector(&self) -> usize {
        let inode_map_bytes = self.meta.num_inode / 8;
        let inode_map_sectors = if inode_map_bytes % SECTOR_SIZE > 0 {
            inode_map_bytes / SECTOR_SIZE + 1
        } else {
            inode_map_bytes / SECTOR_SIZE
        };

        let dnode_map_bytes = self.meta.num_dnode / 8;
        let dnode_map_sectors = if dnode_map_bytes % SECTOR_SIZE > 0 {
            dnode_map_bytes / SECTOR_SIZE + 1
        } else {
            dnode_map_bytes / SECTOR_SIZE
        };

        1 + inode_map_sectors + dnode_map_sectors
    }

    /// Get the sector number of the first dnode
    fn get_dnode_start_sector(&self) -> usize {
        self.get_inode_start_sector() + self.meta.num_inode
    }

    /// Get the `i`th inode
    pub fn get_inode(&mut self, i: usize) -> Inode {
        let inode_sector = self.get_inode_start_sector() + i/Inode::inodes_per_sector();
        let inode_mod = i % Inode::inodes_per_sector();

        // read from disk
        let inode_size = mem::size_of::<Inode>();
        let mut buf = BlockDataBuffer::new(inode_size);
        self.device.read_fully(inode_sector*SECTOR_SIZE+inode_mod*inode_size, &mut buf);

        unsafe {
            buf.get_ref::<Inode>(inode_mod).clone()
        }
    }

    /// Get the `d`th dnode
    fn get_dnode(&mut self, d: usize) -> Dnode {
        let dnode_sector = self.get_dnode_start_sector() + d/Dnode::dnodes_per_sector();
        let dnode_mod = d % Dnode::dnodes_per_sector();

        // read from disk
        let dnode_size = mem::size_of::<Dnode>();
        let mut buf = BlockDataBuffer::new(dnode_size);
        self.device.read_fully(dnode_sector*SECTOR_SIZE+dnode_mod*dnode_size, &mut buf);

        unsafe {
            buf.get_ref::<Dnode>(dnode_mod).clone()
        }
    }
}

impl<B: BlockDevice> File<B> {
    // TODO: fix this

    pub fn read(&mut self) -> usize {

    }
}
<|endoftext|>


<commit_before>extern crate clock_ticks;
extern crate rand;
extern crate sdl2;
extern crate sdl2_gfx;
extern crate sdl2_image;
extern crate sdl2_mixer;
extern crate sdl2_ttf;

use pongo::ui::{Drawable, Ui};

use rand::distributions::{IndependentSample, Range};

use sdl2::{AudioSubsystem, Sdl};
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::Color;
use sdl2::rect::Rect;
use sdl2::render::{Renderer, Texture};

use sdl2_gfx::primitives::DrawRenderer;
use sdl2_image::{LoadTexture, INIT_PNG};
use sdl2_mixer::{AUDIO_S16LSB, DEFAULT_FREQUENCY, Music};
use sdl2_ttf::{Font, Hinting, Sdl2TtfContext};

use std::cell::RefCell;
use std::f32;
use std::path::Path;
use std::rc::Rc;
use std::thread;
use std::vec::Vec;

use super::Resettable;

pub struct ScoreCard {
    pub color: Color,
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
    pub font: Rc<Font>,
    pub score: i32
}

impl ScoreCard {

    pub fn new(color: Color, x: f32, y: f32, width: f32, height: f32, font: Rc<Font>) -> ScoreCard {
        return ScoreCard {
            color: color,
            x: x,
            y: y,
            width: width,
            height: height,
            font: font,
            score: 0
        };
    }

}

impl Drawable for ScoreCard {

    fn draw(&self, ui: &mut Ui) {
        let formatted_score = format!("{:^3}", self.score);
        let formatted_score_ref: &str = formatted_score.as_ref();
        let surface = self.font.render(formatted_score_ref,
                                           sdl2_ttf::blended(self.color)).unwrap();
        let texture = ui.renderer.create_texture_from_surface(&surface).unwrap();
        let target = Rect::new_unwrap(self.x as i32,
                                      self.y as i32,
                                      self.width as u32,
                                      self.height as u32);
        ui.renderer.copy(&texture, None, Some(target));
    }

}

impl Resettable for ScoreCard {

    fn reset(&mut self) {
        self.score = 0;
    }

}
<commit_msg>fixed up warnings from score_card.rs<commit_after>extern crate clock_ticks;
extern crate rand;
extern crate sdl2;
extern crate sdl2_gfx;
extern crate sdl2_image;
extern crate sdl2_mixer;
extern crate sdl2_ttf;

use pongo::ui::{Drawable, Ui};

use sdl2::pixels::Color;
use sdl2::rect::Rect;

use sdl2_ttf::Font;

use std::rc::Rc;

use super::Resettable;

pub struct ScoreCard {
    pub color: Color,
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
    pub font: Rc<Font>,
    pub score: i32
}

impl ScoreCard {

    pub fn new(color: Color, x: f32, y: f32, width: f32, height: f32, font: Rc<Font>) -> ScoreCard {
        return ScoreCard {
            color: color,
            x: x,
            y: y,
            width: width,
            height: height,
            font: font,
            score: 0
        };
    }

}

impl Drawable for ScoreCard {

    fn draw(&self, ui: &mut Ui) {
        let formatted_score = format!("{:^3}", self.score);
        let formatted_score_ref: &str = formatted_score.as_ref();
        let surface = self.font.render(formatted_score_ref,
                                           sdl2_ttf::blended(self.color)).unwrap();
        let texture = ui.renderer.create_texture_from_surface(&surface).unwrap();
        let target = Rect::new_unwrap(self.x as i32,
                                      self.y as i32,
                                      self.width as u32,
                                      self.height as u32);
        ui.renderer.copy(&texture, None, Some(target));
    }

}

impl Resettable for ScoreCard {

    fn reset(&mut self) {
        self.score = 0;
    }

}
<|endoftext|>


<commit_before>#![allow(dead_code)]
#[macro_use]
extern crate jam;
extern crate cgmath;
extern crate time;

use std::f64::consts::PI;

use jam::font::FontDirectory;
use jam::input::InputState;
use jam::camera::Camera;
use jam::color;
use jam::color::Color;

use jam::HashSet;

use jam::{Vec3, Vec2};

use jam::dimensions::Dimensions;

use jam::render::command::*;
use jam::render::command::Command::*;
use jam::render::command::Blend;
use jam::render::{Seconds};
use jam::render::ShaderPair;
use jam::render::TextureDirectory;
use jam::render::text;
use jam::render::GeometryTesselator;
use jam::render::TextureRegion;
use jam::render::glium::renderer;
use jam::render::down_size_m4;
use jam::render::glium::renderer::Renderer;

use cgmath::Rad;

fn main() {
    let shader_pair = ShaderPair::for_paths("resources/shader/fat.vert", "resources/shader/fat.frag");
    let texture_dir = TextureDirectory::for_path("resources/textures", hashset!["png".into()]);
    let font_dir = FontDirectory::for_path("resources/fonts");

    let starting_dimensions = Dimensions {
        pixels: (800,600),
        scale: 1.0,
    };

    let renderer = Renderer::new(shader_pair, texture_dir, font_dir, starting_dimensions.pixels).expect("a renderer");

    let mut app = App {
        name: "mixalot".into(),
        camera: Camera {
            at: Vec3::new(0.0, 0.0, 0.0),
            pitch: Rad(PI / 4.0_f64),
            viewport: starting_dimensions,
            pixels_per_unit: 16.0 * 1.0,
        },
        zoom: 1.0,
        pixels_per_unit: 16.0,
        n: 0, // frame counter
        renderer: renderer,
    };
    app.run();
}

struct App {
    name : String,
    camera : Camera,
    zoom : f64,
    pixels_per_unit : f64,
    n : u64,
    renderer:Renderer<String>,
}

impl App {
    fn run(&mut self) {
        let mut last_time = time::precise_time_ns();
        'main: loop {
            let (dimensions, input_state) = self.renderer.begin();

            let time = time::precise_time_ns();
            let delta_time = ((time - last_time) as f64) / 1_000_000.0;

            self.update(&input_state, dimensions, delta_time);

            let render_passes = self.render();

            self.renderer.render(render_passes);

            last_time = time;
            if input_state.close {
                break;
            }
        }
    }

    fn units_per_pixel(&self) -> f64 {
        1.0 / self.pixels_per_unit
    }

    fn tesselator(&self) -> GeometryTesselator {
        let upp = self.units_per_pixel();
        let tesselator_scale = Vec3::new(upp, upp, upp);
        GeometryTesselator::new(tesselator_scale)
    }

    fn raster(&self, color:Color, x:f64, z:f64) -> GeometryTesselator {
         let texture_region = TextureRegion {
            u_min: 0,
            u_max: 128,
            v_min: 0,
            v_max: 128,
            texture_size: 1024,
        };

        let texture_region_small = TextureRegion {
            u_min: 16,
            u_max: 32,
            v_min: 16,
            v_max: 32,
            texture_size: 1024,
        };

        let mut t = self.tesselator();
        // t.color = color.float_raw();
        // t.draw_floor_tile(&texture_region, 0, x, 0.0, z, 0.0, false);
        // t.color = color::RED.float_raw();
        // t.draw_wall_tile(&texture_region_small, 0, x, 0.0, z, 0.0, false);
        // t.color = color::GREEN.float_raw();
        // t.draw_floor_centre_anchored(&texture_region_small, 0, x + 2.0, 0.0, z + 2.0, 0.1, false);
        // t.color = color::YELLOW.float_raw();

        // t.draw_floor_centre_anchored_rotated(&texture_region_small, 0, x + 4.0, 0.0, z + 4.0, 0.0, 0.1);

        // t.color = color::RED.float_raw();
        // t.draw_wall_base_anchored(&texture_region_small, 0, x + 3.0, 0.0, z, 0.0, false);
        // t.color = color::YELLOW.float_raw();
        // t.draw_wall_centre_anchored(&texture_region_small, 0, x + 5.0, 1.0, z, 0.0, false);
        t
    }

    fn update(&mut self, input_state:&InputState, dimensions:Dimensions, delta_time: Seconds) {
        self.n += 1;

        self.camera.at = Vec3::new(17.0, 0.0, 17.0);
        // self.camera.at = Vec3::new(8.0, 0.0, 8.0);
        self.camera.pixels_per_unit = self.pixels_per_unit * self.zoom;
        self.camera.viewport = dimensions;
    }

    fn render(&mut self) -> Vec<Pass<String>> {
        use jam::font::FontDescription;

        let font_description = FontDescription { family: "DejaVuSerif".into(), pixel_size: (32 as f32 * self.camera.viewport.scale) as u32 };
        let loaded = self.renderer.load_font(&font_description);
        match loaded {
            Err(e) => println!("font load error -> {:?}", e),
            Ok(_) => (),
        }

        let mut opaque_commands : Vec<Command<String>> = Vec::new();
        let mut translucent_commands : Vec<Command<String>> = Vec::new();
        let mut additive_commands : Vec<Command<String>> = Vec::new();

        // let font = self.renderer.load_font(&font_description);

        // println!("render with delta -> {:?}", delta_time);
        let colors = vec![color::WHITE, color::BLUE, color::RED];

        // let (w, h) = self.camera.viewport.pixels;
        // let line = self.camera.ray_for_mouse_position((w / 2) as i32, (h / 2) as i32);
        // println!("forward line -> {:?}", line);

        let an = self.n / 60;

        let on_second = (self.n % 60) == 0;

        let raster_color = colors[(((an / 16) % 16) % 3) as usize]; // cycles every 16 seconds

        if on_second && an % 5 == 0 { // every fifth second
            let column = (an / 4) % 4;
            let name : String = format!("zone_{}", column);
            println!("delete {}", name);
            let pred : Box<Fn(&String) -> bool> = Box::new(move |key| key.starts_with(&name));
            opaque_commands.push(DeleteMatching { pred: pred });
        }

        // k.starts_with(&prefix)

        let n = (((an % 16) as f64) / 16.0 * 255.0) as u8;

        for i in 0..16 {
            let xo = i % 4;
            let zo = i / 4;
            let name : String = format!("zone_{}_{}", xo, zo);

            if (an % 16) == i && on_second {
                let t = self.raster(raster_color, (xo * 9) as f64, (zo * 9) as f64);
                opaque_commands.push(DrawNew {
                    key: Some(name),
                    vertices: t.tesselator.vertices,
                    uniforms: Uniforms {
                        transform : down_size_m4(self.camera.view_projection().into()),
                        color: color::WHITE,
                    }
                });
            } else if ((an+8) % 16) == i && on_second {
                let t = self.raster(raster_color, (xo * 9) as f64, (zo * 9) as f64);
                opaque_commands.push(Update {
                    key: name,
                    vertices: t.tesselator.vertices,
                });
            } else {
                let rem = (xo + zo) % 3;

                let color = match rem {
                    0 => color::rgba(255,255,255, 128),
                    1 => color::rgba(255,255,255, 50),
                    _ => color::WHITE,
                };
                let command = Draw {
                    key: name,
                     uniforms: Uniforms {
                        transform: down_size_m4(self.camera.view_projection().into()),
                        color: color,
                    }
                };

                match rem {
                    0 => translucent_commands.push(command),
                    1 => additive_commands.push(command),
                    _ => opaque_commands.push(command),
                };
            }
        }

        if let Some((font, layer)) = self.renderer.get_font(&font_description) {
            // println!("ok we got a font to use to draw layer -> {:?}", layer);
            let scale = 1.0 / self.camera.viewport.scale as f64;
            let mut t = GeometryTesselator::new(Vec3::new(1.0, 1.0, 1.0));

             let texture_region = TextureRegion {
                u_min: 0,
                u_max: 128,
                v_min: 0,
                v_max: 128,
                texture_size: 1024,
            };
            t.color = color::WHITE.float_raw();
            t.draw_ui(&texture_region, 0, 20.0, 20.0, 0.0, false, 1.0);

            let at = Vec2::new(0.0, 400.0);
            t.color = color::BLACK.float_raw();
            text::render_text(
                "Why oh why does a silly cow fly, you idiot.\n\nGo die in a pie.\n\nPls.",
                font,
                layer,
                at,
                -1.0, // i assume this is because our coordinate system is hosed ...
                scale,
                &mut t,
                Some(300.0)
            );

            translucent_commands.push(DrawNew {
                key: None,
                vertices: t.tesselator.vertices,
                uniforms: Uniforms {
                    transform : down_size_m4(self.camera.ui_projection().into()),
                    color: color::WHITE,
                }
            });
        }

        vec![Pass {
            blend: Blend::None,
            commands: opaque_commands,
        }, Pass {
            blend: Blend::Alpha,
            commands: translucent_commands,
        }, Pass {
            blend: Blend::Add,
            commands: additive_commands,
        }]
    }
}
<commit_msg>Have done by best with coordinate spaces<commit_after>#![allow(dead_code)]
#[macro_use]
extern crate jam;
extern crate cgmath;
extern crate time;

use std::f64::consts::PI;

use jam::font::FontDirectory;
use jam::input::InputState;
use jam::camera::Camera;
use jam::color;
use jam::color::Color;

use jam::HashSet;

use jam::{Vec3, Vec2};

use jam::dimensions::Dimensions;

use jam::render::command::*;
use jam::render::command::Command::*;
use jam::render::command::Blend;
use jam::render::{Seconds};
use jam::render::ShaderPair;
use jam::render::TextureDirectory;
use jam::render::text;
use jam::render::GeometryTesselator;
use jam::render::TextureRegion;
use jam::render::glium::renderer;
use jam::render::down_size_m4;
use jam::render::glium::renderer::Renderer;

use cgmath::Rad;

fn main() {
    let shader_pair = ShaderPair::for_paths("resources/shader/fat.vert", "resources/shader/fat.frag");
    let texture_dir = TextureDirectory::for_path("resources/textures", hashset!["png".into()]);
    let font_dir = FontDirectory::for_path("resources/fonts");

    let starting_dimensions = Dimensions {
        pixels: (800,600),
        scale: 1.0,
    };

    let renderer = Renderer::new(shader_pair, texture_dir, font_dir, starting_dimensions.pixels).expect("a renderer");

    let mut app = App {
        name: "mixalot".into(),
        camera: Camera {
            at: Vec3::new(0.0, 0.0, 0.0),
            pitch: Rad(PI / 4.0_f64),
            viewport: starting_dimensions,
            pixels_per_unit: 16.0 * 1.0,
        },
        zoom: 1.0,
        pixels_per_unit: 16.0,
        n: 0, // frame counter
        renderer: renderer,
    };
    app.run();
}

struct App {
    name : String,
    camera : Camera,
    zoom : f64,
    pixels_per_unit : f64,
    n : u64,
    renderer:Renderer<String>,
}

impl App {
    fn run(&mut self) {
        let mut last_time = time::precise_time_ns();
        'main: loop {
            let (dimensions, input_state) = self.renderer.begin();

            let time = time::precise_time_ns();
            let delta_time = ((time - last_time) as f64) / 1_000_000.0;

            self.update(&input_state, dimensions, delta_time);

            let render_passes = self.render();

            self.renderer.render(render_passes);

            last_time = time;
            if input_state.close {
                break;
            }
        }
    }

    fn units_per_pixel(&self) -> f64 {
        1.0 / self.pixels_per_unit
    }

    fn tesselator(&self) -> GeometryTesselator {
        let upp = self.units_per_pixel();
        let tesselator_scale = Vec3::new(upp, upp, upp);
        GeometryTesselator::new(tesselator_scale)
    }

    fn raster(&self, color:Color, x:f64, z:f64) -> GeometryTesselator {
         let texture_region = TextureRegion {
            u_min: 0,
            u_max: 128,
            v_min: 0,
            v_max: 128,
            texture_size: 1024,
        };

        let texture_region_small = TextureRegion {
            u_min: 16,
            u_max: 32,
            v_min: 16,
            v_max: 32,
            texture_size: 1024,
        };

        let mut t = self.tesselator();
        t.color = color.float_raw();
        t.draw_floor_tile(&texture_region, 0, x, 0.0, z, 0.0, false);
        t.color = color::RED.float_raw();
        t.draw_wall_tile(&texture_region_small, 0, x, 0.0, z, 0.0, false);
        t.color = color::GREEN.float_raw();
        t.draw_floor_centre_anchored(&texture_region_small, 0, x + 2.0, 0.0, z + 2.0, 0.1, false);
        t.color = color::YELLOW.float_raw();

        t.draw_floor_centre_anchored_rotated(&texture_region_small, 0, x + 4.0, 0.0, z + 4.0, 0.0, 0.1);

        t.color = color::RED.float_raw();
        t.draw_wall_base_anchored(&texture_region_small, 0, x + 3.0, 0.0, z, 0.0, false);
        t.color = color::YELLOW.float_raw();
        t.draw_wall_centre_anchored(&texture_region_small, 0, x + 5.0, 1.0, z, 0.0, false);
        t
    }

    fn update(&mut self, input_state:&InputState, dimensions:Dimensions, delta_time: Seconds) {
        self.n += 1;

        self.camera.at = Vec3::new(17.0, 0.0, 17.0);
        // self.camera.at = Vec3::new(8.0, 0.0, 8.0);
        self.camera.pixels_per_unit = self.pixels_per_unit * self.zoom;
        self.camera.viewport = dimensions;
    }

    fn render(&mut self) -> Vec<Pass<String>> {
        use jam::font::FontDescription;

        let font_description = FontDescription { family: "DejaVuSerif".into(), pixel_size: (32 as f32 * self.camera.viewport.scale) as u32 };
        let loaded = self.renderer.load_font(&font_description);
        match loaded {
            Err(e) => println!("font load error -> {:?}", e),
            Ok(_) => (),
        }

        let mut opaque_commands : Vec<Command<String>> = Vec::new();
        let mut translucent_commands : Vec<Command<String>> = Vec::new();
        let mut additive_commands : Vec<Command<String>> = Vec::new();

        // let font = self.renderer.load_font(&font_description);

        // println!("render with delta -> {:?}", delta_time);
        let colors = vec![color::WHITE, color::BLUE, color::RED];

        // let (w, h) = self.camera.viewport.pixels;
        // let line = self.camera.ray_for_mouse_position((w / 2) as i32, (h / 2) as i32);
        // println!("forward line -> {:?}", line);

        let an = self.n / 60;

        let on_second = (self.n % 60) == 0;

        let raster_color = colors[(((an / 16) % 16) % 3) as usize]; // cycles every 16 seconds

        if on_second && an % 5 == 0 { // every fifth second
            let column = (an / 4) % 4;
            let name : String = format!("zone_{}", column);
            println!("delete {}", name);
            let pred : Box<Fn(&String) -> bool> = Box::new(move |key| key.starts_with(&name));
            opaque_commands.push(DeleteMatching { pred: pred });
        }

        // k.starts_with(&prefix)

        let n = (((an % 16) as f64) / 16.0 * 255.0) as u8;

        for i in 0..16 {
            let xo = i % 4;
            let zo = i / 4;
            let name : String = format!("zone_{}_{}", xo, zo);

            if (an % 16) == i && on_second {
                let t = self.raster(raster_color, (xo * 9) as f64, (zo * 9) as f64);
                opaque_commands.push(DrawNew {
                    key: Some(name),
                    vertices: t.tesselator.vertices,
                    uniforms: Uniforms {
                        transform : down_size_m4(self.camera.view_projection().into()),
                        color: color::WHITE,
                    }
                });
            } else if ((an+8) % 16) == i && on_second {
                let t = self.raster(raster_color, (xo * 9) as f64, (zo * 9) as f64);
                opaque_commands.push(Update {
                    key: name,
                    vertices: t.tesselator.vertices,
                });
            } else {
                let rem = (xo + zo) % 3;

                let color = match rem {
                    0 => color::rgba(255,255,255, 128),
                    1 => color::rgba(255,255,255, 50),
                    _ => color::WHITE,
                };
                let command = Draw {
                    key: name,
                     uniforms: Uniforms {
                        transform: down_size_m4(self.camera.view_projection().into()),
                        color: color,
                    }
                };

                match rem {
                    0 => translucent_commands.push(command),
                    1 => additive_commands.push(command),
                    _ => opaque_commands.push(command),
                };
            }
        }

        if let Some((font, layer)) = self.renderer.get_font(&font_description) {
            // println!("ok we got a font to use to draw layer -> {:?}", layer);
            let scale = 1.0 / self.camera.viewport.scale as f64;
            let mut t = GeometryTesselator::new(Vec3::new(1.0, 1.0, 1.0));

             let texture_region = TextureRegion {
                u_min: 0,
                u_max: 128,
                v_min: 0,
                v_max: 128,
                texture_size: 1024,
            };
            t.color = color::WHITE.float_raw();
            t.draw_ui(&texture_region, 0, 20.0, 20.0, 0.0, false, 1.0);

            let at = Vec2::new(0.0, 400.0);
            t.color = color::BLACK.float_raw();
            text::render_text(
                "Why oh why does a silly cow fly, you idiot.\n\nGo die in a pie.\n\nPls.",
                font,
                layer,
                at,
                -1.0, // i assume this is because our coordinate system is hosed ...
                scale,
                &mut t,
                Some(300.0)
            );

            translucent_commands.push(DrawNew {
                key: None,
                vertices: t.tesselator.vertices,
                uniforms: Uniforms {
                    transform : down_size_m4(self.camera.ui_projection().into()),
                    color: color::WHITE,
                }
            });
        }

        vec![Pass {
            blend: Blend::None,
            commands: opaque_commands,
        }, Pass {
            blend: Blend::Alpha,
            commands: translucent_commands,
        }, Pass {
            blend: Blend::Add,
            commands: additive_commands,
        }]
    }
}
<|endoftext|>


<commit_before>#![feature(ascii_ctype)]
use std::ascii::AsciiExt;

pub fn is_pangram(words: &str) -> bool {
    let score = &mut [false; 26];

    for v in words.chars() {
        if v.is_ascii_alphabetic() {
            let index = v.to_ascii_lowercase() as usize - 'a' as usize;

            score[index] = true;
        }
    }

    score.iter().all(|&x| x)
}
<commit_msg>Use bits as counters<commit_after>#![feature(ascii_ctype)]
use std::ascii::AsciiExt;

pub fn is_pangram(words: &str) -> bool {
    let mut score = 0u32;

    for v in words.chars() {
        if v.is_ascii_alphabetic() {
            let index = v.to_ascii_lowercase() as usize - 'a' as usize;
            score |= 1 << index;
        }
    }

    score == (1 << 26) - 1
}
<|endoftext|>


<commit_before>#[derive(Debug, PartialEq)]
pub enum Error {
    IncompleteNumber,
    Overflow,
}

/// Convert a list of numbers to a stream of bytes encoded with variable length encoding.
pub fn to_bytes(values: &[u32]) -> Vec<u8> {
    unimplemented!()
}

/// Given a stream of bytes, extract all numbers which are encoded in there.
pub fn from_bytes(bytes: &[u8]) -> Result<Vec<u32>, Error> {
    unimplemented!()
}
<commit_msg>variable-length-quantity: eliminate stub warnings<commit_after>#[derive(Debug, PartialEq)]
pub enum Error {
    IncompleteNumber,
    Overflow,
}

/// Convert a list of numbers to a stream of bytes encoded with variable length encoding.
pub fn to_bytes(values: &[u32]) -> Vec<u8> {
    unimplemented!("Convert the values {:?} to a list of bytes", values)
}

/// Given a stream of bytes, extract all numbers which are encoded in there.
pub fn from_bytes(bytes: &[u8]) -> Result<Vec<u32>, Error> {
    unimplemented!("Convert the list of bytes {:?} to a list of numbers", bytes)
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

use hir::{AssocItem, Either, FieldSource, HasSource, ModuleSource};
use ra_db::{FileId, SourceDatabase};
use ra_syntax::{
    ast::{self, DocCommentsOwner, NameOwner},
    match_ast, AstNode, SmolStr,
    SyntaxKind::{self, BIND_PAT},
    SyntaxNode, TextRange,
};

use super::short_label::ShortLabel;
use crate::{db::RootDatabase, FileSymbol};

/// `NavigationTarget` represents and element in the editor's UI which you can
/// click on to navigate to a particular piece of code.
///
/// Typically, a `NavigationTarget` corresponds to some element in the source
/// code, like a function or a struct, but this is not strictly required.
#[derive(Debug, Clone)]
pub struct NavigationTarget {
    file_id: FileId,
    name: SmolStr,
    kind: SyntaxKind,
    full_range: TextRange,
    focus_range: Option<TextRange>,
    container_name: Option<SmolStr>,
    description: Option<String>,
    docs: Option<String>,
}

pub(crate) trait ToNav {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget;
}

impl NavigationTarget {
    /// When `focus_range` is specified, returns it. otherwise
    /// returns `full_range`
    pub fn range(&self) -> TextRange {
        self.focus_range.unwrap_or(self.full_range)
    }

    pub fn name(&self) -> &SmolStr {
        &self.name
    }

    pub fn container_name(&self) -> Option<&SmolStr> {
        self.container_name.as_ref()
    }

    pub fn kind(&self) -> SyntaxKind {
        self.kind
    }

    pub fn file_id(&self) -> FileId {
        self.file_id
    }

    pub fn full_range(&self) -> TextRange {
        self.full_range
    }

    pub fn docs(&self) -> Option<&str> {
        self.docs.as_ref().map(String::as_str)
    }

    pub fn description(&self) -> Option<&str> {
        self.description.as_ref().map(String::as_str)
    }

    /// A "most interesting" range withing the `full_range`.
    ///
    /// Typically, `full_range` is the whole syntax node,
    /// including doc comments, and `focus_range` is the range of the identifier.
    pub fn focus_range(&self) -> Option<TextRange> {
        self.focus_range
    }

    pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
        let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
        if let Some(src) = module.declaration_source(db) {
            let (file_id, text_range) = find_range_from_node(db, src.file_id, src.ast.syntax());
            return NavigationTarget::from_syntax(
                file_id,
                name,
                None,
                text_range,
                src.ast.syntax(),
                src.ast.doc_comment_text(),
                src.ast.short_label(),
            );
        }
        module.to_nav(db)
    }

    pub(crate) fn from_def(
        db: &RootDatabase,
        module_def: hir::ModuleDef,
    ) -> Option<NavigationTarget> {
        let nav = match module_def {
            hir::ModuleDef::Module(module) => module.to_nav(db),
            hir::ModuleDef::Function(it) => it.to_nav(db),
            hir::ModuleDef::Adt(it) => it.to_nav(db),
            hir::ModuleDef::Const(it) => it.to_nav(db),
            hir::ModuleDef::Static(it) => it.to_nav(db),
            hir::ModuleDef::EnumVariant(it) => it.to_nav(db),
            hir::ModuleDef::Trait(it) => it.to_nav(db),
            hir::ModuleDef::TypeAlias(it) => it.to_nav(db),
            hir::ModuleDef::BuiltinType(..) => {
                return None;
            }
        };
        Some(nav)
    }

    #[cfg(test)]
    pub(crate) fn assert_match(&self, expected: &str) {
        let actual = self.debug_render();
        test_utils::assert_eq_text!(expected.trim(), actual.trim(),);
    }

    #[cfg(test)]
    pub(crate) fn debug_render(&self) -> String {
        let mut buf = format!(
            "{} {:?} {:?} {:?}",
            self.name(),
            self.kind(),
            self.file_id(),
            self.full_range()
        );
        if let Some(focus_range) = self.focus_range() {
            buf.push_str(&format!(" {:?}", focus_range))
        }
        if let Some(container_name) = self.container_name() {
            buf.push_str(&format!(" {}", container_name))
        }
        buf
    }

    /// Allows `NavigationTarget` to be created from a `NameOwner`
    pub(crate) fn from_named(
        db: &RootDatabase,
        file_id: hir::HirFileId,
        node: &impl ast::NameOwner,
        docs: Option<String>,
        description: Option<String>,
    ) -> NavigationTarget {
        //FIXME: use `_` instead of empty string
        let name = node.name().map(|it| it.text().clone()).unwrap_or_default();
        let focus_range = node.name().map(|it| find_range_from_node(db, file_id, it.syntax()).1);
        let (file_id, full_range) = find_range_from_node(db, file_id, node.syntax());

        NavigationTarget::from_syntax(
            file_id,
            name,
            focus_range,
            full_range,
            node.syntax(),
            docs,
            description,
        )
    }

    fn from_syntax(
        file_id: FileId,
        name: SmolStr,
        focus_range: Option<TextRange>,
        full_range: TextRange,
        node: &SyntaxNode,
        docs: Option<String>,
        description: Option<String>,
    ) -> NavigationTarget {
        NavigationTarget {
            file_id,
            name,
            kind: node.kind(),
            full_range,
            focus_range,
            container_name: None,
            description,
            docs,
        }
    }
}

impl ToNav for FileSymbol {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        NavigationTarget {
            file_id: self.file_id,
            name: self.name.clone(),
            kind: self.ptr.kind(),
            full_range: self.ptr.range(),
            focus_range: self.name_range,
            container_name: self.container_name.clone(),
            description: description_from_symbol(db, self),
            docs: docs_from_symbol(db, self),
        }
    }
}

pub(crate) trait ToNavFromAst {}
impl ToNavFromAst for hir::Function {}
impl ToNavFromAst for hir::Const {}
impl ToNavFromAst for hir::Static {}
impl ToNavFromAst for hir::Struct {}
impl ToNavFromAst for hir::Enum {}
impl ToNavFromAst for hir::EnumVariant {}
impl ToNavFromAst for hir::Union {}
impl ToNavFromAst for hir::TypeAlias {}
impl ToNavFromAst for hir::Trait {}

impl<D> ToNav for D
where
    D: HasSource + ToNavFromAst + Copy,
    D::Ast: ast::DocCommentsOwner + ast::NameOwner + ShortLabel,
{
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        let src = self.source(db);
        NavigationTarget::from_named(
            db,
            src.file_id,
            &src.ast,
            src.ast.doc_comment_text(),
            src.ast.short_label(),
        )
    }
}

impl ToNav for hir::Module {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        let src = self.definition_source(db);
        let name = self.name(db).map(|it| it.to_string().into()).unwrap_or_default();
        match src.ast {
            ModuleSource::SourceFile(node) => {
                let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax());

                NavigationTarget::from_syntax(
                    file_id,
                    name,
                    None,
                    text_range,
                    node.syntax(),
                    None,
                    None,
                )
            }
            ModuleSource::Module(node) => {
                let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax());

                NavigationTarget::from_syntax(
                    file_id,
                    name,
                    None,
                    text_range,
                    node.syntax(),
                    node.doc_comment_text(),
                    node.short_label(),
                )
            }
        }
    }
}

impl ToNav for hir::ImplBlock {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        let src = self.source(db);
        let (file_id, text_range) = find_range_from_node(db, src.file_id, src.ast.syntax());

        NavigationTarget::from_syntax(
            file_id,
            "impl".into(),
            None,
            text_range,
            src.ast.syntax(),
            None,
            None,
        )
    }
}

impl ToNav for hir::StructField {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        let src = self.source(db);

        match src.ast {
            FieldSource::Named(it) => NavigationTarget::from_named(
                db,
                src.file_id,
                &it,
                it.doc_comment_text(),
                it.short_label(),
            ),
            FieldSource::Pos(it) => {
                let (file_id, text_range) = find_range_from_node(db, src.file_id, it.syntax());
                NavigationTarget::from_syntax(
                    file_id,
                    "".into(),
                    None,
                    text_range,
                    it.syntax(),
                    None,
                    None,
                )
            }
        }
    }
}

impl ToNav for hir::MacroDef {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        let src = self.source(db);
        log::debug!("nav target {:#?}", src.ast.syntax());
        NavigationTarget::from_named(db, src.file_id, &src.ast, src.ast.doc_comment_text(), None)
    }
}

impl ToNav for hir::Adt {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        match self {
            hir::Adt::Struct(it) => it.to_nav(db),
            hir::Adt::Union(it) => it.to_nav(db),
            hir::Adt::Enum(it) => it.to_nav(db),
        }
    }
}

impl ToNav for hir::AssocItem {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        match self {
            AssocItem::Function(it) => it.to_nav(db),
            AssocItem::Const(it) => it.to_nav(db),
            AssocItem::TypeAlias(it) => it.to_nav(db),
        }
    }
}

impl ToNav for hir::Local {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        let src = self.source(db);
        let (full_range, focus_range) = match src.ast {
            Either::A(it) => {
                (it.syntax().text_range(), it.name().map(|it| it.syntax().text_range()))
            }
            Either::B(it) => (it.syntax().text_range(), Some(it.self_kw_token().text_range())),
        };
        let name = match self.name(db) {
            Some(it) => it.to_string().into(),
            None => "".into(),
        };
        NavigationTarget {
            file_id: src.file_id.original_file(db),
            name,
            kind: BIND_PAT,
            full_range,
            focus_range,
            container_name: None,
            description: None,
            docs: None,
        }
    }
}

fn find_range_from_node(
    db: &RootDatabase,
    src: hir::HirFileId,
    node: &SyntaxNode,
) -> (FileId, TextRange) {
    let text_range = node.text_range();
    let (file_id, text_range) = src
        .expansion_info(db)
        .and_then(|expansion_info| expansion_info.find_range(text_range))
        .unwrap_or((src, text_range));

    // FIXME: handle recursive macro generated macro
    (file_id.original_file(db), text_range)
}

pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> {
    let parse = db.parse(symbol.file_id);
    let node = symbol.ptr.to_node(parse.tree().syntax());

    match_ast! {
        match node {
            ast::FnDef(it) => { it.doc_comment_text() },
            ast::StructDef(it) => { it.doc_comment_text() },
            ast::EnumDef(it) => { it.doc_comment_text() },
            ast::TraitDef(it) => { it.doc_comment_text() },
            ast::Module(it) => { it.doc_comment_text() },
            ast::TypeAliasDef(it) => { it.doc_comment_text() },
            ast::ConstDef(it) => { it.doc_comment_text() },
            ast::StaticDef(it) => { it.doc_comment_text() },
            ast::RecordFieldDef(it) => { it.doc_comment_text() },
            ast::EnumVariant(it) => { it.doc_comment_text() },
            ast::MacroCall(it) => { it.doc_comment_text() },
            _ => None,
        }
    }
}

/// Get a description of a symbol.
///
/// e.g. `struct Name`, `enum Name`, `fn Name`
pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> {
    let parse = db.parse(symbol.file_id);
    let node = symbol.ptr.to_node(parse.tree().syntax());

    match_ast! {
        match node {
            ast::FnDef(it) => { it.short_label() },
            ast::StructDef(it) => { it.short_label() },
            ast::EnumDef(it) => { it.short_label() },
            ast::TraitDef(it) => { it.short_label() },
            ast::Module(it) => { it.short_label() },
            ast::TypeAliasDef(it) => { it.short_label() },
            ast::ConstDef(it) => { it.short_label() },
            ast::StaticDef(it) => { it.short_label() },
            ast::RecordFieldDef(it) => { it.short_label() },
            ast::EnumVariant(it) => { it.short_label() },
            _ => None,
        }
    }
}
<commit_msg>More Source<commit_after>//! FIXME: write short doc here

use hir::{AssocItem, Either, FieldSource, HasSource, ModuleSource, Source};
use ra_db::{FileId, SourceDatabase};
use ra_syntax::{
    ast::{self, DocCommentsOwner, NameOwner},
    match_ast, AstNode, SmolStr,
    SyntaxKind::{self, BIND_PAT},
    SyntaxNode, TextRange,
};

use super::short_label::ShortLabel;
use crate::{db::RootDatabase, FileSymbol};

/// `NavigationTarget` represents and element in the editor's UI which you can
/// click on to navigate to a particular piece of code.
///
/// Typically, a `NavigationTarget` corresponds to some element in the source
/// code, like a function or a struct, but this is not strictly required.
#[derive(Debug, Clone)]
pub struct NavigationTarget {
    file_id: FileId,
    name: SmolStr,
    kind: SyntaxKind,
    full_range: TextRange,
    focus_range: Option<TextRange>,
    container_name: Option<SmolStr>,
    description: Option<String>,
    docs: Option<String>,
}

pub(crate) trait ToNav {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget;
}

impl NavigationTarget {
    /// When `focus_range` is specified, returns it. otherwise
    /// returns `full_range`
    pub fn range(&self) -> TextRange {
        self.focus_range.unwrap_or(self.full_range)
    }

    pub fn name(&self) -> &SmolStr {
        &self.name
    }

    pub fn container_name(&self) -> Option<&SmolStr> {
        self.container_name.as_ref()
    }

    pub fn kind(&self) -> SyntaxKind {
        self.kind
    }

    pub fn file_id(&self) -> FileId {
        self.file_id
    }

    pub fn full_range(&self) -> TextRange {
        self.full_range
    }

    pub fn docs(&self) -> Option<&str> {
        self.docs.as_ref().map(String::as_str)
    }

    pub fn description(&self) -> Option<&str> {
        self.description.as_ref().map(String::as_str)
    }

    /// A "most interesting" range withing the `full_range`.
    ///
    /// Typically, `full_range` is the whole syntax node,
    /// including doc comments, and `focus_range` is the range of the identifier.
    pub fn focus_range(&self) -> Option<TextRange> {
        self.focus_range
    }

    pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
        let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
        if let Some(src) = module.declaration_source(db) {
            let (file_id, text_range) =
                find_range_from_node(db, src.as_ref().map(|it| it.syntax()));
            return NavigationTarget::from_syntax(
                file_id,
                name,
                None,
                text_range,
                src.ast.syntax(),
                src.ast.doc_comment_text(),
                src.ast.short_label(),
            );
        }
        module.to_nav(db)
    }

    pub(crate) fn from_def(
        db: &RootDatabase,
        module_def: hir::ModuleDef,
    ) -> Option<NavigationTarget> {
        let nav = match module_def {
            hir::ModuleDef::Module(module) => module.to_nav(db),
            hir::ModuleDef::Function(it) => it.to_nav(db),
            hir::ModuleDef::Adt(it) => it.to_nav(db),
            hir::ModuleDef::Const(it) => it.to_nav(db),
            hir::ModuleDef::Static(it) => it.to_nav(db),
            hir::ModuleDef::EnumVariant(it) => it.to_nav(db),
            hir::ModuleDef::Trait(it) => it.to_nav(db),
            hir::ModuleDef::TypeAlias(it) => it.to_nav(db),
            hir::ModuleDef::BuiltinType(..) => {
                return None;
            }
        };
        Some(nav)
    }

    #[cfg(test)]
    pub(crate) fn assert_match(&self, expected: &str) {
        let actual = self.debug_render();
        test_utils::assert_eq_text!(expected.trim(), actual.trim(),);
    }

    #[cfg(test)]
    pub(crate) fn debug_render(&self) -> String {
        let mut buf = format!(
            "{} {:?} {:?} {:?}",
            self.name(),
            self.kind(),
            self.file_id(),
            self.full_range()
        );
        if let Some(focus_range) = self.focus_range() {
            buf.push_str(&format!(" {:?}", focus_range))
        }
        if let Some(container_name) = self.container_name() {
            buf.push_str(&format!(" {}", container_name))
        }
        buf
    }

    /// Allows `NavigationTarget` to be created from a `NameOwner`
    pub(crate) fn from_named(
        db: &RootDatabase,
        file_id: hir::HirFileId,
        node: &impl ast::NameOwner,
        docs: Option<String>,
        description: Option<String>,
    ) -> NavigationTarget {
        //FIXME: use `_` instead of empty string
        let name = node.name().map(|it| it.text().clone()).unwrap_or_default();
        let focus_range =
            node.name().map(|it| find_range_from_node(db, Source::new(file_id, it.syntax())).1);
        let (file_id, full_range) = find_range_from_node(db, Source::new(file_id, node.syntax()));

        NavigationTarget::from_syntax(
            file_id,
            name,
            focus_range,
            full_range,
            node.syntax(),
            docs,
            description,
        )
    }

    fn from_syntax(
        file_id: FileId,
        name: SmolStr,
        focus_range: Option<TextRange>,
        full_range: TextRange,
        node: &SyntaxNode,
        docs: Option<String>,
        description: Option<String>,
    ) -> NavigationTarget {
        NavigationTarget {
            file_id,
            name,
            kind: node.kind(),
            full_range,
            focus_range,
            container_name: None,
            description,
            docs,
        }
    }
}

impl ToNav for FileSymbol {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        NavigationTarget {
            file_id: self.file_id,
            name: self.name.clone(),
            kind: self.ptr.kind(),
            full_range: self.ptr.range(),
            focus_range: self.name_range,
            container_name: self.container_name.clone(),
            description: description_from_symbol(db, self),
            docs: docs_from_symbol(db, self),
        }
    }
}

pub(crate) trait ToNavFromAst {}
impl ToNavFromAst for hir::Function {}
impl ToNavFromAst for hir::Const {}
impl ToNavFromAst for hir::Static {}
impl ToNavFromAst for hir::Struct {}
impl ToNavFromAst for hir::Enum {}
impl ToNavFromAst for hir::EnumVariant {}
impl ToNavFromAst for hir::Union {}
impl ToNavFromAst for hir::TypeAlias {}
impl ToNavFromAst for hir::Trait {}

impl<D> ToNav for D
where
    D: HasSource + ToNavFromAst + Copy,
    D::Ast: ast::DocCommentsOwner + ast::NameOwner + ShortLabel,
{
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        let src = self.source(db);
        NavigationTarget::from_named(
            db,
            src.file_id,
            &src.ast,
            src.ast.doc_comment_text(),
            src.ast.short_label(),
        )
    }
}

impl ToNav for hir::Module {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        let src = self.definition_source(db);
        let name = self.name(db).map(|it| it.to_string().into()).unwrap_or_default();
        match &src.ast {
            ModuleSource::SourceFile(node) => {
                let (file_id, text_range) = find_range_from_node(db, src.with_ast(node.syntax()));

                NavigationTarget::from_syntax(
                    file_id,
                    name,
                    None,
                    text_range,
                    node.syntax(),
                    None,
                    None,
                )
            }
            ModuleSource::Module(node) => {
                let (file_id, text_range) = find_range_from_node(db, src.with_ast(node.syntax()));

                NavigationTarget::from_syntax(
                    file_id,
                    name,
                    None,
                    text_range,
                    node.syntax(),
                    node.doc_comment_text(),
                    node.short_label(),
                )
            }
        }
    }
}

impl ToNav for hir::ImplBlock {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        let src = self.source(db);
        let (file_id, text_range) = find_range_from_node(db, src.as_ref().map(|it| it.syntax()));

        NavigationTarget::from_syntax(
            file_id,
            "impl".into(),
            None,
            text_range,
            src.ast.syntax(),
            None,
            None,
        )
    }
}

impl ToNav for hir::StructField {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        let src = self.source(db);

        match &src.ast {
            FieldSource::Named(it) => NavigationTarget::from_named(
                db,
                src.file_id,
                it,
                it.doc_comment_text(),
                it.short_label(),
            ),
            FieldSource::Pos(it) => {
                let (file_id, text_range) = find_range_from_node(db, src.with_ast(it.syntax()));
                NavigationTarget::from_syntax(
                    file_id,
                    "".into(),
                    None,
                    text_range,
                    it.syntax(),
                    None,
                    None,
                )
            }
        }
    }
}

impl ToNav for hir::MacroDef {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        let src = self.source(db);
        log::debug!("nav target {:#?}", src.ast.syntax());
        NavigationTarget::from_named(db, src.file_id, &src.ast, src.ast.doc_comment_text(), None)
    }
}

impl ToNav for hir::Adt {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        match self {
            hir::Adt::Struct(it) => it.to_nav(db),
            hir::Adt::Union(it) => it.to_nav(db),
            hir::Adt::Enum(it) => it.to_nav(db),
        }
    }
}

impl ToNav for hir::AssocItem {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        match self {
            AssocItem::Function(it) => it.to_nav(db),
            AssocItem::Const(it) => it.to_nav(db),
            AssocItem::TypeAlias(it) => it.to_nav(db),
        }
    }
}

impl ToNav for hir::Local {
    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
        let src = self.source(db);
        let (full_range, focus_range) = match src.ast {
            Either::A(it) => {
                (it.syntax().text_range(), it.name().map(|it| it.syntax().text_range()))
            }
            Either::B(it) => (it.syntax().text_range(), Some(it.self_kw_token().text_range())),
        };
        let name = match self.name(db) {
            Some(it) => it.to_string().into(),
            None => "".into(),
        };
        NavigationTarget {
            file_id: src.file_id.original_file(db),
            name,
            kind: BIND_PAT,
            full_range,
            focus_range,
            container_name: None,
            description: None,
            docs: None,
        }
    }
}

fn find_range_from_node(db: &RootDatabase, node: Source<&SyntaxNode>) -> (FileId, TextRange) {
    let text_range = node.ast.text_range();
    let (file_id, text_range) = node
        .file_id
        .expansion_info(db)
        .and_then(|expansion_info| expansion_info.find_range(text_range))
        .unwrap_or((node.file_id, text_range));

    // FIXME: handle recursive macro generated macro
    (file_id.original_file(db), text_range)
}

pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> {
    let parse = db.parse(symbol.file_id);
    let node = symbol.ptr.to_node(parse.tree().syntax());

    match_ast! {
        match node {
            ast::FnDef(it) => { it.doc_comment_text() },
            ast::StructDef(it) => { it.doc_comment_text() },
            ast::EnumDef(it) => { it.doc_comment_text() },
            ast::TraitDef(it) => { it.doc_comment_text() },
            ast::Module(it) => { it.doc_comment_text() },
            ast::TypeAliasDef(it) => { it.doc_comment_text() },
            ast::ConstDef(it) => { it.doc_comment_text() },
            ast::StaticDef(it) => { it.doc_comment_text() },
            ast::RecordFieldDef(it) => { it.doc_comment_text() },
            ast::EnumVariant(it) => { it.doc_comment_text() },
            ast::MacroCall(it) => { it.doc_comment_text() },
            _ => None,
        }
    }
}

/// Get a description of a symbol.
///
/// e.g. `struct Name`, `enum Name`, `fn Name`
pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> {
    let parse = db.parse(symbol.file_id);
    let node = symbol.ptr.to_node(parse.tree().syntax());

    match_ast! {
        match node {
            ast::FnDef(it) => { it.short_label() },
            ast::StructDef(it) => { it.short_label() },
            ast::EnumDef(it) => { it.short_label() },
            ast::TraitDef(it) => { it.short_label() },
            ast::Module(it) => { it.short_label() },
            ast::TypeAliasDef(it) => { it.short_label() },
            ast::ConstDef(it) => { it.short_label() },
            ast::StaticDef(it) => { it.short_label() },
            ast::RecordFieldDef(it) => { it.short_label() },
            ast::EnumVariant(it) => { it.short_label() },
            _ => None,
        }
    }
}
<|endoftext|>


<commit_before>use regex::Regex;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
use std::collections::HashSet;
use std::str::FromStr;

extern crate regex;

struct Replacement {
    key: String,
    val: String,
}

impl Replacement {
    fn new(key: &str, val: &str) -> Replacement {
        Replacement {
            key: key.to_string(),
            val: val.to_string(),
        }
    }

    fn possibilities(&self, input: &String) -> HashSet<String> {
        let mut poss = HashSet::new();
        for p in input.match_indices(&self.key) {
            let len = p.1.len();
            let prefix = &input[0..p.0];
            let suffix = &input[p.0 + len..];
            poss.insert(prefix.to_string() + &self.val + suffix);
        }
        poss
    }
}

#[derive(Debug)]
struct InvalidInput;

impl FromStr for Replacement {
    type Err = InvalidInput;
    fn from_str(s: &str) -> Result<Replacement, InvalidInput> {
        let parser = Regex::new(r"(.+)\s=>\s(.+)").unwrap();
        let res = parser.captures(s);
        if res.is_none() {
            return Err(InvalidInput {});
        }

        let cap = res.unwrap();
        let from = cap.at(1).unwrap();
        let to = cap.at(2).unwrap();
        Ok(Replacement::new(from, to))
    }
}

fn unique_possibilities(input: &String, replacements: &Vec<Replacement>) -> HashSet<String> {
    let mut out = HashSet::new();
    for r in replacements {
        out = out.union(&r.possibilities(input)).cloned().collect();
    }
    out
}

#[test]
fn test_unique() {
    let start = "HOH".to_string();
    let reps = vec!(
        Replacement::new("H", "HO"),
        Replacement::new("H", "OH"),
        Replacement::new("O", "HH"),
    );
    let poss = unique_possibilities(&start, &reps);
    assert_eq!(poss,
               ["HOOH", "OHOH", "HOHO", "HHHH"].iter().map(|x| x.to_string()).collect());
}

fn main() {
    let f = File::open("input.txt").unwrap();
    let line_buffer = BufReader::new(&f);

    let mut repls = Vec::new();
    let mut start: String = "".to_string();
    for line in line_buffer.lines() {
        let curr = line.unwrap();
        if curr == "" {
            continue;
        }
        match curr.parse::<Replacement>() {
            Ok(r) => repls.push(r),
            Err(_) => {
                start = curr;
            }
        };
    }

    let possible = unique_possibilities(&start, &repls);
    println!("{} possibilities", possible.len());
}
<commit_msg> I cheated, whatever, though my exhaustive did spit this one out at point, I got the hard input type and did not want to write a full lexer<commit_after>use regex::Regex;
use std::cmp::min;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
use std::collections::{HashSet};
use std::str::FromStr;

extern crate regex;

#[derive(Clone, Debug)]
struct Replacement {
    key: String,
    val: String,
}

impl Replacement {
    fn new(key: &str, val: &str) -> Replacement {
        Replacement {
            key: key.to_string(),
            val: val.to_string(),
        }
    }

    fn possibilities(&self, input: &String) -> HashSet<String> {
        let mut poss = HashSet::new();
        for p in input.match_indices(&self.key) {
            let len = p.1.len();
            let prefix = &input[0..p.0];
            let suffix = &input[p.0 + len..];
            poss.insert(prefix.to_string() + &self.val + suffix);
        }
        poss
    }

    // Assuming this replacement was used to create result, what was it before.
    fn produced_from(&self, result: &String) -> Option<(usize, String)> {
        let new = result.replace(&self.val, &self.key);
        if new == *result { None } else { Some((result.matches(&self.val).count(), new)) }
    }

    fn replace_first(&self, input: &String) -> Option<String> {
        let len = self.key.len();
        input.find(&self.key).and_then(|x| Some(input[0..x].to_string() + &self.val + &input[x + len..]))
    }

    fn num_result_molecules(&self) -> usize {
        self.val.chars().filter(|x| x.is_uppercase()).count()
    }
}

#[derive(Debug)]
struct InvalidInput;

impl FromStr for Replacement {
    type Err = InvalidInput;
    fn from_str(s: &str) -> Result<Replacement, InvalidInput> {
        let parser = Regex::new(r"(.+)\s=>\s(.+)").unwrap();
        let res = parser.captures(s);
        if res.is_none() {
            return Err(InvalidInput {});
        }

        let cap = res.unwrap();
        let from = cap.at(1).unwrap();
        let to = cap.at(2).unwrap();
        Ok(Replacement::new(from, to))
    }
}

fn unique_possibilities(input: &String, replacements: &Vec<Replacement>) -> HashSet<String> {
    let mut out = HashSet::new();
    for r in replacements {
        out = out.union(&r.possibilities(input)).cloned().collect();
    }
    out
}

fn find_synthesis(input: &String, replacements: &Vec<Replacement>) -> Vec<Replacement> {
    let mut sorted = replacements.clone();
    sorted.sort_by(|a, b| a.num_result_molecules().cmp(&b.num_result_molecules()));
    return find_synthesis_with_order(input, &sorted);
}

fn find_synthesis_with_order(input: &String, replacements: &Vec<Replacement>) -> Vec<Replacement> {
    let mut curr = input.clone();
    let mut steps = Vec::new();
    loop {
        let (next, mut next_steps) = best_step(&curr, replacements);
        println!("Best Steps {:?} from {} to {}", next_steps, curr, next);
        next_steps.extend(steps);
        steps = next_steps;
        if next == "e" {
            break;
        }
        curr = next;
    }
    steps
}

fn best_step(input: &String, sorted_replacements: &Vec<Replacement>) -> (String, Vec<Replacement>) {
    let mut curr = input;
    for repl in sorted_replacements {
        let replaced = repl.produced_from(curr);
        match replaced {
            None => {},
            Some((num, new)) => {
                let mut steps = Vec::new();
                for i in 0..num {
                    steps.push(repl.clone());
                }
                return (new, steps);
            },
        };
    }
    (input.clone(), Vec::new())
}

#[test]
fn test_unique() {
    let start = "HOH".to_string();
    let reps = vec!(
        Replacement::new("H", "HO"),
        Replacement::new("H", "OH"),
        Replacement::new("O", "HH"),
    );
    let poss = unique_possibilities(&start, &reps);
    assert_eq!(poss,
               ["HOOH", "OHOH", "HOHO", "HHHH"].iter().map(|x| x.to_string()).collect());
}

// Totally infeasible.
fn exhaustive(input: &String, target: &String, repls: &Vec<Replacement>, depth: usize) -> (HashSet<String>, Option<usize>) {
    let i_len = input.len();
    let t_len = target.len();
    if i_len > t_len {
        return (HashSet::new(), None);
    } else if i_len == t_len && input == target {
        return (HashSet::new(), Some(depth));
    }

    let mut out = HashSet::new();
    let mut best = None;
    for poss in unique_possibilities(input, &repls) {
        let (options, found) = exhaustive(&poss, target, &repls, depth + 1);
        best = match found {
            Some(v) => Some(min(best.unwrap_or(std::usize::MAX), v)),
            None => best,
        };
        out = out.union(&options).cloned().collect();
    }
    (out, best)
}

// Also infeasible
fn exhaustive_reverse(input: &String, target: &String, repls: &Vec<Replacement>, depth: usize) -> (HashSet<String>, Option<usize>) {
    let i_len = input.len();
    let t_len = target.len();
    if i_len < t_len {
        return (HashSet::new(), None);
    } else if i_len == t_len && input == target {
        println!("Bottom out {}", depth);
        return (HashSet::new(), Some(depth));
    }

    let mut out = HashSet::new();
    let mut best = None;
    for poss in unique_possibilities(input, &repls) {
        let (options, found) = exhaustive_reverse(&poss, target, &repls, depth + 1);
        best = match found {
            Some(v) => Some(min(best.unwrap_or(std::usize::MAX), v)),
            None => best,
        };
        out = out.union(&options).cloned().collect();
    }
    if best.is_some() {
        println!("Found one at depth {}", best.unwrap());
    }
    if out.len() == 0 {
        println!("Busted at {} with {}", depth, input);
    }
    (out, best)
}

// Cheat and sue the formula
// https://www.reddit.com/r/adventofcode/comments/3xflz8/day_19_solutions/cy4etju to reduce based
fn calculate(input: &String) -> usize {
    let element_count = input.chars().filter(|x| x.is_uppercase()).count();
    let paren_count = input.match_indices("Ar").count() + input.match_indices("Rn").count();
    let comma_count = input.match_indices("Y").count();
    element_count - paren_count - 2*comma_count - 1
}

fn main() {
    let f = File::open("input.txt").unwrap();
    let line_buffer = BufReader::new(&f);

    let mut repls = Vec::new();
    let mut goal: String = "".to_string();
    for line in line_buffer.lines() {
        let curr = line.unwrap();
        if curr == "" {
            continue;
        }
        match curr.parse::<Replacement>() {
            Ok(r) => repls.push(r),
            Err(_) => {
                goal = curr;
            }
        };
    }

    println!("Repls {:?}", repls);

    let mut rev_reps = Vec::new();
    for r in &repls {
        rev_reps.push(Replacement{key: r.val.clone(), val: r.key.clone()});
    }

    let possible = unique_possibilities(&goal, &repls);
    //    let ex = exhaustive_reverse(&goal, &"e".to_string(), &rev_reps, 0);
   // let chain = find_synthesis(&goal, &repls);
    println!("{} cheater, I'm not writing a lexer and I got the hard input", calculate(&goal));
}
<|endoftext|>