<commit_before>use std::io::net::udp::UdpSocket;
use std::io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr};
use std::io::{IoResult, IoError, OtherIoError, TimedOut};
use std::io::Timer;
use std::comm::{Disconnected, Empty, Select};
use std::time::duration::Duration;
use std::collections::TreeMap;
use packet::{Packet, PacketType, PacketConnect, PacketDisconnect, PacketMessage, PacketAccept, PacketReject, Command, Disconnect};

//FIXME: Ew ew ew
fn hash_sender(address: &SocketAddr) -> String {
    match address.ip {
        Ipv4Addr(a, b, c, d) => {
            format!("{}-{}-{}-{}:{}", a, b, c, d, address.port)
        },
        Ipv6Addr(a, b, c, d, e, f, g, h) => {
            format!("{}-{}-{}-{}-{}-{}-{}-{}:{}", a, b, c, d, e, f, g, h, address.port)
        }
    }
}

/**
 * What we want:
 * Server sits and loops about. Has a send/receive buffer
 * Has a broadcast method?
 * Has a send method
 * Has a read method, to pump items out of the receive buffer
 * Has a read iterator?
 */
fn reader_process(mut reader: UdpSocket, reader_sub_out: Sender<(Packet, SocketAddr)>, reader_sub_in: Receiver<Command>, protocol_id: u32) {
    let mut buf = [0, ..255];
    reader.set_timeout(Some(1000));
    loop {
        match reader.recv_from(buf) {
            Ok((amt, src)) => {
                match Packet::deserialize(buf.slice_to(amt)) {
                    Ok(packet) => {
                        if packet.protocol_id == protocol_id {
                            reader_sub_out.send((packet, src));
                        }
                    },
                    Err(_) => ()
                }
            },
            Err(e) => {
                match e.kind {
                    TimedOut => {
                        match reader_sub_in.try_recv() {
                            Ok(Disconnect) => {
                                break;
                            },
                            Err(Disconnected) => {
                                break;
                            },
                            Err(Empty) => ()
                        }
                    },
                    _ => ()
                }
            }
        }
    }
}

fn writer_process(mut writer: UdpSocket, writer_sub_out: Sender<Command>, writer_sub_in: Receiver<(Packet, SocketAddr)>) {
    for (msg, target_addr) in writer_sub_in.iter() {
        match msg.serialize() {
            Ok(msg) => {
                match writer.send_to(msg.as_slice(), target_addr) {
                    Ok(()) => (),
                    Err(e) => println!("Error sending data - {}", e)
                }
            },
            Err(_) => ()
        }
    }
}

pub struct ServerManager {
    pub addr: SocketAddr,

    protocol_id: u32,
    reader_send: Sender<Command>,
    reader_receive: Receiver<(Packet, SocketAddr)>,
    writer_send: Sender<(Packet, SocketAddr)>,
    writer_receive: Receiver<Command>,

    connections: TreeMap<String, SocketAddr>
}

impl ServerManager {
    pub fn new(protocol_id: u32, addr: SocketAddr) -> IoResult<ServerManager> {
        match UdpSocket::bind(addr) {
            Ok(reader) => {
                let writer = reader.clone();
                let (reader_out, reader_sub_in) = channel();
                let (reader_sub_out, reader_in) = channel();

                spawn(proc() {
                    reader_process(reader, reader_sub_out, reader_sub_in, protocol_id);
                });

                let (writer_out, writer_sub_in) = channel();
                let (writer_sub_out, writer_in) = channel();

                spawn(proc() {
                    writer_process(writer, writer_sub_out, writer_sub_in);
                });

                Ok(ServerManager {
                    protocol_id: protocol_id,
                    addr: addr,
                    reader_send: reader_out,
                    reader_receive: reader_in,
                    writer_send: writer_out,
                    writer_receive: writer_in,
                    connections: TreeMap::new()
                })
            }
            Err(e) => Err(e)
        }
    }

    pub fn poll(&mut self) -> Option<(Packet, SocketAddr)> {
        let mut out = None;
        loop {
            match self.reader_receive.try_recv() {
                Ok((packet, src)) => {
                    //Handle any new connections
                    match packet.packet_type {
                        PacketConnect => {
                            self.connections.insert(hash_sender(&src), src);
                            self.writer_send.send((Packet::accept(self.protocol_id), src));
                            out = Some((packet, src));
                            break
                        },
                        PacketDisconnect => {
                            let hash = hash_sender(&src);
                            self.connections.remove(&hash);
                            if self.connections.contains_key(&hash) {
                                out = Some((packet, src));
                                break
                            }
                        },
                        PacketMessage => {
                            let hash = hash_sender(&src);
                            if self.connections.contains_key(&hash) {
                                //Propagate any new messages
                                out = Some((packet, src));
                                break
                            }
                        },
                        _ => ()
                    };
                },
                _ => {
                    break
                }
            };
        };
        out
    }

    pub fn send_to(&mut self, packet: &Packet, addr: &SocketAddr) {
        let hashed = hash_sender(addr);
        match self.connections.find(&hashed) {
            Some(_) => self.writer_send.send((packet.clone(), addr.clone())),
            None => (),
        }
    }

    pub fn send_to_many(&mut self, packet: &Packet, addrs: &Vec<SocketAddr>) {
        for addr in addrs.iter() {
            self.send_to(packet, addr)
        }
    }

    pub fn send_to_all(&mut self, packet: &Packet) {
        for addr in self.connections.clone().values() { //FIXME: Urgh
            self.send_to(packet, addr)
        }
    }
}

impl Drop for ServerManager {

    fn drop(&mut self) {
        self.reader_send.send(Disconnect);
    }
}
<commit_msg>Started implementing server-side timeouts<commit_after>use std::io::net::udp::UdpSocket;
use std::io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr};
use std::io::{IoResult, IoError, OtherIoError, TimedOut};
use std::io::Timer;
use std::comm::{Disconnected, Empty, Select};
use std::time::duration::Duration;
use std::collections::TreeMap;
use packet::{Packet, PacketType, PacketConnect, PacketDisconnect, PacketMessage, PacketAccept, PacketReject, Command, Disconnect};
use time;

//FIXME: Ew ew ew
fn hash_sender(address: &SocketAddr) -> String {
    match address.ip {
        Ipv4Addr(a, b, c, d) => {
            format!("{}-{}-{}-{}:{}", a, b, c, d, address.port)
        },
        Ipv6Addr(a, b, c, d, e, f, g, h) => {
            format!("{}-{}-{}-{}-{}-{}-{}-{}:{}", a, b, c, d, e, f, g, h, address.port)
        }
    }
}

#[deriving(Clone)]
struct ClientInstance {
    addr: SocketAddr,
    timeout: i64
}

impl ClientInstance {
    pub fn new(addr: SocketAddr, timeout: i64) -> ClientInstance {
        ClientInstance {
            addr: addr,
            timeout: timeout
        }
    }
}

/**
 * What we want:
 * Server sits and loops about. Has a send/receive buffer
 * Has a broadcast method?
 * Has a send method
 * Has a read method, to pump items out of the receive buffer
 * Has a read iterator?
 */
fn reader_process(mut reader: UdpSocket, reader_sub_out: Sender<(Packet, SocketAddr)>, reader_sub_in: Receiver<Command>, protocol_id: u32) {
    let mut buf = [0, ..255];
    reader.set_timeout(Some(1000));
    loop {
        match reader.recv_from(buf) {
            Ok((amt, src)) => {
                match Packet::deserialize(buf.slice_to(amt)) {
                    Ok(packet) => {
                        if packet.protocol_id == protocol_id {
                            reader_sub_out.send((packet, src));
                        }
                    },
                    Err(_) => ()
                }
            },
            Err(e) => {
                match e.kind {
                    TimedOut => {
                        match reader_sub_in.try_recv() {
                            Ok(Disconnect) => {
                                break;
                            },
                            Err(Disconnected) => {
                                break;
                            },
                            Err(Empty) => ()
                        }
                    },
                    _ => ()
                }
            }
        }
    }
}

fn writer_process(mut writer: UdpSocket, writer_sub_out: Sender<Command>, writer_sub_in: Receiver<(Packet, SocketAddr)>) {
    for (msg, target_addr) in writer_sub_in.iter() {
        match msg.serialize() {
            Ok(msg) => {
                match writer.send_to(msg.as_slice(), target_addr) {
                    Ok(()) => (),
                    Err(e) => println!("Error sending data - {}", e)
                }
            },
            Err(_) => ()
        }
    }
}

pub struct ServerManager {
    pub addr: SocketAddr,

    protocol_id: u32,
    reader_send: Sender<Command>,
    reader_receive: Receiver<(Packet, SocketAddr)>,
    writer_send: Sender<(Packet, SocketAddr)>,
    writer_receive: Receiver<Command>,

    connections: TreeMap<String, ClientInstance>
}

impl ServerManager {
    pub fn new(protocol_id: u32, addr: SocketAddr) -> IoResult<ServerManager> {
        match UdpSocket::bind(addr) {
            Ok(reader) => {
                let writer = reader.clone();
                let (reader_out, reader_sub_in) = channel();
                let (reader_sub_out, reader_in) = channel();

                spawn(proc() {
                    reader_process(reader, reader_sub_out, reader_sub_in, protocol_id);
                });

                let (writer_out, writer_sub_in) = channel();
                let (writer_sub_out, writer_in) = channel();

                spawn(proc() {
                    writer_process(writer, writer_sub_out, writer_sub_in);
                });

                Ok(ServerManager {
                    protocol_id: protocol_id,
                    addr: addr,
                    reader_send: reader_out,
                    reader_receive: reader_in,
                    writer_send: writer_out,
                    writer_receive: writer_in,
                    connections: TreeMap::new()
                })
            }
            Err(e) => Err(e)
        }
    }

    pub fn poll(&mut self) -> Option<(Packet, SocketAddr)> {
        let mut out = None;
        loop {
            match self.reader_receive.try_recv() {
                Ok((packet, src)) => {
                    //Handle any new connections
                    match packet.packet_type {
                        PacketConnect => {
                            self.connections.insert(hash_sender(&src), ClientInstance::new(src, time::now().to_timespec().sec + 10)); //FIXME: Shouldn't be done here
                            self.writer_send.send((Packet::accept(self.protocol_id), src));
                            out = Some((packet, src));
                            break
                        },
                        PacketDisconnect => {
                            let hash = hash_sender(&src);
                            if self.connections.contains_key(&hash) {
                                out = Some((packet, src));
                                self.connections.remove(&hash);
                                break
                            }
                        },
                        PacketMessage => {
                            let hash = hash_sender(&src);
                            match self.connections.find_mut(&hash) {
                                Some(ref mut comms) => {
                                    out = Some((packet, src));
                                    //Update our timeout
                                    comms.timeout = time::now().to_timespec().sec + 10; //FIXME: Stop hardcoding
                                    break
                                },
                                None => ()
                            }
                        },
                        _ => ()
                    };
                },
                _ => {
                    break
                }
            };
        };
        out
    }

    pub fn cull(&mut self) {
        let mut culled = TreeMap::new();

        for (hash, connection) in self.connections.move_iter() {
            culled.insert(hash, connection);
        };

        self.connections = culled;
    }

    pub fn send_to(&mut self, packet: &Packet, addr: &SocketAddr) {
        let hashed = hash_sender(addr);
        match self.connections.find(&hashed) {
            Some(_) => self.writer_send.send((packet.clone(), addr.clone())),
            None => (),
        }
    }

    pub fn send_to_many(&mut self, packet: &Packet, addrs: &Vec<SocketAddr>) {
        for addr in addrs.iter() {
            self.send_to(packet, addr)
        }
    }

    pub fn send_to_all(&mut self, packet: &Packet) {
        for addr in self.connections.clone().values() { //FIXME: Urgh
            self.send_to(packet, &addr.addr)
        }
    }
}

impl Drop for ServerManager {

    fn drop(&mut self) {
        self.reader_send.send(Disconnect);
    }
}
<|endoftext|>


<commit_before>use std::iter::{Map, Unfold};
use std::num::{one, zero};
use std::vec;

pub trait Shrink<T: Iterator<Self>> {
    fn shrink(&self) -> T;
}

impl Shrink<vec::MoveItems<()>> for () {
    fn shrink(&self) -> vec::MoveItems<()> { (~[]).move_iter() }
}

impl Shrink<vec::MoveItems<bool>> for bool {
    fn shrink(&self) -> vec::MoveItems<bool> {
        match *self {
            true => (~[false]).move_iter(),
            false => (~[]).move_iter(),
        }
    }
}

struct OptionState<T> {
    state: Option<T>,
    started: bool,
}

impl<A: Shrink<Ia>, Ia: Iterator>
    Shrink<Unfold<'static, Option, OptionState<Ia>>>
    for Option
{
    fn shrink(&self) -> Unfold<'static, Option, OptionState<Ia>> {
        let init = match *self {
            None => None,
            Some(ref x) => Some(x.shrink()),
        };
        let st = OptionState{
            state: init,
            started: false,
        };
        Unfold::new(st, |st: &mut OptionState<Ia>| -> Option<Option> {
            match st.state {
                None => return None,
                Some(ref mut x) => {
                    if !st.started {
                        st.started = true;
                        return Some(None)
                    }
                    match x.next() {
                        None => None,
                        Some(it) => Some(Some(it)),
                    }
                }
            }
        })
    }
}

impl<A: Shrink<Ia>, B: Shrink<Ib>, Ia: Iterator, Ib: Iterator>
    Shrink<Unfold<'static, Result, Result<Ia, Ib>>>
    for Result
{
    fn shrink(&self) -> Unfold<'static, Result, Result<Ia, Ib>> {
        let init = match *self {
            Ok(ref a) => Ok(a.shrink()),
            Err(ref b) => Err(b.shrink()),
        };
        Unfold::new(init, |st: &mut Result<Ia, Ib>| -> Option<Result> {
            match *st {
                Ok(ref mut a) => match a.next() {
                    None => return None,
                    Some(a) => Some(Ok(a)),
                },
                Err(ref mut b) => match b.next() {
                    None => return None,
                    Some(b) => Some(Err(b)),
                },
            }
        })
    }
}

// Shrinking a tuple is done by shrinking the first element and generated a
// new tuple with each shrunk element from the first along with a copy of the
// given second element. Vice versa for the second element. More precisely:
//
//     shrink((a, b)) =
//         let (sa, sb) = (a.shrink(), b.shrink());
//         ~[(sa1, b), ..., (saN, b), (a, sb1), ..., (a, sbN)]
//
// I wasn't able to figure out how to do this without copying. Maybe there is
// a lifetime parameter lurking somewhere that might help.
impl<A: Shrink<Ia> + Clone, B: Shrink<Ib> + Clone,
     Ia: Iterator, Ib: Iterator>
    Shrink<Unfold<'static, (A, B), (A, B, Ia, Ib)>>
    for (A, B)
{
    fn shrink(&self) -> Unfold<'static, (A, B), (A, B, Ia, Ib)> {
        let (ref a, ref b) = *self;
        let init = (a.clone(), b.clone(), a.shrink(), b.shrink());
        Unfold::new(init, |st: &mut (A, B, Ia, Ib)| -> Option<(A, B)> {
            let (ref a, ref b, ref mut ia, ref mut ib) = *st;
            match ia.next() {
                Some(na) => Some((na, b.clone())),
                None => match ib.next() {
                    Some(nb) => Some((a.clone(), nb)),
                    None => None,
                }
            }
        })
    }
}

impl<Ia: Iterator, A: Shrink<Ia> + Clone> Shrink<vec::MoveItems<~[A]>> for ~[A] {
    fn shrink(&self) -> vec::MoveItems<~[A]> {
        let mut xs: ~[~[A]] = ~[];
        if self.len() == 0 {
            return xs.move_iter()
        }
        xs.push(~[]);

        let mut k = self.len() / 2;
        while k > 0 && k <= self.len() {
            xs.push_all_move(shuffle_vec(*self, k, self.len()));
            k = k / 2;
        }
        for (i, x) in self.iter().enumerate() {
            for sx in x.shrink() {
                let pre = self.slice_to(i).map(|x| x.clone());
                let pre = vec::append_one(pre, sx);
                xs.push(vec::append(pre, self.slice_from(i+1)))
            }
        }
        xs.move_iter()
    }
}

fn shuffle_vec(xs: &[A], k: uint, n: uint) -> ~[~[A]] {
    if k > n {
        return ~[]
    }
    let xs1 = xs.slice_to(k).map(|x| x.clone());
    let xs2 = xs.slice_from(k).map(|x| x.clone());
    if xs2.len() == 0 {
        return ~[~[]]
    }

    let cat = |x: &~[A]| {
        let mut pre = xs1.clone();
        pre.push_all_move(x.clone());
        pre
    };
    let mut more = shuffle_vec(xs2, k, n - k).map(cat);
    more.unshift(xs2);
    more
}

impl Shrink<vec::MoveItems<int>> for int {
    fn shrink(&self) -> vec::MoveItems<int> {
        shrink_signed(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<i8>> for i8 {
    fn shrink(&self) -> vec::MoveItems<i8> {
        shrink_signed(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<i16>> for i16 {
    fn shrink(&self) -> vec::MoveItems<i16> {
        shrink_signed(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<i32>> for i32 {
    fn shrink(&self) -> vec::MoveItems<i32> {
        shrink_signed(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<i64>> for i64 {
    fn shrink(&self) -> vec::MoveItems<i64> {
        shrink_signed(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<uint>> for uint {
    fn shrink(&self) -> vec::MoveItems<uint> {
        shrink_unsigned(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<u8>> for u8 {
    fn shrink(&self) -> vec::MoveItems<u8> {
        shrink_unsigned(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<u16>> for u16 {
    fn shrink(&self) -> vec::MoveItems<u16> {
        shrink_unsigned(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<u32>> for u32 {
    fn shrink(&self) -> vec::MoveItems<u32> {
        shrink_unsigned(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<u64>> for u64 {
    fn shrink(&self) -> vec::MoveItems<u64> {
        shrink_unsigned(*self).move_iter()
    }
}

impl Shrink<Map<'static, i32, f32, vec::MoveItems<i32>>> for f32 {
    fn shrink(&self) -> Map<'static, i32, f32, vec::MoveItems<i32>> {
        let it = shrink_signed(self.to_i32().unwrap()).move_iter();
        it.map(|x| x.to_f32().unwrap())
    }
}

impl Shrink<Map<'static, i64, f64, vec::MoveItems<i64>>> for f64 {
    fn shrink(&self) -> Map<'static, i64, f64, vec::MoveItems<i64>> {
        let it = shrink_signed(self.to_i64().unwrap()).move_iter();
        it.map(|x| x.to_f64().unwrap())
    }
}

// This feels incredibly gross. I hacked my way through this one.
// The cloning seems unfortunate, but maybe the compiler is smart enough
// to elide it.
fn shrink_signed<A: Clone + Ord + Signed + Mul>(x: A) -> ~[A] {
    if x.is_zero() {
        return ~[]
    }

    let two: A = one::() + one::();
    let mut xs: ~[A] = ~[zero()];
    let mut i: A = x.clone() / two;
    if i.is_negative() {
        xs.push(x.clone().abs())
    }
    while (x.clone() - i.clone()).abs() < x.clone().abs() {
        xs.push(x.clone() - i.clone());
        i = i.clone() / two;
    }
    xs
}

fn shrink_unsigned<A: Clone + Ord + Unsigned + Mul>(x: A) -> ~[A] {
    if x.is_zero() {
        return ~[]
    }

    let two: A = one::() + one::();
    let mut xs: ~[A] = ~[zero()];
    let mut i: A = x.clone() / two;
    while x.clone() - i.clone() < x.clone() {
        xs.push(x.clone() - i.clone());
        i = i.clone() / two;
    }
    xs
}

#[cfg(test)]
mod tests {
    use std::fmt::Show;
    use std::hash::Hash;
    use collections::HashSet;
    use super::Shrink;

    #[test]
    fn unit() {
        eq((), ~[]);
    }

    #[test]
    fn bools() {
        eq(false, ~[]);
        eq(true, ~[false]);
    }

    #[test]
    fn options() {
        eq(None::<()>, ~[]);
        eq(Some(false), ~[None]);
        eq(Some(true), ~[None, Some(false)]);
    }

    #[test]
    fn results() {
        // Result doesn't implement the Hash trait, so these tests
        // depends on the order of shrunk results. Ug.
        // TODO: Fix this.
        ordered_eq(Ok::<bool, ()>(true), ~[Ok(false)]);
        ordered_eq(Err::<(), bool>(true), ~[Err(false)]);
    }

    #[test]
    fn tuples() {
        eq((false, false), ~[]);
        eq((true, false), ~[(false, false)]);
        eq((true, true), ~[(false, true), (true, false)]);
    }

    #[test]
    fn ints() {
        // TODO: Test overflow?
        eq(5i, ~[0, 3, 4]);
        eq(-5i, ~[5, 0, -3, -4]);
        eq(0i, ~[]);
    }

    #[test]
    fn ints8() {
        eq(5i8, ~[0, 3, 4]);
        eq(-5i8, ~[5, 0, -3, -4]);
        eq(0i8, ~[]);
    }

    #[test]
    fn ints16() {
        eq(5i16, ~[0, 3, 4]);
        eq(-5i16, ~[5, 0, -3, -4]);
        eq(0i16, ~[]);
    }

    #[test]
    fn ints32() {
        eq(5i32, ~[0, 3, 4]);
        eq(-5i32, ~[5, 0, -3, -4]);
        eq(0i32, ~[]);
    }

    #[test]
    fn ints64() {
        eq(5i64, ~[0, 3, 4]);
        eq(-5i64, ~[5, 0, -3, -4]);
        eq(0i64, ~[]);
    }

    #[test]
    fn uints() {
        eq(5u, ~[0, 3, 4]);
        eq(0u, ~[]);
    }

    #[test]
    fn uints8() {
        eq(5u8, ~[0, 3, 4]);
        eq(0u8, ~[]);
    }

    #[test]
    fn uints16() {
        eq(5u16, ~[0, 3, 4]);
        eq(0u16, ~[]);
    }

    #[test]
    fn uints32() {
        eq(5u32, ~[0, 3, 4]);
        eq(0u32, ~[]);
    }

    #[test]
    fn uints64() {
        eq(5u64, ~[0, 3, 4]);
        eq(0u64, ~[]);
    }

    #[test]
    fn floats32() {
        ordered_eq(5f32, ~[0f32, 3f32, 4f32]);
        ordered_eq(-5f32, ~[0f32, 5f32, -3f32, -4f32]);
        ordered_eq(0f32, ~[]);
    }

    #[test]
    fn floats64() {
        ordered_eq(5f64, ~[0f64, 3f64, 4f64]);
        ordered_eq(-5f64, ~[0f64, 5f64, -3f64, -4f64]);
        ordered_eq(0f64, ~[]);
    }

    #[test]
    fn vecs() {
        eq({let it: ~[int] = ~[]; it}, ~[]);
        eq({let it: ~[~[int]] = ~[~[]]; it}, ~[~[]]);
        eq(~[1], ~[~[], ~[0]]);
        eq(~[11], ~[~[], ~[0], ~[6], ~[9], ~[10]]);
        eq(
            ~[3, 5],
            ~[~[], ~[5], ~[3], ~[0,5], ~[2,5], ~[3,0], ~[3,3], ~[3,4]]
        );
    }

    // All this jazz is for testing set equality on the results of a shrinker.
    fn eq<A: Shrink<Ia> + Eq + Show + Hash, Ia: Iterator>(s: A, v: ~[A]) {
        assert_eq!(shrunk(s), set(v))
    }
    fn shrunk<A: Shrink<Ia> + Eq + Hash, Ia: Iterator>(s: A) -> HashSet {
        set(s.shrink().to_owned_vec())
    }
    fn set(xs: ~[A]) -> HashSet {
        xs.move_iter().collect()
    }

    fn ordered_eq<A: Shrink<Ia> + Eq + Show, Ia: Iterator>(s: A, v: ~[A]) {
        assert_eq!(s.shrink().to_owned_vec(), v);
    }
}
<commit_msg>String shrinking. No char shrinking yet.<commit_after>use std::iter::{Map, Unfold};
use std::num::{one, zero};
use std::str::from_chars;
use std::vec;

pub trait Shrink<T: Iterator<Self>> {
    fn shrink(&self) -> T;
}

impl Shrink<vec::MoveItems<()>> for () {
    fn shrink(&self) -> vec::MoveItems<()> { (~[]).move_iter() }
}

impl Shrink<vec::MoveItems<bool>> for bool {
    fn shrink(&self) -> vec::MoveItems<bool> {
        match *self {
            true => (~[false]).move_iter(),
            false => (~[]).move_iter(),
        }
    }
}

struct OptionState<T> {
    state: Option<T>,
    started: bool,
}

impl<A: Shrink<Ia>, Ia: Iterator>
    Shrink<Unfold<'static, Option, OptionState<Ia>>>
    for Option
{
    fn shrink(&self) -> Unfold<'static, Option, OptionState<Ia>> {
        let init = match *self {
            None => None,
            Some(ref x) => Some(x.shrink()),
        };
        let st = OptionState{
            state: init,
            started: false,
        };
        Unfold::new(st, |st: &mut OptionState<Ia>| -> Option<Option> {
            match st.state {
                None => return None,
                Some(ref mut x) => {
                    if !st.started {
                        st.started = true;
                        return Some(None)
                    }
                    match x.next() {
                        None => None,
                        Some(it) => Some(Some(it)),
                    }
                }
            }
        })
    }
}

impl<A: Shrink<Ia>, B: Shrink<Ib>, Ia: Iterator, Ib: Iterator>
    Shrink<Unfold<'static, Result, Result<Ia, Ib>>>
    for Result
{
    fn shrink(&self) -> Unfold<'static, Result, Result<Ia, Ib>> {
        let init = match *self {
            Ok(ref a) => Ok(a.shrink()),
            Err(ref b) => Err(b.shrink()),
        };
        Unfold::new(init, |st: &mut Result<Ia, Ib>| -> Option<Result> {
            match *st {
                Ok(ref mut a) => match a.next() {
                    None => return None,
                    Some(a) => Some(Ok(a)),
                },
                Err(ref mut b) => match b.next() {
                    None => return None,
                    Some(b) => Some(Err(b)),
                },
            }
        })
    }
}

// Shrinking a tuple is done by shrinking the first element and generated a
// new tuple with each shrunk element from the first along with a copy of the
// given second element. Vice versa for the second element. More precisely:
//
//     shrink((a, b)) =
//         let (sa, sb) = (a.shrink(), b.shrink());
//         ~[(sa1, b), ..., (saN, b), (a, sb1), ..., (a, sbN)]
//
// I wasn't able to figure out how to do this without copying. Maybe there is
// a lifetime parameter lurking somewhere that might help.
impl<A: Shrink<Ia> + Clone, B: Shrink<Ib> + Clone,
     Ia: Iterator, Ib: Iterator>
    Shrink<Unfold<'static, (A, B), (A, B, Ia, Ib)>>
    for (A, B)
{
    fn shrink(&self) -> Unfold<'static, (A, B), (A, B, Ia, Ib)> {
        let (ref a, ref b) = *self;
        let init = (a.clone(), b.clone(), a.shrink(), b.shrink());
        Unfold::new(init, |st: &mut (A, B, Ia, Ib)| -> Option<(A, B)> {
            let (ref a, ref b, ref mut ia, ref mut ib) = *st;
            match ia.next() {
                Some(na) => Some((na, b.clone())),
                None => match ib.next() {
                    Some(nb) => Some((a.clone(), nb)),
                    None => None,
                }
            }
        })
    }
}

impl<Ia: Iterator, A: Shrink<Ia> + Clone>
    Shrink<vec::MoveItems<~[A]>>
    for ~[A] {
    fn shrink(&self) -> vec::MoveItems<~[A]> {
        let mut xs: ~[~[A]] = ~[];
        if self.len() == 0 {
            return xs.move_iter()
        }
        xs.push(~[]);

        let mut k = self.len() / 2;
        while k > 0 && k <= self.len() {
            xs.push_all_move(shuffle_vec(*self, k, self.len()));
            k = k / 2;
        }
        for (i, x) in self.iter().enumerate() {
            for sx in x.shrink() {
                let pre = self.slice_to(i).map(|x| x.clone());
                let pre = vec::append_one(pre, sx);
                xs.push(vec::append(pre, self.slice_from(i+1)))
            }
        }
        xs.move_iter()
    }
}

impl Shrink<vec::MoveItems<~str>> for ~str {
    fn shrink(&self) -> vec::MoveItems<~str> {
        let chars: ~[char] = self.chars().to_owned_vec();
        let mut strs: ~[~str] = ~[];
        for x in chars.shrink() {
            strs.push(from_chars(x));
        }
        strs.move_iter()
    }
}

impl Shrink<vec::MoveItems<char>> for char {
    fn shrink(&self) -> vec::MoveItems<char> { (~[]).move_iter() }
}

fn shuffle_vec(xs: &[A], k: uint, n: uint) -> ~[~[A]] {
    if k > n {
        return ~[]
    }
    let xs1 = xs.slice_to(k).map(|x| x.clone());
    let xs2 = xs.slice_from(k).map(|x| x.clone());
    if xs2.len() == 0 {
        return ~[~[]]
    }

    let cat = |x: &~[A]| {
        let mut pre = xs1.clone();
        pre.push_all_move(x.clone());
        pre
    };
    let mut more = shuffle_vec(xs2, k, n - k).map(cat);
    more.unshift(xs2);
    more
}

impl Shrink<vec::MoveItems<int>> for int {
    fn shrink(&self) -> vec::MoveItems<int> {
        shrink_signed(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<i8>> for i8 {
    fn shrink(&self) -> vec::MoveItems<i8> {
        shrink_signed(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<i16>> for i16 {
    fn shrink(&self) -> vec::MoveItems<i16> {
        shrink_signed(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<i32>> for i32 {
    fn shrink(&self) -> vec::MoveItems<i32> {
        shrink_signed(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<i64>> for i64 {
    fn shrink(&self) -> vec::MoveItems<i64> {
        shrink_signed(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<uint>> for uint {
    fn shrink(&self) -> vec::MoveItems<uint> {
        shrink_unsigned(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<u8>> for u8 {
    fn shrink(&self) -> vec::MoveItems<u8> {
        shrink_unsigned(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<u16>> for u16 {
    fn shrink(&self) -> vec::MoveItems<u16> {
        shrink_unsigned(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<u32>> for u32 {
    fn shrink(&self) -> vec::MoveItems<u32> {
        shrink_unsigned(*self).move_iter()
    }
}

impl Shrink<vec::MoveItems<u64>> for u64 {
    fn shrink(&self) -> vec::MoveItems<u64> {
        shrink_unsigned(*self).move_iter()
    }
}

impl Shrink<Map<'static, i32, f32, vec::MoveItems<i32>>> for f32 {
    fn shrink(&self) -> Map<'static, i32, f32, vec::MoveItems<i32>> {
        let it = shrink_signed(self.to_i32().unwrap()).move_iter();
        it.map(|x| x.to_f32().unwrap())
    }
}

impl Shrink<Map<'static, i64, f64, vec::MoveItems<i64>>> for f64 {
    fn shrink(&self) -> Map<'static, i64, f64, vec::MoveItems<i64>> {
        let it = shrink_signed(self.to_i64().unwrap()).move_iter();
        it.map(|x| x.to_f64().unwrap())
    }
}

// This feels incredibly gross. I hacked my way through this one.
// The cloning seems unfortunate, but maybe the compiler is smart enough
// to elide it.
fn shrink_signed<A: Clone + Ord + Signed + Mul>(x: A) -> ~[A] {
    if x.is_zero() {
        return ~[]
    }

    let two: A = one::() + one::();
    let mut xs: ~[A] = ~[zero()];
    let mut i: A = x.clone() / two;
    if i.is_negative() {
        xs.push(x.clone().abs())
    }
    while (x.clone() - i.clone()).abs() < x.clone().abs() {
        xs.push(x.clone() - i.clone());
        i = i.clone() / two;
    }
    xs
}

fn shrink_unsigned<A: Clone + Ord + Unsigned + Mul>(x: A) -> ~[A] {
    if x.is_zero() {
        return ~[]
    }

    let two: A = one::() + one::();
    let mut xs: ~[A] = ~[zero()];
    let mut i: A = x.clone() / two;
    while x.clone() - i.clone() < x.clone() {
        xs.push(x.clone() - i.clone());
        i = i.clone() / two;
    }
    xs
}

#[cfg(test)]
mod tests {
    use std::fmt::Show;
    use std::hash::Hash;
    use collections::HashSet;
    use super::Shrink;

    #[test]
    fn unit() {
        eq((), ~[]);
    }

    #[test]
    fn bools() {
        eq(false, ~[]);
        eq(true, ~[false]);
    }

    #[test]
    fn options() {
        eq(None::<()>, ~[]);
        eq(Some(false), ~[None]);
        eq(Some(true), ~[None, Some(false)]);
    }

    #[test]
    fn results() {
        // Result doesn't implement the Hash trait, so these tests
        // depends on the order of shrunk results. Ug.
        // TODO: Fix this.
        ordered_eq(Ok::<bool, ()>(true), ~[Ok(false)]);
        ordered_eq(Err::<(), bool>(true), ~[Err(false)]);
    }

    #[test]
    fn tuples() {
        eq((false, false), ~[]);
        eq((true, false), ~[(false, false)]);
        eq((true, true), ~[(false, true), (true, false)]);
    }

    #[test]
    fn ints() {
        // TODO: Test overflow?
        eq(5i, ~[0, 3, 4]);
        eq(-5i, ~[5, 0, -3, -4]);
        eq(0i, ~[]);
    }

    #[test]
    fn ints8() {
        eq(5i8, ~[0, 3, 4]);
        eq(-5i8, ~[5, 0, -3, -4]);
        eq(0i8, ~[]);
    }

    #[test]
    fn ints16() {
        eq(5i16, ~[0, 3, 4]);
        eq(-5i16, ~[5, 0, -3, -4]);
        eq(0i16, ~[]);
    }

    #[test]
    fn ints32() {
        eq(5i32, ~[0, 3, 4]);
        eq(-5i32, ~[5, 0, -3, -4]);
        eq(0i32, ~[]);
    }

    #[test]
    fn ints64() {
        eq(5i64, ~[0, 3, 4]);
        eq(-5i64, ~[5, 0, -3, -4]);
        eq(0i64, ~[]);
    }

    #[test]
    fn uints() {
        eq(5u, ~[0, 3, 4]);
        eq(0u, ~[]);
    }

    #[test]
    fn uints8() {
        eq(5u8, ~[0, 3, 4]);
        eq(0u8, ~[]);
    }

    #[test]
    fn uints16() {
        eq(5u16, ~[0, 3, 4]);
        eq(0u16, ~[]);
    }

    #[test]
    fn uints32() {
        eq(5u32, ~[0, 3, 4]);
        eq(0u32, ~[]);
    }

    #[test]
    fn uints64() {
        eq(5u64, ~[0, 3, 4]);
        eq(0u64, ~[]);
    }

    #[test]
    fn floats32() {
        ordered_eq(5f32, ~[0f32, 3f32, 4f32]);
        ordered_eq(-5f32, ~[0f32, 5f32, -3f32, -4f32]);
        ordered_eq(0f32, ~[]);
    }

    #[test]
    fn floats64() {
        ordered_eq(5f64, ~[0f64, 3f64, 4f64]);
        ordered_eq(-5f64, ~[0f64, 5f64, -3f64, -4f64]);
        ordered_eq(0f64, ~[]);
    }

    #[test]
    fn vecs() {
        eq({let it: ~[int] = ~[]; it}, ~[]);
        eq({let it: ~[~[int]] = ~[~[]]; it}, ~[~[]]);
        eq(~[1], ~[~[], ~[0]]);
        eq(~[11], ~[~[], ~[0], ~[6], ~[9], ~[10]]);
        eq(
            ~[3, 5],
            ~[~[], ~[5], ~[3], ~[0,5], ~[2,5], ~[3,0], ~[3,3], ~[3,4]]
        );
    }

    #[test]
    fn chars() {
        eq('a', ~[]);
    }

    #[test]
    fn strs() {
        eq(~"", ~[]);
        eq(~"A", ~[~""]);
        eq(~"ABC", ~[~"", ~"AB", ~"BC", ~"AC"]);
    }

    // All this jazz is for testing set equality on the results of a shrinker.
    fn eq<A: Shrink<Ia> + Eq + Show + Hash, Ia: Iterator>(s: A, v: ~[A]) {
        assert_eq!(shrunk(s), set(v))
    }
    fn shrunk<A: Shrink<Ia> + Eq + Hash, Ia: Iterator>(s: A) -> HashSet {
        set(s.shrink().to_owned_vec())
    }
    fn set(xs: ~[A]) -> HashSet {
        xs.move_iter().collect()
    }

    fn ordered_eq<A: Shrink<Ia> + Eq + Show, Ia: Iterator>(s: A, v: ~[A]) {
        assert_eq!(s.shrink().to_owned_vec(), v);
    }
}
<|endoftext|>


<commit_before>extern crate mongodb;
extern crate time;
extern crate serde;
extern crate serde_json;

use super::worker_pool;
use std::thread;
use std::sync::Arc;
use self::serde_json::Value;

use super::cove;

///
/// Holds a show object
///
pub struct Program<'a> {
    pub data: &'a str,
    pub program_id: u64
}

///
/// Does the actual ingestion
///
pub fn ingest(first_time: bool) {
    let total_programs = get_total_programs();
    let mut updated_date = String::from("");

    if !first_time {
        let current_time = time::now_utc();
        let updated_date = format!("{}-{}-{}", current_time.tm_year, current_time.tm_mon, current_time.tm_mday);
    }

    for i in (0..total_programs).step_by(200) {
        println!("Processing program set {} of {}", i, total_programs);
        let mut worker_pool = worker_pool::WorkerPool::new();
        let updated_date = Arc::new(updated_date);

        worker_pool.join_handles.push(thread::spawn(move || {
            let programs = get_programs(i);

            for program in programs {
                let total_videos = get_video_count_for_program(&program);
                let mut worker_pool = worker_pool::WorkerPool::new();
                let program = Arc::new(program);

                for j in (0..total_videos).step_by(200) {
                    println!("Processing video set {} of {}", j, total_videos);
                    let shared_program = program.clone();
                    let shared_updated_date = updated_date.clone();

                    worker_pool.join_handles.push(thread::spawn(move || {
                        get_videos(&shared_updated_date, j, &shared_program);
                    }));
                }

                worker_pool.wait_for_children();
            }
        }));

        worker_pool.wait_for_children();
    }
}

///
/// Gets the total programs to break them up
///
fn get_total_programs() -> u64 {
    cove::video_api("programs", vec![]).as_object().unwrap().get("count").unwrap().as_u64().unwrap()
}

///
/// Gets all the shows from COVE
///
fn get_programs<'a>(start_index: u64) -> Vec<Program<'a>> {
    let cove_data = cove::video_api("programs", vec![["limit_start", start_index.to_string().as_str()]]);
    let programs = serde_json::from_value(*cove_data.as_object().unwrap().get("results").unwrap()).unwrap();
    let programs_data = vec![];

    for program in programs {
        let program_uri = program.as_object().unwrap().get("resource_uri").unwrap().as_str();
        let program_id = program_uri.split("/")[3].to_u64();

        // Do the mongo insert.

        programs_data.push(Program {data: program, program_id: program_id});
    }

    programs_data
}

///
/// Gets the total videos for a program so they can be chunked
///
fn get_video_count_for_program<'a>(program: &Program) -> u64 {
    cove::video_api("videos", vec![["program_id", program.program_id]]).as_object().unwrap().get("count").unwrap().as_u64().unwrap()
}

///
/// Gets all videos from COVE for a program, 200 at a time
///
fn get_videos<'a>(updated_date: &Arc<String>, start_index: u64, program: &Arc<Program>) {
    let params = vec![["program_id", program.program_id], ["limit_start", start_index.as_str()]];

    if updated_date != "" {
        params.push(["filter_record_last_updated_datetime__gt", updated_date]);
    }

    let cove_data = cove::video_api("videos", params);
    let videos = cove_data.as_object().unwrap().get("results").unwrap();

    for video in videos {

        // Do the mongo insert.
    }
}<commit_msg>A few more compile borrow errors to fix<commit_after>extern crate mongodb;
extern crate time;
extern crate serde;
extern crate serde_json;

use super::worker_pool;
use std::thread;
use std::sync::Arc;
use self::serde_json::{Value, Map};

use super::cove;

///
/// Holds a show object
///
pub struct Program<'a> {
    pub data: &'a str,
    pub program_id: u64
}

///
/// Does the actual ingestion
///
pub fn ingest(first_time: bool) {
    let total_programs = get_total_programs();
    let mut updated_date = Arc::new(String::from(""));

    if !first_time {
        let current_time = time::now_utc();
        updated_date = Arc::new(format!("{}-{}-{}", current_time.tm_year, current_time.tm_mon, current_time.tm_mday));
    }

    for i in (0..total_programs).step_by(200) {
        let shared_updated_date = updated_date.clone();
        println!("Processing program set {} of {}", i, total_programs);
        let mut worker_pool = worker_pool::WorkerPool::new();

        worker_pool.join_handles.push(thread::spawn(move || {
            let programs = get_programs(i);

            for program in programs {
                let total_videos = get_video_count_for_program(&program);
                let mut worker_pool = worker_pool::WorkerPool::new();
                let program = Arc::new(program);

                for j in (0..total_videos).step_by(200) {
                    println!("Processing video set {} of {}", j, total_videos);
                    let shared_program = program.clone();
                    let shared_updated_date = shared_updated_date.clone();

                    worker_pool.join_handles.push(thread::spawn(move || {
                        get_videos(&shared_updated_date, j, &shared_program);
                    }));
                }

                worker_pool.wait_for_children();
            }
        }));

        worker_pool.wait_for_children();
    }
}

///
/// Gets the total programs to break them up
///
fn get_total_programs() -> u64 {
    cove::video_api("programs", vec![]).as_object().unwrap().get("count").unwrap().as_u64().unwrap()
}

///
/// Gets all the shows from COVE
///
fn get_programs<'a>(start_index: u64) -> Vec<Program<'a>> {
    let cove_data = cove::video_api("programs", vec![["limit_start", start_index.to_string().as_str()]]);
    let programs: &Vec<Value> = cove_data.as_object().unwrap().get("results").unwrap().as_array().unwrap();
    let mut programs_data = vec![];

    for program in programs {
        let program_uri = program.as_object().unwrap().get("resource_uri").unwrap().as_str().unwrap();
        let program_id: u64 = program_uri.split("/").nth(3).unwrap().parse().unwrap();

        // Do the mongo insert.

        programs_data.push(Program {data: program.as_str().unwrap().clone(), program_id: program_id});
    }

    programs_data
}

///
/// Gets the total videos for a program so they can be chunked
///
fn get_video_count_for_program<'a>(program: &Program) -> u64 {
    cove::video_api("videos", vec![["program_id", program.program_id.to_string().as_str()]]).as_object().unwrap().get("count").unwrap().as_u64().unwrap()
}

///
/// Gets all videos from COVE for a program, 200 at a time
///
fn get_videos<'a>(updated_date: &Arc<String>, start_index: u64, program: &Arc<Program>) {
    let program_id = program.program_id.to_string().as_str();
    let mut params = vec![["program_id", program_id], ["limit_start", start_index.to_string().as_str()]];

    if updated_date.as_str() == "" {
        params.push(["filter_record_last_updated_datetime__gt", updated_date.as_str()]);
    }

    let cove_data = cove::video_api("videos", params);
    let videos:&Vec<Value> = cove_data.as_object().unwrap().get("results").unwrap().as_array().unwrap();

    for video in videos {

        // Do the mongo insert.
    }
}<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::rc::Rc;

use super::super::target::bytecode::layout::{Function, Instruction, Reg, Unit};

use super::value::{NativeFunction, Value};

// Frames can live outside of the stack (eg. closures) and can be mutated from
// places outside the stack (again, closures), therefore we need referencing
// counting (`Rc`) and interior mutability (`RefCell`).
type SharedFrame = Rc<RefCell<Frame>>;

// The first three fields should *not* be changed after the frame
// is initialized.
struct Frame {
    unit: Rc<Unit>,
    function: Rc<Function>,
    lexical_parent: Option<SharedFrame>,
    return_register: Reg,
    registers: Vec<Value>,
    locals: Vec<Value>,
    current_block: usize,
    current_address: usize,
}

impl Frame {
    fn new(
        unit: Rc<Unit>,
        function: Rc<Function>,
        lexical_parent: Option<SharedFrame>,
        return_register: Reg,
    ) -> Self {
        let registers = function.registers;
        let locals = function.locals;
        Self {
            unit,
            function,
            lexical_parent,
            return_register,
            registers: vec![Value::Null; registers as usize],
            locals: vec![Value::Null; locals as usize],
            current_block: 0,
            current_address: 0,
        }
    }

    #[inline]
    fn current(&self) -> Instruction {
        let block = &self.function.basic_blocks[self.current_block];
        block.instructions[self.current_address].clone()
    }

    #[inline]
    fn offset_register(index: Reg) -> usize {
        (index as usize) - 1
    }

    fn advance(&mut self) {
        self.current_address += 1;
    }

    fn read_register(&self, index: Reg) -> Value {
        self.registers[Frame::offset_register(index)].clone()
    }

    fn write_register(&mut self, index: Reg, value: Value) {
        if index == 0 {
            return;
        }
        self.registers[Frame::offset_register(index)] = value;
    }

    fn get_local(&self, index: u8) -> Value {
        self.locals[index as usize].clone()
    }

    fn get_local_lexical(&self, name: &String) -> Value {
        let index = self
            .function
            .locals_names
            .iter()
            .position(|local| local == name);
        if let Some(index) = index {
            self.locals[index].clone()
        } else {
            if let Some(ref lexical_parent) = self.lexical_parent {
                lexical_parent.borrow().get_local_lexical(name)
            } else {
                panic!("Out of parents")
            }
        }
    }

    fn set_local(&mut self, index: u8, value: Value) {
        self.locals[index as usize] = value;
    }
}

pub struct Vm {
    stack: Vec<SharedFrame>,
}

enum Action {
    // Advance to the next instruction.
    Advance,
    // Execute a dynamic function call (ie. push onto the stack).
    CallDynamic(Reg, Value, Vec<Value>),
    CallNative(Reg, NativeFunction, Vec<Value>),
    Return(Value),
}

fn prelude_println(arguments: Vec<Value>) -> Value {
    if let Some(argument) = arguments.first() {
        match argument {
            Value::Integer(value) => println!("{}", value),
            _ => unreachable!(),
        }
    };
    Value::Null
}

impl Vm {
    pub fn run_main(unit: Rc<Unit>) {
        let prelude = Vm::build_prelude();
        let main_function = Rc::new(unit.functions[0].clone());
        let frame = Frame::new(unit, main_function, Some(prelude), 0);
        let mut vm = Self {
            stack: vec![Rc::new(RefCell::new(frame))],
        };
        vm.run();
    }

    fn build_prelude() -> SharedFrame {
        let prelude_unit = Unit {
            functions: vec![Function {
                id: 0,
                name: "prelude".to_string(),
                registers: 0,
                basic_blocks: vec![],
                locals: 1,
                locals_names: vec!["println".to_string()],
            }],
        };
        let prelude_main_function = prelude_unit.functions[0].clone();
        let mut prelude = Frame::new(
            Rc::new(prelude_unit),
            Rc::new(prelude_main_function),
            None,
            0,
        );
        prelude.set_local(
            0,
            Value::NativeFunction(NativeFunction::new(Rc::new(prelude_println))),
        );
        Rc::new(RefCell::new(prelude))
    }

    fn run(&mut self) {
        loop {
            let top = self.stack.last().expect("Empty stack");
            let instruction = top.borrow().current();
            let action = Vm::dispatch(&instruction, &mut top.borrow_mut());
            match action {
                Action::Advance => top.borrow_mut().advance(),
                // Due to borrow-checker rules we cannot have the side effects
                // of a call happen within `dispatch`.
                Action::CallDynamic(return_register, target, arguments) => {
                    let (unit, function) = target.dynamic_function().unwrap();
                    let frame = Rc::new(RefCell::new(Frame::new(
                        unit,
                        function,
                        None,
                        return_register,
                    )));
                    self.stack.push(frame)
                }
                Action::CallNative(return_register, target, arguments) => {
                    let result = target.call(arguments);
                    let mut top = top.borrow_mut();
                    top.write_register(return_register, result);
                    top.advance();
                }
                Action::Return(value) => {
                    let popped = self.stack.pop().expect("Empty stack");
                    let return_register = popped.borrow().return_register;
                    match self.stack.last() {
                        Some(top) => {
                            let mut top = top.borrow_mut();
                            top.write_register(return_register, value);
                            top.advance();
                        }
                        // Returning from the top frame.
                        None => return,
                    }
                }
                _ => unreachable!(),
            }
        }
    }

    // Decodes the instruction, applies any frame-level side effects, and
    // returns an `Action` describing stack/VM-level side effects.
    #[inline]
    fn dispatch(instruction: &Instruction, top: &mut Frame) -> Action {
        match instruction {
            Instruction::GetLocal(lval, index) => {
                top.write_register(*lval, top.get_local(*index));
                Action::Advance
            }
            Instruction::GetLocalLexical(lval, name) => {
                top.write_register(*lval, top.get_local_lexical(name));
                Action::Advance
            }
            Instruction::SetLocal(index, rval) => {
                top.set_local(*index, top.read_register(*rval));
                Action::Advance
            }
            Instruction::MakeInteger(lval, value) => {
                top.write_register(*lval, Value::Integer(*value));
                Action::Advance
            }
            Instruction::Call(lval, target, arguments) => {
                let target = top.read_register(*target);
                let arguments = arguments
                    .iter()
                    .map(|argument| top.read_register(*argument))
                    .collect::<Vec<Value>>();
                match target {
                    Value::DynamicFunction(_, _) => Action::CallDynamic(*lval, target, arguments),
                    Value::NativeFunction(native_function) => {
                        Action::CallNative(*lval, native_function, arguments)
                    }
                    _ => panic!("Cannot call"),
                }
            }
            Instruction::ReturnNull => Action::Return(Value::Null),
            _ => panic!("Cannot dispatch: {:?}", instruction),
        }
    }
}
<commit_msg>Update documentation comments<commit_after>use std::cell::RefCell;
use std::rc::Rc;

use super::super::target::bytecode::layout::{Function, Instruction, Reg, Unit};

use super::value::{NativeFunction, Value};

// Frames can live outside of the stack (eg. closures) and can be mutated from
// places outside the stack (again, closures), therefore we need reference
// counting (`Rc`) and interior mutability (`RefCell`).
type SharedFrame = Rc<RefCell<Frame>>;

// The first three fields should *not* be changed after the frame
// is initialized.
struct Frame {
    unit: Rc<Unit>,
    function: Rc<Function>,
    lexical_parent: Option<SharedFrame>,
    return_register: Reg,
    registers: Vec<Value>,
    locals: Vec<Value>,
    current_block: usize,
    current_address: usize,
}

impl Frame {
    fn new(
        unit: Rc<Unit>,
        function: Rc<Function>,
        lexical_parent: Option<SharedFrame>,
        return_register: Reg,
    ) -> Self {
        let registers = function.registers;
        let locals = function.locals;
        Self {
            unit,
            function,
            lexical_parent,
            return_register,
            registers: vec![Value::Null; registers as usize],
            locals: vec![Value::Null; locals as usize],
            current_block: 0,
            current_address: 0,
        }
    }

    #[inline]
    fn current(&self) -> Instruction {
        let block = &self.function.basic_blocks[self.current_block];
        block.instructions[self.current_address].clone()
    }

    #[inline]
    fn offset_register(index: Reg) -> usize {
        (index as usize) - 1
    }

    fn advance(&mut self) {
        self.current_address += 1;
    }

    fn read_register(&self, index: Reg) -> Value {
        self.registers[Frame::offset_register(index)].clone()
    }

    fn write_register(&mut self, index: Reg, value: Value) {
        if index == 0 {
            return;
        }
        self.registers[Frame::offset_register(index)] = value;
    }

    fn get_local(&self, index: u8) -> Value {
        self.locals[index as usize].clone()
    }

    fn get_local_lexical(&self, name: &String) -> Value {
        let index = self
            .function
            .locals_names
            .iter()
            .position(|local| local == name);
        if let Some(index) = index {
            self.locals[index].clone()
        } else {
            if let Some(ref lexical_parent) = self.lexical_parent {
                lexical_parent.borrow().get_local_lexical(name)
            } else {
                panic!("Out of parents")
            }
        }
    }

    fn set_local(&mut self, index: u8, value: Value) {
        self.locals[index as usize] = value;
    }
}

pub struct Vm {
    stack: Vec<SharedFrame>,
}

enum Action {
    // Advance to the next instruction.
    Advance,
    // Execute a dynamic function call (ie. push onto the stack).
    CallDynamic(Reg, Value, Vec<Value>),
    CallNative(Reg, NativeFunction, Vec<Value>),
    Return(Value),
}

fn prelude_println(arguments: Vec<Value>) -> Value {
    if let Some(argument) = arguments.first() {
        match argument {
            Value::Integer(value) => println!("{}", value),
            _ => unreachable!(),
        }
    };
    Value::Null
}

impl Vm {
    pub fn run_main(unit: Rc<Unit>) {
        let prelude = Vm::build_prelude();
        let main_function = Rc::new(unit.functions[0].clone());
        let frame = Frame::new(unit, main_function, Some(prelude), 0);
        let mut vm = Self {
            stack: vec![Rc::new(RefCell::new(frame))],
        };
        vm.run();
    }

    fn build_prelude() -> SharedFrame {
        let prelude_unit = Unit {
            functions: vec![Function {
                id: 0,
                name: "prelude".to_string(),
                registers: 0,
                basic_blocks: vec![],
                locals: 1,
                locals_names: vec!["println".to_string()],
            }],
        };
        let prelude_main_function = prelude_unit.functions[0].clone();
        let mut prelude = Frame::new(
            Rc::new(prelude_unit),
            Rc::new(prelude_main_function),
            None,
            0,
        );
        prelude.set_local(
            0,
            Value::NativeFunction(NativeFunction::new(Rc::new(prelude_println))),
        );
        Rc::new(RefCell::new(prelude))
    }

    fn run(&mut self) {
        loop {
            let top = self.stack.last().expect("Empty stack");
            let instruction = top.borrow().current();
            let action = Vm::dispatch(&instruction, &mut top.borrow_mut());
            // Apply side effects which will impact the whole VM. We isolated
            // frame-level side effects inside of `Vm::dispatch` to make the
            // borrow-checker happy.
            match action {
                Action::Advance => top.borrow_mut().advance(),
                // Due to borrow-checker rules we cannot have the side effects
                // of a call happen within `dispatch`.
                Action::CallDynamic(return_register, target, arguments) => {
                    let (unit, function) = target.dynamic_function().unwrap();
                    let frame = Rc::new(RefCell::new(Frame::new(
                        unit,
                        function,
                        None,
                        return_register,
                    )));
                    self.stack.push(frame)
                }
                Action::CallNative(return_register, target, arguments) => {
                    let result = target.call(arguments);
                    let mut top = top.borrow_mut();
                    top.write_register(return_register, result);
                    top.advance();
                }
                Action::Return(value) => {
                    let popped = self.stack.pop().expect("Empty stack");
                    let return_register = popped.borrow().return_register;
                    match self.stack.last() {
                        Some(top) => {
                            let mut top = top.borrow_mut();
                            top.write_register(return_register, value);
                            top.advance();
                        }
                        // Returning from the top frame.
                        None => return,
                    }
                }
                _ => unreachable!(),
            }
        }
    }

    // Decodes the instruction, applies any frame-level side effects, and
    // returns an `Action` describing stack/VM-level side effects.
    #[inline]
    fn dispatch(instruction: &Instruction, top: &mut Frame) -> Action {
        match instruction {
            Instruction::GetLocal(lval, index) => {
                top.write_register(*lval, top.get_local(*index));
                Action::Advance
            }
            Instruction::GetLocalLexical(lval, name) => {
                top.write_register(*lval, top.get_local_lexical(name));
                Action::Advance
            }
            Instruction::SetLocal(index, rval) => {
                top.set_local(*index, top.read_register(*rval));
                Action::Advance
            }
            Instruction::MakeInteger(lval, value) => {
                top.write_register(*lval, Value::Integer(*value));
                Action::Advance
            }
            Instruction::Call(lval, target, arguments) => {
                let target = top.read_register(*target);
                let arguments = arguments
                    .iter()
                    .map(|argument| top.read_register(*argument))
                    .collect::<Vec<Value>>();
                match target {
                    Value::DynamicFunction(_, _) => Action::CallDynamic(*lval, target, arguments),
                    Value::NativeFunction(native_function) => {
                        Action::CallNative(*lval, native_function, arguments)
                    }
                    _ => panic!("Cannot call"),
                }
            }
            Instruction::ReturnNull => Action::Return(Value::Null),
            _ => panic!("Cannot dispatch: {:?}", instruction),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementations that just need to read from a file
use crate::util_libc::{last_os_error, open_readonly, sys_fill_exact, LazyFd};
use crate::Error;

#[cfg(target_os = "redox")]
const FILE_PATH: &str = "rand:\0";
#[cfg(any(
    target_os = "dragonfly",
    target_os = "emscripten",
    target_os = "haiku",
    target_os = "macos",
    target_os = "solaris",
    target_os = "illumos"
))]
const FILE_PATH: &str = "/dev/random\0";

pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
    static FD: LazyFd = LazyFd::new();
    let fd = FD.init(init_file).ok_or_else(last_os_error)?;
    let read = |buf: &mut [u8]| unsafe { libc::read(fd, buf.as_mut_ptr() as *mut _, buf.len()) };

    if cfg!(target_os = "emscripten") {
        // `Crypto.getRandomValues` documents `dest` should be at most 65536 bytes.
        for chunk in dest.chunks_mut(65536) {
            sys_fill_exact(chunk, read)?;
        }
    } else {
        sys_fill_exact(dest, read)?;
    }
    Ok(())
}

cfg_if! {
    if #[cfg(any(target_os = "android", target_os = "linux"))] {
        fn init_file() -> Option<libc::c_int> {
            // Poll /dev/random to make sure it is ok to read from /dev/urandom.
            let mut pfd = libc::pollfd {
                fd: unsafe { open_readonly("/dev/random\0")? },
                events: libc::POLLIN,
                revents: 0,
            };

            let ret = loop {
                // A negative timeout means an infinite timeout.
                let res = unsafe { libc::poll(&mut pfd, 1, -1) };
                if res == 1 {
                    break unsafe { open_readonly("/dev/urandom\0") };
                } else if res < 0 {
                    let e = last_os_error().raw_os_error();
                    if e == Some(libc::EINTR) || e == Some(libc::EAGAIN) {
                        continue;
                    }
                }
                // We either hard failed, or poll() returned the wrong pfd.
                break None;
            };
            unsafe { libc::close(pfd.fd) };
            ret
        }
    } else {
        fn init_file() -> Option<libc::c_int> {
            unsafe { open_readonly(FILE_PATH) }
        }
    }
}
<commit_msg>use_file: Remove use of spin-locks<commit_after>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementations that just need to read from a file
use crate::util::LazyUsize;
use crate::util_libc::{open_readonly, sys_fill_exact};
use crate::Error;
use core::cell::UnsafeCell;
use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};

#[cfg(target_os = "redox")]
const FILE_PATH: &str = "rand:\0";
#[cfg(any(
    target_os = "dragonfly",
    target_os = "emscripten",
    target_os = "haiku",
    target_os = "macos",
    target_os = "solaris",
    target_os = "illumos"
))]
const FILE_PATH: &str = "/dev/random\0";
#[cfg(any(target_os = "android", target_os = "linux"))]
const FILE_PATH: &str = "/dev/urandom\0";

pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
    let fd = get_rng_fd()?;
    let read = |buf: &mut [u8]| unsafe { libc::read(fd, buf.as_mut_ptr() as *mut _, buf.len()) };

    if cfg!(target_os = "emscripten") {
        // `Crypto.getRandomValues` documents `dest` should be at most 65536 bytes.
        for chunk in dest.chunks_mut(65536) {
            sys_fill_exact(chunk, read)?;
        }
    } else {
        sys_fill_exact(dest, read)?;
    }
    Ok(())
}

// Returns the file descriptor for the device file used to retrieve random
// bytes. The file will be opened exactly once. All successful calls will
// return the same file descriptor. This file descriptor is never closed.
fn get_rng_fd() -> Result<libc::c_int, Error> {
    static FD: AtomicUsize = AtomicUsize::new(LazyUsize::UNINIT);
    fn get_fd() -> Option<libc::c_int> {
        match FD.load(Relaxed) {
            LazyUsize::UNINIT => None,
            val => Some(val as libc::c_int),
        }
    }

    // Use double-checked locking to avoid acquiring the lock if possible.
    if let Some(fd) = get_fd() {
        return Ok(fd);
    }

    // SAFETY: We use the mutex only in this method, and we always unlock it
    // before returning, making sure we don't violate the pthread_mutex_t API.
    static MUTEX: Mutex = Mutex::new();
    unsafe { MUTEX.lock() };
    let _guard = DropGuard(|| unsafe { MUTEX.unlock() });

    if let Some(fd) = get_fd() {
        return Ok(fd);
    }

    // On Linux, /dev/urandom might return insecure values.
    #[cfg(any(target_os = "android", target_os = "linux"))]
    wait_until_rng_ready()?;

    let fd = unsafe { open_readonly(FILE_PATH)? };
    // The fd always fits in a usize without conflicting with UNINIT.
    debug_assert!(fd >= 0 && (fd as usize) < LazyUsize::UNINIT);
    FD.store(fd as usize, Relaxed);

    Ok(fd)
}

// Succeeds once /dev/urandom is safe to read from
#[cfg(any(target_os = "android", target_os = "linux"))]
fn wait_until_rng_ready() -> Result<(), Error> {
    // Poll /dev/random to make sure it is ok to read from /dev/urandom.
    let fd = unsafe { open_readonly("/dev/random\0")? };
    let mut pfd = libc::pollfd {
        fd,
        events: libc::POLLIN,
        revents: 0,
    };
    let _guard = DropGuard(|| unsafe {
        libc::close(fd);
    });

    loop {
        // A negative timeout means an infinite timeout.
        let res = unsafe { libc::poll(&mut pfd, 1, -1) };
        if res >= 0 {
            assert_eq!(res, 1); // We only used one fd, and cannot timeout.
            return Ok(());
        }
        let err = crate::util_libc::last_os_error();
        match err.raw_os_error() {
            Some(libc::EINTR) | Some(libc::EAGAIN) => continue,
            _ => return Err(err),
        }
    }
}

struct Mutex(UnsafeCell<libc::pthread_mutex_t>);

impl Mutex {
    const fn new() -> Self {
        Self(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER))
    }
    unsafe fn lock(&self) {
        let r = libc::pthread_mutex_lock(self.0.get());
        debug_assert_eq!(r, 0);
    }
    unsafe fn unlock(&self) {
        let r = libc::pthread_mutex_unlock(self.0.get());
        debug_assert_eq!(r, 0);
    }
}

unsafe impl Sync for Mutex {}

struct DropGuard<F: FnMut()>(F);

impl<F: FnMut()> Drop for DropGuard<F> {
    fn drop(&mut self) {
        self.0()
    }
}
<|endoftext|>


<commit_before>use std::path::Path;
use std::fs::File;
use std::io::BufReader;
use std::io::Read;
use std::ascii::AsciiExt;
use std::str;

use std::sync::Mutex;

lazy_static! {
    static ref GLOBAL_BUFFER: Mutex<Buffer> = Mutex::new(Buffer::new());
}

pub struct Buffer {
    strs: Vec<String>
}

impl Buffer {
    pub fn new() -> Buffer { Buffer { strs: Vec::new() } }

    pub fn insert(&mut self, s: String) {
        self.strs.push(s)
    }
    pub fn get_by_index(&self, ix: usize) -> String {
        self.strs[ix].clone()
    }
}

pub fn strings_from_file<'a>(path: &str) -> Result<String, &'a str> {
    let fs_result = File::open(path);
    match fs_result {
        Ok(file) => {
            let mut reader = BufReader::new(file);
            let mut contents = String::new();
            let read_result = reader.read_to_string(&mut contents);
            match read_result {
                Ok(_) => {
                    Result::Ok(contents.to_string())
                },
                Err(error) => {
                    print!("{:?}", error);
                    Result::Err("Could not read file")
                }
            }
        },
        Err(error) => {
            print!("{:?}", error);
            Result::Err("Could not open file")
        }
    }
}

fn bytes_to_strings(bytes: &[u8]) {
    let min_consecutive_chars = 3;
    let mut guard = GLOBAL_BUFFER.lock().unwrap();
    if bytes.is_ascii() {
        let result = str::from_utf8(&bytes);
        match result {
            Ok(string) => {
                guard.insert(string.to_string());
            },
            Err(_) => {}
        }

    }
}

#[test]
fn it_reads_strings_from_files() {
    let expected = Result::Ok("Hello, world.".to_string());
    assert_eq!(strings_from_file("./src/hello.txt"), expected);
}

#[test]
fn it_raises_if_no_file_exists() {
    let actual = strings_from_file("no such file");
    let expected = Result::Err("Could not open file");
    assert_eq!(expected, actual)
}

#[test]
fn it_pushes_strings_to_global_buffer() {
    bytes_to_strings("hi".as_bytes());
    let expected = "hi";
    let mut guard = GLOBAL_BUFFER.lock().unwrap();
    let actual = guard.get_by_index(0);
    assert_eq!(expected, actual);
}<commit_msg>passing read test with buffer<commit_after>use std::path::Path;
use std::fs::File;
use std::io::BufReader;
use std::io::Read;
use std::io::Write;
use std::io::Cursor;
use std::ascii::AsciiExt;
use std::str;

use std::sync::Mutex;

lazy_static! {
    static ref GLOBAL_BUFFER: Mutex<Buffer> = Mutex::new(Buffer::new());
}

pub struct Buffer {
    strs: Vec<String>
}

impl Buffer {
    pub fn new() -> Buffer { Buffer { strs: Vec::new() } }

    pub fn insert(&mut self, s: String) {
        self.strs.push(s)
    }
    pub fn get_by_index(&self, ix: usize) -> String {
        self.strs[ix].clone()
    }
}

pub fn strings_from_file<'a>(path: &str) -> Result<String, &'a str> {
    let fs_result = File::open(path);
    match fs_result {
        Ok(file) => {
            let mut reader = BufReader::new(file);
            let mut contents = String::new();
            let read_result = reader.read_to_string(&mut contents);
            match read_result {
                Ok(_) => {
                    Result::Ok(contents.to_string())
                },
                Err(error) => {
                    print!("{:?}", error);
                    Result::Err("Could not read file")
                }
            }
        },
        Err(error) => {
            print!("{:?}", error);
            Result::Err("Could not open file")
        }
    }
}

fn bytes_to_strings<W: Write>(bytes: &[u8], w:  &mut W) {
    let min_consecutive_chars = 3;
    let mut current_bytes : Vec<u8> = Vec::new();

    for b in bytes {
        if b.is_ascii() {
            current_bytes.push(*b);
        }
        else  {
            if current_bytes.len() >= min_consecutive_chars {
                let result = str::from_utf8(&current_bytes);
                match result {
                    Ok(string) => {
                        println!("Found string: {}", string.clone());
                        writeln!(w, "{}", string);
                    },
                    Err(_) => {}
                }
            }
            current_bytes.truncate(0)
        }
    }
    if current_bytes.len() >= min_consecutive_chars {
        let result = str::from_utf8(&current_bytes);
        match result {
            Ok(string) => {
                println!("Found string: {}", string.clone());
                writeln!(w, "{}", string);
            },
            Err(_) => {}
        }
    }
}

#[test]
fn it_reads_strings_from_files() {
    let expected = Result::Ok("Hello, world.".to_string());
    assert_eq!(strings_from_file("./src/hello.txt"), expected);
}

#[test]
fn it_raises_if_no_file_exists() {
    let actual = strings_from_file("no such file");
    let expected = Result::Err("Could not open file");
    assert_eq!(expected, actual)
}

#[test]
fn it_writes_to_the_buffer() {
    let mut cursor = Cursor::new(Vec::new());
    bytes_to_strings("hello".as_bytes(), &mut cursor);
    let expected = "hello\n";
    let vec = cursor.into_inner();
    let actual = String::from_utf8(vec).unwrap();
    assert_eq!(expected, actual);
}<|endoftext|>


<commit_before>//! This is the Buffer module for Xtensis.

// This file is part of Xtensis.

// This is the Xtensis text editor; it edits text.
// Copyright (C) 2016-2017  The Xtensis Developers

// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see
// <http://www.gnu.org/licenses/>.

extern crate slog;
extern crate slog_scope;

use std::path::PathBuf;

use server::gapbuffer::GapBuffer;
use utils::uuid;
use slog::Logger;

/// Struct for a Buffer in Xtensis
/// This stores metadata about a buffer.
#[derive(Debug)]
pub struct Buffer {
    /// UUID of a buffer.
    pub buf_uuid: String,
    /// File path of a buffer.
    pub file_path: Option<PathBuf>,
    /// Active status of a buffer.
    pub active: bool,
    /// Temporary status of a buffer.
    pub temporary: bool,
    /// If a buffer is r/o.
    /// If this is `true`, then r/w is `false.`
    /// Likewise, if this is `false`, then r/w is `true.
    pub read_only: bool,
    /// Major mode of a buffer
    pub major_mode: &'static str,
    /// Vector of Minor modes in a buffer
    pub minor_modes: Vec<&'static str>,
    /// Dirty status of a buffer
    pub dirty: bool,
    /// Contents of a buffer.
    pub text: GapBuffer<u8>,
    /// Logger of a buffer.
    pub logger: Logger,
}

impl Buffer {
    /// Return a new instance of `Buffer`.
    pub fn new() -> Buffer {
        let buf_logger = slog_scope::logger().new(o!("module" =>
                                                     "buffer"));

        slog_scope::scope(buf_logger.clone(), || {
            warn!(buf_logger, "The buffer is being created!!");
        });

        trace!(buf_logger, "Initialising logger..");
        Buffer {
            buf_uuid: uuid::get_uuid_buffer(),
            file_path: None,
            active: false,
            temporary: false,
            read_only: false,
            major_mode: "fundamental-mode",
            minor_modes: Vec::new(),
            dirty: false,
            text: GapBuffer::new(),
            logger: buf_logger,
        }
    }

    /// Return true if a buffer is active.
    /// That is to say, a 'focused' buffer, or otherwise in-use, and
    /// *not* inactive.
    /// If it's not a active buffer, then return false.
    pub fn is_active(&self) -> bool {
        self.active
    }

    /// Return true if a buffer is temporary.
    /// If it's not a temporary buffer, then return false.
    /// A temporary buffer is defined by the characteristic of having
    /// no 'target' to save to.
    pub fn is_temporary(&self) -> bool {
        self.temporary
    }

    /// Return true if a buffer is read only.

    /// If it's not read-only, then it returns false, and the buffer
    /// will be presumed to be read-write.

    /// A read-only buffer is defined by the characteristic of the FS
    /// denying write access, or being set manually.
    pub fn is_ro(&self) -> bool {
        self.read_only
    }

    /// Return true if a buffer is dirty.
    /// If it's not dirty, then return false.
    /// A dirty buffer is defined by the characteristic of the buffer
    /// having changed since the last save.
    /// Temporary buffers are *exempt* from this field.
    pub fn is_dirty(&self) -> bool {
        self.dirty
    }

    /// Return the current major mode of a buffer.
    pub fn get_major_mode(&self) -> &str {
        self.major_mode
    }

    /// Return a `Vec<&'static str>` of minor modes.
    pub fn get_minor_modes(&self) -> Vec<&'static str> {
        self.minor_modes.clone()
    }

    /// Return the length of a buffer.
    pub fn get_buffer_length(&self) -> usize {
        self.text.len()
    }
}

impl Default for Buffer {
    fn default() -> Buffer {
        Buffer::new()
    }
}

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

    #[test]
    fn test_buffer_default_values() {
        let buf = Buffer::new();

        assert_eq!(None, buf.file_path);
        assert_eq!(false, buf.active);
        assert_eq!(false, buf.is_active());

        assert_eq!(false, buf.temporary);
        assert_eq!(false, buf.is_temporary());

        assert_eq!(false, buf.read_only);
        assert_eq!(false, buf.is_ro());

        assert_eq!("fundamental-mode", buf.major_mode);
        assert_eq!(false, buf.dirty);
    }

    #[test]
    fn test_buffer_major_minor_modes() {
        let mut buf = Buffer::new();
        buf.major_mode = "rust-mode";
        buf.minor_modes.push("auto-wrap-mode");
        buf.minor_modes.push("spell-check-mode");
        buf.minor_modes.push("complete-me-mode");
        buf.minor_modes.push("language-server-mode");

        assert_eq!(4, buf.minor_modes.len());
        assert_eq!("rust-mode", buf.major_mode);
    }
}
<commit_msg>buffer: remove Logging invocations<commit_after>//! This is the Buffer module for Xtensis.

// This file is part of Xtensis.

// This is the Xtensis text editor; it edits text.
// Copyright (C) 2016-2017  The Xtensis Developers

// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see
// <http://www.gnu.org/licenses/>.

extern crate slog;
extern crate slog_scope;

use std::path::PathBuf;

use server::gapbuffer::GapBuffer;
use utils::uuid;
use slog::Logger;

/// Struct for a Buffer in Xtensis
/// This stores metadata about a buffer.
#[derive(Debug)]
pub struct Buffer {
    /// UUID of a buffer.
    pub buf_uuid: String,
    /// File path of a buffer.
    pub file_path: Option<PathBuf>,
    /// Active status of a buffer.
    pub active: bool,
    /// Temporary status of a buffer.
    pub temporary: bool,
    /// If a buffer is r/o.
    /// If this is `true`, then r/w is `false.`
    /// Likewise, if this is `false`, then r/w is `true.
    pub read_only: bool,
    /// Major mode of a buffer
    pub major_mode: &'static str,
    /// Vector of Minor modes in a buffer
    pub minor_modes: Vec<&'static str>,
    /// Dirty status of a buffer
    pub dirty: bool,
    /// Contents of a buffer.
    pub text: GapBuffer<u8>,
}

impl Buffer {
    /// Return a new instance of `Buffer`.
    pub fn new() -> Buffer {
        Buffer {
            buf_uuid: uuid::get_uuid_buffer(),
            file_path: None,
            active: false,
            temporary: false,
            read_only: false,
            major_mode: "fundamental-mode",
            minor_modes: Vec::new(),
            dirty: false,
            text: GapBuffer::new(),
        }
    }

    /// Return true if a buffer is active.
    /// That is to say, a 'focused' buffer, or otherwise in-use, and
    /// *not* inactive.
    /// If it's not a active buffer, then return false.
    pub fn is_active(&self) -> bool {
        self.active
    }

    /// Return true if a buffer is temporary.
    /// If it's not a temporary buffer, then return false.
    /// A temporary buffer is defined by the characteristic of having
    /// no 'target' to save to.
    pub fn is_temporary(&self) -> bool {
        self.temporary
    }

    /// Return true if a buffer is read only.

    /// If it's not read-only, then it returns false, and the buffer
    /// will be presumed to be read-write.

    /// A read-only buffer is defined by the characteristic of the FS
    /// denying write access, or being set manually.
    pub fn is_ro(&self) -> bool {
        self.read_only
    }

    /// Return true if a buffer is dirty.
    /// If it's not dirty, then return false.
    /// A dirty buffer is defined by the characteristic of the buffer
    /// having changed since the last save.
    /// Temporary buffers are *exempt* from this field.
    pub fn is_dirty(&self) -> bool {
        self.dirty
    }

    /// Return the current major mode of a buffer.
    pub fn get_major_mode(&self) -> &str {
        self.major_mode
    }

    /// Return a `Vec<&'static str>` of minor modes.
    pub fn get_minor_modes(&self) -> Vec<&'static str> {
        self.minor_modes.clone()
    }

    /// Return the length of a buffer.
    pub fn get_buffer_length(&self) -> usize {
        self.text.len()
    }
}

impl Default for Buffer {
    fn default() -> Buffer {
        Buffer::new()
    }
}

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

    #[test]
    fn test_buffer_default_values() {
        let buf = Buffer::new();

        assert_eq!(None, buf.file_path);
        assert_eq!(false, buf.active);
        assert_eq!(false, buf.is_active());

        assert_eq!(false, buf.temporary);
        assert_eq!(false, buf.is_temporary());

        assert_eq!(false, buf.read_only);
        assert_eq!(false, buf.is_ro());

        assert_eq!("fundamental-mode", buf.major_mode);
        assert_eq!(false, buf.dirty);
    }

    #[test]
    fn test_buffer_major_minor_modes() {
        let mut buf = Buffer::new();
        buf.major_mode = "rust-mode";
        buf.minor_modes.push("auto-wrap-mode");
        buf.minor_modes.push("spell-check-mode");
        buf.minor_modes.push("complete-me-mode");
        buf.minor_modes.push("language-server-mode");

        assert_eq!(4, buf.minor_modes.len());
        assert_eq!("rust-mode", buf.major_mode);
    }
}
<|endoftext|>


<commit_before>//! Target information

use super::prelude::*;

#[repr(C)]
pub enum LLVMByteOrdering {
    LLVMBigEndian = 0,
    LLVMLittleEndian = 1,
}

pub enum LLVMOpaqueTargetData {}
pub type LLVMTargetDataRef = *mut LLVMOpaqueTargetData;

pub enum LLVMOpaqueTargetLibraryInfotData {}
pub type LLVMTargetLibraryInfoRef = *mut LLVMOpaqueTargetLibraryInfotData;

extern "C" {
    pub fn LLVMInitializeAMDGPUTargetInfo();
    pub fn LLVMInitializeSystemZTargetInfo();
    pub fn LLVMInitializeHexagonTargetInfo();
    pub fn LLVMInitializeNVPTXTargetInfo();
    pub fn LLVMInitializeCppBackendTargetInfo();
    pub fn LLVMInitializeMSP430TargetInfo();
    pub fn LLVMInitializeXCoreTargetInfo();
    pub fn LLVMInitializeMipsTargetInfo();
    pub fn LLVMInitializeAArch64TargetInfo();
    pub fn LLVMInitializeARMTargetInfo();
    pub fn LLVMInitializePowerPCTargetInfo();
    pub fn LLVMInitializeSparcTargetInfo();
    pub fn LLVMInitializeX86TargetInfo();
    pub fn LLVMInitializeAMDGPUTarget();
    pub fn LLVMInitializeSystemZTarget();
    pub fn LLVMInitializeHexagonTarget();
    pub fn LLVMInitializeNVPTXTarget();
    pub fn LLVMInitializeCppBackendTarget();
    pub fn LLVMInitializeMSP430Target();
    pub fn LLVMInitializeXCoreTarget();
    pub fn LLVMInitializeMipsTarget();
    pub fn LLVMInitializeAArch64Target();
    pub fn LLVMInitializeARMTarget();
    pub fn LLVMInitializePowerPCTarget();
    pub fn LLVMInitializeSparcTarget();
    pub fn LLVMInitializeX86Target();
    pub fn LLVMInitializeAMDGPUTargetMC();
    pub fn LLVMInitializeSystemZTargetMC();
    pub fn LLVMInitializeHexagonTargetMC();
    pub fn LLVMInitializeNVPTXTargetMC();
    pub fn LLVMInitializeCppBackendTargetMC();
    pub fn LLVMInitializeMSP430TargetMC();
    pub fn LLVMInitializeXCoreTargetMC();
    pub fn LLVMInitializeMipsTargetMC();
    pub fn LLVMInitializeAArch64TargetMC();
    pub fn LLVMInitializeARMTargetMC();
    pub fn LLVMInitializePowerPCTargetMC();
    pub fn LLVMInitializeSparcTargetMC();
    pub fn LLVMInitializeX86TargetMC();
    pub fn LLVMInitializeAMDGPUAsmPrinter();
    pub fn LLVMInitializeSystemZAsmPrinter();
    pub fn LLVMInitializeHexagonAsmPrinter();
    pub fn LLVMInitializeNVPTXAsmPrinter();
    pub fn LLVMInitializeMSP430AsmPrinter();
    pub fn LLVMInitializeXCoreAsmPrinter();
    pub fn LLVMInitializeMipsAsmPrinter();
    pub fn LLVMInitializeAArch64AsmPrinter();
    pub fn LLVMInitializeARMAsmPrinter();
    pub fn LLVMInitializePowerPCAsmPrinter();
    pub fn LLVMInitializeSparcAsmPrinter();
    pub fn LLVMInitializeX86AsmPrinter();
    pub fn LLVMInitializeAMDGPUAsmParser();
    pub fn LLVMInitializeSystemZAsmParser();
    pub fn LLVMInitializeMipsAsmParser();
    pub fn LLVMInitializeAArch64AsmParser();
    pub fn LLVMInitializeARMAsmParser();
    pub fn LLVMInitializePowerPCAsmParser();
    pub fn LLVMInitializeSparcAsmParser();
    pub fn LLVMInitializeX86AsmParser();
    pub fn LLVMInitializeSystemZDisassembler();
    pub fn LLVMInitializeHexagonDisassembler();
    pub fn LLVMInitializeXCoreDisassembler();
    pub fn LLVMInitializeMipsDisassembler();
    pub fn LLVMInitializeAArch64Disassembler();
    pub fn LLVMInitializeARMDisassembler();
    pub fn LLVMInitializePowerPCDisassembler();
    pub fn LLVMInitializeSparcDisassembler();
    pub fn LLVMInitializeX86Disassembler();
}

extern "C" {
    /// Get the data layout for a module.
    pub fn LLVMGetModuleDataLayout(M: LLVMModuleRef) -> LLVMTargetDataRef;
    /// Set the data layout for a module.
    pub fn LLVMSetModuleDataLayout(M: LLVMModuleRef, R: LLVMTargetDataRef);
    /// Create target data from a target layout string.
    pub fn LLVMCreateTargetData(StringRep: *const ::libc::c_char) -> LLVMTargetDataRef;
    pub fn LLVMAddTargetLibraryInfo(TLI: LLVMTargetLibraryInfoRef, PM: LLVMPassManagerRef);
    pub fn LLVMCopyStringRepOfTargetData(TD: LLVMTargetDataRef) -> *mut ::libc::c_char;
    pub fn LLVMByteOrder(TD: LLVMTargetDataRef) -> LLVMByteOrdering;
    pub fn LLVMPointerSize(TD: LLVMTargetDataRef) -> ::libc::c_uint;
    pub fn LLVMPointerSizeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> ::libc::c_uint;
    pub fn LLVMIntPtrType(TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeInContext(C: LLVMContextRef, TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForASInContext(C: LLVMContextRef,
                                        TD: LLVMTargetDataRef,
                                        AS: ::libc::c_uint)
                                        -> LLVMTypeRef;
    pub fn LLVMSizeOfTypeInBits(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMStoreSizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABISizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABIAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMCallFrameAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfGlobal(TD: LLVMTargetDataRef,
                                          GlobalVar: LLVMValueRef)
                                          -> ::libc::c_uint;
    pub fn LLVMElementAtOffset(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Offset: ::libc::c_ulonglong)
                               -> ::libc::c_uint;
    pub fn LLVMOffsetOfElement(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Element: ::libc::c_uint)
                               -> ::libc::c_ulonglong;
    pub fn LLVMDisposeTargetData(TD: LLVMTargetDataRef);
}

// Functions from our target wrappers, since the C interface defines them with
// macros (wrappers/target.c).
extern "C" {
    pub fn LLVM_InitializeAllTargetInfos();
    pub fn LLVM_InitializeAllTargets();
    pub fn LLVM_InitializeAllTargetMCs();
    pub fn LLVM_InitializeAllAsmPrinters();
    pub fn LLVM_InitializeAllAsmParsers();
    pub fn LLVM_InitializeAllDisassemblers();

    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeTarget() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmParser() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmPrinter() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeDisassembler() -> LLVMBool;
}
<commit_msg>Reorganize target declarations.<commit_after>//! Target information

use super::prelude::*;

#[repr(C)]
pub enum LLVMByteOrdering {
    LLVMBigEndian = 0,
    LLVMLittleEndian = 1,
}

pub enum LLVMOpaqueTargetData {}
pub type LLVMTargetDataRef = *mut LLVMOpaqueTargetData;

pub enum LLVMOpaqueTargetLibraryInfotData {}
pub type LLVMTargetLibraryInfoRef = *mut LLVMOpaqueTargetLibraryInfotData;

extern "C" {
    pub fn LLVMInitializeAMDGPUTargetInfo();
    pub fn LLVMInitializeAMDGPUTarget();
    pub fn LLVMInitializeAMDGPUTargetMC();
    pub fn LLVMInitializeAMDGPUAsmPrinter();
    pub fn LLVMInitializeAMDGPUAsmParser();
    // Disassembler?

    pub fn LLVMInitializeSystemZTargetInfo();
    pub fn LLVMInitializeSystemZTarget();
    pub fn LLVMInitializeSystemZTargetMC();
    pub fn LLVMInitializeSystemZAsmPrinter();
    pub fn LLVMInitializeSystemZAsmParser();
    pub fn LLVMInitializeSystemZDisassembler();

    pub fn LLVMInitializeHexagonTargetInfo();
    pub fn LLVMInitializeHexagonTarget();
    pub fn LLVMInitializeHexagonTargetMC();
    pub fn LLVMInitializeHexagonAsmPrinter();
    // AsmParser?
    pub fn LLVMInitializeHexagonDisassembler();

    pub fn LLVMInitializeNVPTXTargetInfo();
    pub fn LLVMInitializeNVPTXTarget();
    pub fn LLVMInitializeNVPTXTargetMC();
    pub fn LLVMInitializeNVPTXAsmPrinter();
    // AsmParser?

    pub fn LLVMInitializeCppBackendTargetInfo();
    pub fn LLVMInitializeCppBackendTarget();
    pub fn LLVMInitializeCppBackendTargetMC();
    // AsmPrinter?
    // AsmParser?

    pub fn LLVMInitializeMSP430TargetInfo();
    pub fn LLVMInitializeMSP430Target();
    pub fn LLVMInitializeMSP430TargetMC();
    pub fn LLVMInitializeMSP430AsmPrinter();
    // AsmParser?

    pub fn LLVMInitializeXCoreTargetInfo();
    pub fn LLVMInitializeXCoreTarget();
    pub fn LLVMInitializeXCoreTargetMC();
    pub fn LLVMInitializeXCoreAsmPrinter();
    // AsmParser?
    pub fn LLVMInitializeXCoreDisassembler();

    pub fn LLVMInitializeMipsTargetInfo();
    pub fn LLVMInitializeMipsTarget();
    pub fn LLVMInitializeMipsTargetMC();
    pub fn LLVMInitializeMipsAsmPrinter();
    pub fn LLVMInitializeMipsAsmParser();
    pub fn LLVMInitializeMipsDisassembler();

    pub fn LLVMInitializeAArch64TargetInfo();
    pub fn LLVMInitializeAArch64Target();
    pub fn LLVMInitializeAArch64TargetMC();
    pub fn LLVMInitializeAArch64AsmPrinter();
    pub fn LLVMInitializeAArch64AsmParser();
    pub fn LLVMInitializeAArch64Disassembler();

    pub fn LLVMInitializeARMTargetInfo();
    pub fn LLVMInitializeARMTarget();
    pub fn LLVMInitializeARMTargetMC();
    pub fn LLVMInitializeARMAsmPrinter();
    pub fn LLVMInitializeARMAsmParser();
    pub fn LLVMInitializeARMDisassembler();

    pub fn LLVMInitializePowerPCTargetInfo();
    pub fn LLVMInitializePowerPCTarget();
    pub fn LLVMInitializePowerPCTargetMC();
    pub fn LLVMInitializePowerPCAsmPrinter();
    pub fn LLVMInitializePowerPCAsmParser();
    pub fn LLVMInitializePowerPCDisassembler();

    pub fn LLVMInitializeSparcTargetInfo();
    pub fn LLVMInitializeSparcTarget();
    pub fn LLVMInitializeSparcTargetMC();
    pub fn LLVMInitializeSparcAsmPrinter();
    pub fn LLVMInitializeSparcAsmParser();
    pub fn LLVMInitializeSparcDisassembler();

    pub fn LLVMInitializeX86TargetInfo();
    pub fn LLVMInitializeX86Target();
    pub fn LLVMInitializeX86TargetMC();
    pub fn LLVMInitializeX86AsmPrinter();
    pub fn LLVMInitializeX86AsmParser();
    pub fn LLVMInitializeX86Disassembler();
}

extern "C" {
    /// Get the data layout for a module.
    pub fn LLVMGetModuleDataLayout(M: LLVMModuleRef) -> LLVMTargetDataRef;
    /// Set the data layout for a module.
    pub fn LLVMSetModuleDataLayout(M: LLVMModuleRef, R: LLVMTargetDataRef);
    /// Create target data from a target layout string.
    pub fn LLVMCreateTargetData(StringRep: *const ::libc::c_char) -> LLVMTargetDataRef;
    pub fn LLVMAddTargetLibraryInfo(TLI: LLVMTargetLibraryInfoRef, PM: LLVMPassManagerRef);
    pub fn LLVMCopyStringRepOfTargetData(TD: LLVMTargetDataRef) -> *mut ::libc::c_char;
    pub fn LLVMByteOrder(TD: LLVMTargetDataRef) -> LLVMByteOrdering;
    pub fn LLVMPointerSize(TD: LLVMTargetDataRef) -> ::libc::c_uint;
    pub fn LLVMPointerSizeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> ::libc::c_uint;
    pub fn LLVMIntPtrType(TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeInContext(C: LLVMContextRef, TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForASInContext(C: LLVMContextRef,
                                        TD: LLVMTargetDataRef,
                                        AS: ::libc::c_uint)
                                        -> LLVMTypeRef;
    pub fn LLVMSizeOfTypeInBits(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMStoreSizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABISizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABIAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMCallFrameAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfGlobal(TD: LLVMTargetDataRef,
                                          GlobalVar: LLVMValueRef)
                                          -> ::libc::c_uint;
    pub fn LLVMElementAtOffset(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Offset: ::libc::c_ulonglong)
                               -> ::libc::c_uint;
    pub fn LLVMOffsetOfElement(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Element: ::libc::c_uint)
                               -> ::libc::c_ulonglong;
    pub fn LLVMDisposeTargetData(TD: LLVMTargetDataRef);
}

// Functions from our target wrappers, since the C interface defines them with
// macros (wrappers/target.c).
extern "C" {
    pub fn LLVM_InitializeAllTargetInfos();
    pub fn LLVM_InitializeAllTargets();
    pub fn LLVM_InitializeAllTargetMCs();
    pub fn LLVM_InitializeAllAsmPrinters();
    pub fn LLVM_InitializeAllAsmParsers();
    pub fn LLVM_InitializeAllDisassemblers();

    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeTarget() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmParser() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmPrinter() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeDisassembler() -> LLVMBool;
}
<|endoftext|>