<commit_before>use front::run::compiler::Compiler;
use syntax::ast::constant::*;
use syntax::ast::op::*;
use syntax::ast::expr::Expr;
use jit::{
    Context,
    Compile,
    Function,
    Value,
    get_type,
    SysBool,
    Int,
    UInt,
    NInt,
    NUInt,
    Float64,
    Pointer
};
type CompiledValue<'a> = (Value<'a>, &'a Function<'a>);
/// A compiler using the LibJIT backend
pub struct JitCompiler<'a> {
    curr: Function<'a>
}
impl<'a> JitCompiler<'a> {
    /// Construct a new JIT Compiler on the given context
    pub fn new(context: &'a Context) -> JitCompiler<'a> {
        let main_t = get_type::<fn(*const int, *const int, *const int) -> *const int>();
        JitCompiler {
            curr: Function::new(context, main_t)
        }
    }
    fn convert_bool(&'a self, val:Value<'a>) -> Value<'a> {
        let bool_t = get_type::<bool>();
        let val_kind = val.get_type().get_kind();
        let convert = |v| self.curr.insn_convert(&v, bool_t, false);
        if val_kind.contains(SysBool) {
            val
        } else if val_kind.contains(Float64) {
            let zero = 0.0f64.compile(&self.curr);
            let not_zero = self.curr.insn_neq(&val, &zero);
            let not_nan = !self.curr.insn_is_nan(&val);
            convert(not_zero & not_nan)
        } else if val_kind.contains(Int) || val_kind.contains(UInt) || val_kind.contains(NInt) || val_kind.contains(NUInt) {
            let zero = 0i.compile(&self.curr);
            convert(self.curr.insn_neq(&val, &zero))
        } else if val_kind.contains(Pointer) {
            let one = 1i.compile(&self.curr);
            convert(self.curr.insn_gt(&val, &one))
        } else {
            convert(val)
        }
    }
    fn undefined(&'a self) -> Value<'a> {
        let ptr = Value::new(&self.curr, get_type::<&int>());
        let val = 0u8.compile(&self.curr);
        self.curr.insn_store(&ptr, &val);
        ptr
    }
}
impl<'a> Compiler<'a, (Value<'a>, &'a Function<'a>)> for JitCompiler<'a> {
    fn compile_const(&'a self, constant:&Const) -> CompiledValue<'a> {
        (match constant.clone() {
            CString(v) =>
                v.compile(&self.curr),
            CNum(v) =>
                v.compile(&self.curr),
            CInt(v) =>
                v.compile(&self.curr),
            CBool(v) =>
                v.compile(&self.curr),
            CNull => {
                let ptr = Value::new(&self.curr, get_type::<&int>());
                let val = 1u8.compile(&self.curr);
                self.curr.insn_store(&ptr, &val);
                ptr
            },
            CUndefined => {
                self.undefined()
            },
            _ => unimplemented!()
        }, &self.curr)
    }
    fn compile_block(&'a self, block:Vec<Expr>) -> CompiledValue<'a> {
        let last = block.last();
        for expr in block.iter() {
            let comp = self.compile(expr);
            if expr == last.unwrap() {
                return comp
            }
        }
        unreachable!()
    }
    fn compile_num_op(&'a self, op:NumOp, left:&Expr, right:&Expr) -> CompiledValue<'a> {
        let (c_left, _) = self.compile(left);
        let (c_right, _) = self.compile(right);
        (match op {
            OpAdd => c_left + c_right,
            OpSub => c_left - c_right,
            OpDiv => c_left / c_right,
            OpMul => c_left * c_right,
            OpMod => c_left % c_right
        }, &self.curr)
    }
    fn compile_bit_op(&'a self, op:BitOp, left:&Expr, right:&Expr) -> CompiledValue<'a> {
        let int_t = get_type::<i32>();
        let (c_left, _) = self.compile(left);
        let c_left = self.curr.insn_convert(&c_left, int_t.clone(), false);
        let (c_right, _) = self.compile(right);
        let c_right = self.curr.insn_convert(&c_right, int_t, false);
        (match op {
            BitAnd => c_left & c_right,
            BitOr => c_left | c_right,
            BitXor => c_left ^ c_right,
            BitShl => c_left << c_right,
            BitShr => c_left >> c_right
        }, &self.curr)
    }
    fn compile_log_op(&'a self, op:LogOp, left:&Expr, right:&Expr) -> CompiledValue<'a> {
        let (c_left, _) = self.compile(left);
        let c_left = self.convert_bool(c_left);
        let (c_right, _) = self.compile(right);
        let c_right = self.convert_bool(c_right);
        (match op {
            LogAnd => c_left & c_right,
            LogOr => c_left | c_right
        }, &self.curr)
    }
    fn compile_comp_op(&'a self, op:CompOp, left:&Expr, right:&Expr) -> CompiledValue<'a> {
        let (c_left, _) = self.compile(left);
        let (c_right, _) = self.compile(right);
        let val = match op {
            CompEqual | CompStrictEqual =>
                self.curr.insn_eq(&c_left, &c_right),
            CompNotEqual | CompStrictNotEqual =>
                self.curr.insn_neq(&c_left, &c_right),
            CompGreaterThan =>
                self.curr.insn_gt(&c_left, &c_right),
            CompGreaterThanOrEqual =>
                self.curr.insn_geq(&c_left, &c_right),
            CompLessThan =>
                self.curr.insn_lt(&c_left, &c_right),
            CompLessThanOrEqual =>
                self.curr.insn_leq(&c_left, &c_right),
        };
        let bool_val = self.curr.insn_convert(&val, get_type::<bool>(), false);
        (bool_val, &self.curr)
    }
    fn compile_unary_op(&'a self, op:UnaryOp, val:&Expr) -> CompiledValue<'a> {
        let (c_val, _) = self.compile(val);
        (match op {
            UnaryMinus => -c_val,
            UnaryPlus => c_val,
            UnaryNot => {
                let c_not = !c_val;
                self.curr.insn_convert(&c_not, get_type::<bool>(), false)
            },
            _ => unimplemented!()
        }, &self.curr)
    }
    fn compile_return(&'a self, val:Option<Box<Expr>>) -> CompiledValue<'a> {
        match val {
            Some(val) => {
                let (c_val, _) = self.compile(val);
                self.curr.insn_return(&c_val)
            },
            None => {
                self.curr.insn_default_return()
            }
        };
        (self.undefined(), &self.curr)
    }
}<commit_msg>Clone captured `bool_t`<commit_after>use front::run::compiler::Compiler;
use syntax::ast::constant::*;
use syntax::ast::op::*;
use syntax::ast::expr::Expr;
use jit::{
    Context,
    Compile,
    Function,
    Value,
    get_type,
    SysBool,
    Int,
    UInt,
    NInt,
    NUInt,
    Float64,
    Pointer
};
type CompiledValue<'a> = (Value<'a>, &'a Function<'a>);
/// A compiler using the LibJIT backend
pub struct JitCompiler<'a> {
    curr: Function<'a>
}
impl<'a> JitCompiler<'a> {
    /// Construct a new JIT Compiler on the given context
    pub fn new(context: &'a Context) -> JitCompiler<'a> {
        let main_t = get_type::<fn(*const int, *const int, *const int) -> *const int>();
        JitCompiler {
            curr: Function::new(context, main_t)
        }
    }
    fn convert_bool(&'a self, val:Value<'a>) -> Value<'a> {
        let bool_t = get_type::<bool>();
        let val_kind = val.get_type().get_kind();
        let convert = |v| self.curr.insn_convert(&v, bool_t.clone(), false);
        if val_kind.contains(SysBool) {
            val
        } else if val_kind.contains(Float64) {
            let zero = 0.0f64.compile(&self.curr);
            let not_zero = self.curr.insn_neq(&val, &zero);
            let not_nan = !self.curr.insn_is_nan(&val);
            convert(not_zero & not_nan)
        } else if val_kind.contains(Int) || val_kind.contains(UInt) || val_kind.contains(NInt) || val_kind.contains(NUInt) {
            let zero = 0i.compile(&self.curr);
            convert(self.curr.insn_neq(&val, &zero))
        } else if val_kind.contains(Pointer) {
            let one = 1i.compile(&self.curr);
            convert(self.curr.insn_gt(&val, &one))
        } else {
            convert(val)
        }
    }
    fn undefined(&'a self) -> Value<'a> {
        let ptr = Value::new(&self.curr, get_type::<&int>());
        let val = 0u8.compile(&self.curr);
        self.curr.insn_store(&ptr, &val);
        ptr
    }
}
impl<'a> Compiler<'a, (Value<'a>, &'a Function<'a>)> for JitCompiler<'a> {
    fn compile_const(&'a self, constant:&Const) -> CompiledValue<'a> {
        (match constant.clone() {
            CString(v) =>
                v.compile(&self.curr),
            CNum(v) =>
                v.compile(&self.curr),
            CInt(v) =>
                v.compile(&self.curr),
            CBool(v) =>
                v.compile(&self.curr),
            CNull => {
                let ptr = Value::new(&self.curr, get_type::<&int>());
                let val = 1u8.compile(&self.curr);
                self.curr.insn_store(&ptr, &val);
                ptr
            },
            CUndefined => {
                self.undefined()
            },
            _ => unimplemented!()
        }, &self.curr)
    }
    fn compile_block(&'a self, block:Vec<Expr>) -> CompiledValue<'a> {
        let last = block.last();
        for expr in block.iter() {
            let comp = self.compile(expr);
            if expr == last.unwrap() {
                return comp
            }
        }
        unreachable!()
    }
    fn compile_num_op(&'a self, op:NumOp, left:&Expr, right:&Expr) -> CompiledValue<'a> {
        let (c_left, _) = self.compile(left);
        let (c_right, _) = self.compile(right);
        (match op {
            OpAdd => c_left + c_right,
            OpSub => c_left - c_right,
            OpDiv => c_left / c_right,
            OpMul => c_left * c_right,
            OpMod => c_left % c_right
        }, &self.curr)
    }
    fn compile_bit_op(&'a self, op:BitOp, left:&Expr, right:&Expr) -> CompiledValue<'a> {
        let int_t = get_type::<i32>();
        let (c_left, _) = self.compile(left);
        let c_left = self.curr.insn_convert(&c_left, int_t.clone(), false);
        let (c_right, _) = self.compile(right);
        let c_right = self.curr.insn_convert(&c_right, int_t, false);
        (match op {
            BitAnd => c_left & c_right,
            BitOr => c_left | c_right,
            BitXor => c_left ^ c_right,
            BitShl => c_left << c_right,
            BitShr => c_left >> c_right
        }, &self.curr)
    }
    fn compile_log_op(&'a self, op:LogOp, left:&Expr, right:&Expr) -> CompiledValue<'a> {
        let (c_left, _) = self.compile(left);
        let c_left = self.convert_bool(c_left);
        let (c_right, _) = self.compile(right);
        let c_right = self.convert_bool(c_right);
        (match op {
            LogAnd => c_left & c_right,
            LogOr => c_left | c_right
        }, &self.curr)
    }
    fn compile_comp_op(&'a self, op:CompOp, left:&Expr, right:&Expr) -> CompiledValue<'a> {
        let (c_left, _) = self.compile(left);
        let (c_right, _) = self.compile(right);
        let val = match op {
            CompEqual | CompStrictEqual =>
                self.curr.insn_eq(&c_left, &c_right),
            CompNotEqual | CompStrictNotEqual =>
                self.curr.insn_neq(&c_left, &c_right),
            CompGreaterThan =>
                self.curr.insn_gt(&c_left, &c_right),
            CompGreaterThanOrEqual =>
                self.curr.insn_geq(&c_left, &c_right),
            CompLessThan =>
                self.curr.insn_lt(&c_left, &c_right),
            CompLessThanOrEqual =>
                self.curr.insn_leq(&c_left, &c_right),
        };
        let bool_val = self.curr.insn_convert(&val, get_type::<bool>(), false);
        (bool_val, &self.curr)
    }
    fn compile_unary_op(&'a self, op:UnaryOp, val:&Expr) -> CompiledValue<'a> {
        let (c_val, _) = self.compile(val);
        (match op {
            UnaryMinus => -c_val,
            UnaryPlus => c_val,
            UnaryNot => {
                let c_not = !c_val;
                self.curr.insn_convert(&c_not, get_type::<bool>(), false)
            },
            _ => unimplemented!()
        }, &self.curr)
    }
    fn compile_return(&'a self, val:Option<Box<Expr>>) -> CompiledValue<'a> {
        match val {
            Some(val) => {
                let (c_val, _) = self.compile(val);
                self.curr.insn_return(&c_val)
            },
            None => {
                self.curr.insn_default_return()
            }
        };
        (self.undefined(), &self.curr)
    }
}<|endoftext|>


<commit_before>// use std::old_io::{TcpListener, TcpStream};
// use std::old_io::{Acceptor, Listener, IoResult, MemReader};
use std::thread::sleep_ms;
use std::io::{Read, Write, Result};

use std::net::{TcpListener, TcpStream};
use std::mem::size_of;

use std::sync::mpsc::{Sender, Receiver, channel};

use std::thread;
use std::sync::{Arc, Future};
use std::mem;

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

use communication::{Pushable, BinaryCommunicator, ProcessCommunicator};

// TODO : Much of this only relates to BinaryWriter/BinaryReader based communication, not networking.
// TODO : Could be moved somewhere less networking-specific.

#[derive(Copy, Clone)]
pub struct MessageHeader {
    pub graph:      u64,   // graph identifier
    pub channel:    u64,   // index of channel
    pub source:     u64,   // index of worker sending message
    pub target:     u64,   // index of worker receiving message
    pub length:     u64,   // number of bytes in message
}

impl MessageHeader {
    // returns a header when there is enough supporting data
    fn try_read(bytes: &mut &[u8]) -> Option<MessageHeader> {
        if bytes.len() > size_of::<MessageHeader>() {
            let headers: &[MessageHeader] = unsafe { mem::transmute((*bytes).clone()) };
            let header = headers[0];
            if bytes.len() >= size_of::<MessageHeader>() + header.length as usize {
                *bytes = &(*bytes)[size_of::<MessageHeader>()..];
                return Some(header);
            }
            else {
                println!("bytes.len() = {}, needed = {}", bytes.len(), size_of::<MessageHeader>() + header.length as usize);
            }
        }
        return None;
    }

    fn write_to<W: Write>(&self, writer: &mut W) -> Result<()> {
        try!(writer.write_u64::<LittleEndian>(self.graph));
        try!(writer.write_u64::<LittleEndian>(self.channel));
        try!(writer.write_u64::<LittleEndian>(self.source));
        try!(writer.write_u64::<LittleEndian>(self.target));
        try!(writer.write_u64::<LittleEndian>(self.length));
        Ok(())
    }
}

// structure in charge of receiving data from a Reader, for example the network
struct BinaryReceiver<R: Read> {
    // targets (and u8 returns) indexed by worker, graph, and channel.
    // option because they get filled progressively; alt design might change that.
    targets:    Vec<Vec<Vec<Option<(Sender<Vec<u8>>, Receiver<Vec<u8>>)>>>>,

    reader:     R,          // the generic reader
    buffer:     Vec<u8>,    // current working buffer
    double:     Vec<u8>,    // second working buffer

    // how a BinaryReceiver learns about new channels; indices and corresponding channel pairs
    channels:   Receiver<((u64, u64, u64), Sender<Vec<u8>>, Receiver<Vec<u8>>)>,
}

impl<R: Read> BinaryReceiver<R> {
    fn new(reader: R, targets: u64, channels: Receiver<((u64, u64, u64), Sender<Vec<u8>>, Receiver<Vec<u8>>)>) -> BinaryReceiver<R> {
        BinaryReceiver {
            targets:    (0..targets).map(|_| Vec::new()).collect(),
            reader:     reader,
            buffer:     Vec::new(),
            double:     Vec::new(),
            channels:   channels,
        }
    }

    fn recv_loop(&mut self) {
        loop {

            // attempt to read some more bytes into our buffer
            let valid = self.buffer.len();
            self.buffer.reserve(1 << 20);
            unsafe { self.buffer.set_len(valid + (1 << 20)); }
            // println!("reading");
            let read = self.reader.read(&mut self.buffer[valid..(valid + (1 << 20))]).unwrap_or(0);
            // println!("read: {}", read);

            unsafe { self.buffer.set_len(valid + read); }

            {
                // get a view of available bytes
                let mut slice = &self.buffer[..];

                while let Some(header) = MessageHeader::try_read(&mut slice) {
                    let h_tgt = header.target as usize;  // target worker
                    let h_grp = header.graph as usize;   // target graph
                    let h_chn = header.channel as usize; // target channel
                    let h_len = header.length as usize;  // length in bytes

                    // println!("looking for {} bytes; have {} bytes", h_len, slice.len());

                    while self.targets.len() <= h_tgt { self.targets.push(Vec::new()) ;}
                    while self.targets[h_tgt].len() <= h_grp { self.targets[h_tgt].push(Vec::new()) ;}
                    while self.targets[h_tgt][h_grp].len() <= h_chn { self.targets[h_tgt][h_grp].push(None) ;}

                    // ensure that the destination exists!
                    while let None = self.targets[h_tgt][h_grp][h_chn] {
                        // receive channel descriptions if any
                        let ((t, g, c), s, r) = self.channels.recv().unwrap();
                        while self.targets.len() as u64 <= t { self.targets.push(Vec::new()); }
                        while self.targets[t as usize].len() as u64 <= g { self.targets[t as usize].push(Vec::new()); }
                        while self.targets[t as usize][g as usize].len() as u64 <= c { self.targets[t as usize][g as usize].push(None); }

                        self.targets[t as usize][g as usize][c as usize] = Some((s, r));
                    }

                    let mut buffer = if let Ok(b) = self.targets[h_tgt][h_grp][h_chn].as_ref().unwrap().1.try_recv() { b }
                                     else { Vec::new() };

                    buffer.clear();
                    buffer.push_all(&slice[..h_len]);

                    slice = &slice[h_len..];

                    self.targets[h_tgt][h_grp][h_chn].as_ref().unwrap().0.send(buffer).unwrap();
                }

                // TODO: way inefficient... =/ Fix! :D
                self.double.clear();
                self.double.push_all(slice);
            }

            mem::swap(&mut self.buffer, &mut self.double);
        }
    }

    fn ensure(&mut self, target: u64, graph: u64, channel: u64) {
        // println!("starting ensure({}, {}, {})", target, graph, channel);

        while self.targets.len() as u64 <= target { self.targets.push(Vec::new()); }
        while self.targets[target as usize].len() as u64 <= graph { self.targets[target as usize].push(Vec::new()); }
        while self.targets[target as usize][graph as usize].len() as u64 <= channel {
            self.targets[target as usize][graph as usize].push(None);
        }

        while let None = self.targets[target as usize][graph as usize][channel as usize] {
            // receive channel descriptions if any
            let ((t, g, c), s, r) = self.channels.recv().unwrap();
            while self.targets.len() as u64 <= t { self.targets.push(Vec::new()); }
            while self.targets[t as usize].len() as u64 <= g { self.targets[t as usize].push(Vec::new()); }
            while self.targets[t as usize][g as usize].len() as u64 <= c { self.targets[t as usize][g as usize].push(None); }

            self.targets[t as usize][g as usize][c as usize] = Some((s, r));
        }

        // println!("exiting ensure()");
    }
}

// structure in charge of sending data to a Writer, for example the network
struct BinarySender<W: Write> {
    writer:     W,
    sources:    Receiver<(MessageHeader, Vec<u8>)>,
    buffers:    Vec<Vec<Vec<Option<Sender<Vec<u8>>>>>>,
    channels:   Receiver<((u64, u64, u64), Sender<Vec<u8>>)>,
}

impl<W: Write> BinarySender<W> {
    fn new(writer: W,
           targets: u64,
           sources: Receiver<(MessageHeader, Vec<u8>)>,
           channels: Receiver<((u64, u64, u64), Sender<Vec<u8>>)>) -> BinarySender<W> {
        BinarySender {
            writer:     writer,
            sources:    sources,
            buffers:    vec![Vec::new(); targets as usize],
            channels:   channels,
        }
    }

    fn send_loop(&mut self) {
        println!("send loop:\tstarting");
        for (mut header, mut buffer) in self.sources.iter() {
            // println!("send loop:\treceived data");
            header.length = buffer.len() as u64;
            // println!("sending {} bytes", header.length);
            header.write_to(&mut self.writer).unwrap();
            self.writer.write_all(&buffer[..]).unwrap();
            buffer.clear();

            // inline because borrow-checker hates me
            let source = header.source as usize;
            let graph = header.graph as usize;
            let channel = header.channel as usize;

            while self.buffers.len() <= source { self.buffers.push(Vec::new()); }
            while self.buffers[source].len() <= graph { self.buffers[source].push(Vec::new()); }
            while self.buffers[source][graph].len() <= channel {
                self.buffers[source][graph].push(None);
            }

            while let None = self.buffers[source][graph][channel] {
                let ((t, g, c), s) = self.channels.recv().unwrap();
                while self.buffers.len() as u64 <= t { self.buffers.push(Vec::new()); }
                while self.buffers[t as usize].len() as u64 <= g { self.buffers[t as usize].push(Vec::new()); }
                while self.buffers[t as usize][g as usize].len() as u64 <= c { self.buffers[t as usize][g as usize].push(None); }
                self.buffers[t as usize][g as usize][c as usize] = Some(s);
            }
            // end-inline

            self.buffers[source][graph][channel].as_ref().unwrap().send(buffer).unwrap();
        }
    }
}

pub fn initialize_networking(addresses: Vec<String>, my_index: u64, workers: u64) -> Result<Vec<BinaryCommunicator>> {

    let processes = addresses.len() as u64;
    let hosts1 = Arc::new(addresses);
    let hosts2 = hosts1.clone();

    let start_task = Future::spawn(move || start_connections(hosts1, my_index));
    let await_task = Future::spawn(move || await_connections(hosts2, my_index));

    let mut results = try!(await_task.into_inner());

    results.push(None);
    results.append(&mut try!(start_task.into_inner()));

    println!("worker {}:\tinitialization complete", my_index);

    let mut writers = Vec::new();   // handles to the BinarySenders (to present new channels)
    let mut readers = Vec::new();   // handles to the BinaryReceivers (to present new channels)
    let mut senders = Vec::new();   // destinations for serialized data (to send serialized data)

    // for each process, if a stream exists (i.e. not local) ...
    for index in (0..results.len()) {
        if let Some(stream) = results[index].take() {
            let (writer_channels_s, writer_channels_r) = channel();
            let (reader_channels_s, reader_channels_r) = channel();
            let (sender_channels_s, sender_channels_r) = channel();

            writers.push(writer_channels_s);    //
            readers.push(reader_channels_s);    //
            senders.push(sender_channels_s);    //

            let mut sender = BinarySender::new(stream.try_clone().unwrap(), workers, sender_channels_r, writer_channels_r);
            let mut recver = BinaryReceiver::new(stream.try_clone().unwrap(), workers, reader_channels_r);

            // start senders and receivers associated with this stream
            thread::Builder::new().name(format!("send thread {}", index))
                                  .spawn(move || sender.send_loop())
                                  .unwrap();
            thread::Builder::new().name(format!("recv thread {}", index))
                                  .spawn(move || recver.recv_loop())
                                  .unwrap();

        }
    }

    let proc_comms = ProcessCommunicator::new_vector(workers);

    let mut results = Vec::new();
    for (index, proc_comm) in proc_comms.into_iter().enumerate() {
        results.push(BinaryCommunicator {
            inner:          proc_comm,
            index:          my_index * workers + index as u64,
            peers:          workers * processes,
            graph:          0,          // TODO : Fix this
            allocated:      0,
            writers:        writers.clone(),
            readers:        readers.clone(),
            senders:        senders.clone(),
        });
    }

    return Ok(results);
}

// result contains connections [0, my_index - 1].
fn start_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..my_index).map(|_| None).collect();
    for index in (0..my_index) {
        let mut connected = false;
        while !connected {
            match TcpStream::connect(&addresses[index as usize][..]) {
                Ok(mut stream) => {
                    try!(stream.write_u64::<LittleEndian>(my_index));
                    results[index as usize] = Some(stream);
                    println!("worker {}:\tconnection to worker {}", my_index, index);
                    connected = true;
                },
                Err(error) => {
                    println!("worker {}:\terror connecting to worker {}: {}; retrying", my_index, index, error);
                    sleep_ms(1000);
                },
            }
        }
    }

    return Ok(results);
}

// result contains connections [my_index + 1, addresses.len() - 1].
fn await_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..(addresses.len() - my_index as usize - 1)).map(|_| None).collect();
    let listener = try!(TcpListener::bind(&addresses[my_index as usize][..]));

    for _ in (my_index as usize + 1 .. addresses.len()) {
        let mut stream = try!(listener.accept()).0;
        let identifier = try!(stream.read_u64::<LittleEndian>()) as usize;
        results[identifier - my_index as usize - 1] = Some(stream);
        println!("worker {}:\tconnection from worker {}", my_index, identifier);
    }

    return Ok(results);
}
<commit_msg>remove uses of unsafe<commit_after>// use std::old_io::{TcpListener, TcpStream};
// use std::old_io::{Acceptor, Listener, IoResult, MemReader};
use std::thread::sleep_ms;
use std::io::{Read, Write, Result};

use std::net::{TcpListener, TcpStream};
use std::mem::size_of;

use std::sync::mpsc::{Sender, Receiver, channel};

use std::thread;
use std::sync::{Arc, Future};
use std::mem;

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

use communication::{Pushable, BinaryCommunicator, ProcessCommunicator};

// TODO : Much of this only relates to BinaryWriter/BinaryReader based communication, not networking.
// TODO : Could be moved somewhere less networking-specific.

#[derive(Copy, Clone)]
pub struct MessageHeader {
    pub graph:      u64,   // graph identifier
    pub channel:    u64,   // index of channel
    pub source:     u64,   // index of worker sending message
    pub target:     u64,   // index of worker receiving message
    pub length:     u64,   // number of bytes in message
}

impl MessageHeader {
    // returns a header when there is enough supporting data
    fn try_read(bytes: &mut &[u8]) -> Option<MessageHeader> {
        if bytes.len() > size_of::<MessageHeader>() {
            // capture original in case we need to rewind
            let original = *bytes;

            // unclear what order struct initializers run in, so ...
            let graph = bytes.read_u64::<LittleEndian>().unwrap();
            let channel = bytes.read_u64::<LittleEndian>().unwrap();
            let source = bytes.read_u64::<LittleEndian>().unwrap();
            let target = bytes.read_u64::<LittleEndian>().unwrap();
            let length = bytes.read_u64::<LittleEndian>().unwrap();

            let header = MessageHeader {
                graph: graph,
                channel: channel,
                source: source,
                target: target,
                length: length,
            };

            if bytes.len() >= header.length as usize {
                Some(header)
            }
            else {
                // rewind the reader
                *bytes = original;
                None
            }
        }
        else { None }
    }

    fn write_to<W: Write>(&self, writer: &mut W) -> Result<()> {
        try!(writer.write_u64::<LittleEndian>(self.graph));
        try!(writer.write_u64::<LittleEndian>(self.channel));
        try!(writer.write_u64::<LittleEndian>(self.source));
        try!(writer.write_u64::<LittleEndian>(self.target));
        try!(writer.write_u64::<LittleEndian>(self.length));
        Ok(())
    }
}

// structure in charge of receiving data from a Reader, for example the network
struct BinaryReceiver<R: Read> {
    // targets (and u8 returns) indexed by worker, graph, and channel.
    // option because they get filled progressively; alt design might change that.
    targets:    Vec<Vec<Vec<Option<(Sender<Vec<u8>>, Receiver<Vec<u8>>)>>>>,

    reader:     R,          // the generic reader
    buffer:     Vec<u8>,    // current working buffer
    double:     Vec<u8>,    // second working buffer

    staging:    Vec<u8>,    // 1 << 20 of buffer to read into

    // how a BinaryReceiver learns about new channels; indices and corresponding channel pairs
    channels:   Receiver<((u64, u64, u64), Sender<Vec<u8>>, Receiver<Vec<u8>>)>,
}

impl<R: Read> BinaryReceiver<R> {
    fn new(reader: R, targets: u64, channels: Receiver<((u64, u64, u64), Sender<Vec<u8>>, Receiver<Vec<u8>>)>) -> BinaryReceiver<R> {
        BinaryReceiver {
            targets:    (0..targets).map(|_| Vec::new()).collect(),
            reader:     reader,
            buffer:     Vec::new(),
            double:     Vec::new(),
            channels:   channels,

            staging:    vec![0u8; 1 << 20],
        }
    }

    fn recv_loop(&mut self) {
        loop {

            // attempt to read some more bytes into our buffer
            // TODO : We read in to self.staging because extending a Vec<u8> is hard without
            // TODO : using set_len, which is unsafe.
            let read = self.reader.read(&mut self.staging[..]).unwrap_or(0);
            self.buffer.push_all(&self.staging[..read]);

            {
                // get a view of available bytes
                let mut slice = &self.buffer[..];

                while let Some(header) = MessageHeader::try_read(&mut slice) {
                    let h_tgt = header.target as usize;  // target worker
                    let h_grp = header.graph as usize;   // target graph
                    let h_chn = header.channel as usize; // target channel
                    let h_len = header.length as usize;  // length in bytes

                    // println!("looking for {} bytes; have {} bytes", h_len, slice.len());

                    while self.targets.len() <= h_tgt { self.targets.push(Vec::new()) ;}
                    while self.targets[h_tgt].len() <= h_grp { self.targets[h_tgt].push(Vec::new()) ;}
                    while self.targets[h_tgt][h_grp].len() <= h_chn { self.targets[h_tgt][h_grp].push(None) ;}

                    // ensure that the destination exists!
                    while let None = self.targets[h_tgt][h_grp][h_chn] {
                        // receive channel descriptions if any
                        let ((t, g, c), s, r) = self.channels.recv().unwrap();
                        while self.targets.len() as u64 <= t { self.targets.push(Vec::new()); }
                        while self.targets[t as usize].len() as u64 <= g { self.targets[t as usize].push(Vec::new()); }
                        while self.targets[t as usize][g as usize].len() as u64 <= c { self.targets[t as usize][g as usize].push(None); }

                        self.targets[t as usize][g as usize][c as usize] = Some((s, r));
                    }

                    let mut buffer = if let Ok(b) = self.targets[h_tgt][h_grp][h_chn].as_ref().unwrap().1.try_recv() { b }
                                     else { Vec::new() };

                    buffer.clear();
                    buffer.push_all(&slice[..h_len]);

                    slice = &slice[h_len..];

                    self.targets[h_tgt][h_grp][h_chn].as_ref().unwrap().0.send(buffer).unwrap();
                }

                // TODO: way inefficient... =/ Fix! :D
                self.double.clear();
                self.double.push_all(slice);
            }

            mem::swap(&mut self.buffer, &mut self.double);
        }
    }

    fn ensure(&mut self, target: u64, graph: u64, channel: u64) {
        // println!("starting ensure({}, {}, {})", target, graph, channel);

        while self.targets.len() as u64 <= target { self.targets.push(Vec::new()); }
        while self.targets[target as usize].len() as u64 <= graph { self.targets[target as usize].push(Vec::new()); }
        while self.targets[target as usize][graph as usize].len() as u64 <= channel {
            self.targets[target as usize][graph as usize].push(None);
        }

        while let None = self.targets[target as usize][graph as usize][channel as usize] {
            // receive channel descriptions if any
            let ((t, g, c), s, r) = self.channels.recv().unwrap();
            while self.targets.len() as u64 <= t { self.targets.push(Vec::new()); }
            while self.targets[t as usize].len() as u64 <= g { self.targets[t as usize].push(Vec::new()); }
            while self.targets[t as usize][g as usize].len() as u64 <= c { self.targets[t as usize][g as usize].push(None); }

            self.targets[t as usize][g as usize][c as usize] = Some((s, r));
        }

        // println!("exiting ensure()");
    }
}

// structure in charge of sending data to a Writer, for example the network
struct BinarySender<W: Write> {
    writer:     W,
    sources:    Receiver<(MessageHeader, Vec<u8>)>,
    buffers:    Vec<Vec<Vec<Option<Sender<Vec<u8>>>>>>,
    channels:   Receiver<((u64, u64, u64), Sender<Vec<u8>>)>,
}

impl<W: Write> BinarySender<W> {
    fn new(writer: W,
           targets: u64,
           sources: Receiver<(MessageHeader, Vec<u8>)>,
           channels: Receiver<((u64, u64, u64), Sender<Vec<u8>>)>) -> BinarySender<W> {
        BinarySender {
            writer:     writer,
            sources:    sources,
            buffers:    vec![Vec::new(); targets as usize],
            channels:   channels,
        }
    }

    fn send_loop(&mut self) {
        println!("send loop:\tstarting");
        for (mut header, mut buffer) in self.sources.iter() {
            header.length = buffer.len() as u64;
            header.write_to(&mut self.writer).unwrap();
            self.writer.write_all(&buffer[..]).unwrap();
            buffer.clear();

            // inline because borrow-checker hates me
            let source = header.source as usize;
            let graph = header.graph as usize;
            let channel = header.channel as usize;

            while self.buffers.len() <= source { self.buffers.push(Vec::new()); }
            while self.buffers[source].len() <= graph { self.buffers[source].push(Vec::new()); }
            while self.buffers[source][graph].len() <= channel {
                self.buffers[source][graph].push(None);
            }

            while let None = self.buffers[source][graph][channel] {
                let ((t, g, c), s) = self.channels.recv().unwrap();
                while self.buffers.len() as u64 <= t { self.buffers.push(Vec::new()); }
                while self.buffers[t as usize].len() as u64 <= g { self.buffers[t as usize].push(Vec::new()); }
                while self.buffers[t as usize][g as usize].len() as u64 <= c { self.buffers[t as usize][g as usize].push(None); }
                self.buffers[t as usize][g as usize][c as usize] = Some(s);
            }
            // end-inline

            self.buffers[source][graph][channel].as_ref().unwrap().send(buffer).unwrap();
        }
    }
}

pub fn initialize_networking(addresses: Vec<String>, my_index: u64, workers: u64) -> Result<Vec<BinaryCommunicator>> {

    let processes = addresses.len() as u64;
    let hosts1 = Arc::new(addresses);
    let hosts2 = hosts1.clone();

    let start_task = Future::spawn(move || start_connections(hosts1, my_index));
    let await_task = Future::spawn(move || await_connections(hosts2, my_index));

    let mut results = try!(await_task.into_inner());

    results.push(None);
    results.append(&mut try!(start_task.into_inner()));

    println!("worker {}:\tinitialization complete", my_index);

    let mut writers = Vec::new();   // handles to the BinarySenders (to present new channels)
    let mut readers = Vec::new();   // handles to the BinaryReceivers (to present new channels)
    let mut senders = Vec::new();   // destinations for serialized data (to send serialized data)

    // for each process, if a stream exists (i.e. not local) ...
    for index in (0..results.len()) {
        if let Some(stream) = results[index].take() {
            let (writer_channels_s, writer_channels_r) = channel();
            let (reader_channels_s, reader_channels_r) = channel();
            let (sender_channels_s, sender_channels_r) = channel();

            writers.push(writer_channels_s);    //
            readers.push(reader_channels_s);    //
            senders.push(sender_channels_s);    //

            let mut sender = BinarySender::new(stream.try_clone().unwrap(), workers, sender_channels_r, writer_channels_r);
            let mut recver = BinaryReceiver::new(stream.try_clone().unwrap(), workers, reader_channels_r);

            // start senders and receivers associated with this stream
            thread::Builder::new().name(format!("send thread {}", index))
                                  .spawn(move || sender.send_loop())
                                  .unwrap();
            thread::Builder::new().name(format!("recv thread {}", index))
                                  .spawn(move || recver.recv_loop())
                                  .unwrap();

        }
    }

    let proc_comms = ProcessCommunicator::new_vector(workers);

    let mut results = Vec::new();
    for (index, proc_comm) in proc_comms.into_iter().enumerate() {
        results.push(BinaryCommunicator {
            inner:          proc_comm,
            index:          my_index * workers + index as u64,
            peers:          workers * processes,
            graph:          0,          // TODO : Fix this
            allocated:      0,
            writers:        writers.clone(),
            readers:        readers.clone(),
            senders:        senders.clone(),
        });
    }

    return Ok(results);
}

// result contains connections [0, my_index - 1].
fn start_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..my_index).map(|_| None).collect();
    for index in (0..my_index) {
        let mut connected = false;
        while !connected {
            match TcpStream::connect(&addresses[index as usize][..]) {
                Ok(mut stream) => {
                    try!(stream.write_u64::<LittleEndian>(my_index));
                    results[index as usize] = Some(stream);
                    println!("worker {}:\tconnection to worker {}", my_index, index);
                    connected = true;
                },
                Err(error) => {
                    println!("worker {}:\terror connecting to worker {}: {}; retrying", my_index, index, error);
                    sleep_ms(1000);
                },
            }
        }
    }

    return Ok(results);
}

// result contains connections [my_index + 1, addresses.len() - 1].
fn await_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..(addresses.len() - my_index as usize - 1)).map(|_| None).collect();
    let listener = try!(TcpListener::bind(&addresses[my_index as usize][..]));

    for _ in (my_index as usize + 1 .. addresses.len()) {
        let mut stream = try!(listener.accept()).0;
        let identifier = try!(stream.read_u64::<LittleEndian>()) as usize;
        results[identifier - my_index as usize - 1] = Some(stream);
        println!("worker {}:\tconnection from worker {}", my_index, identifier);
    }

    return Ok(results);
}
<|endoftext|>


<commit_before>use crate::Msg;
use chrono::{NaiveDate};
use seed::prelude::*;

pub fn render() -> seed::dom_types::Node<Msg> {
    div![
        h1!["News"],
        br![],
        br![],
        br![],
        El::from_html("

Date	News

28th July 2019	bigprimes.net has been rewritten from the ground up using rust!
All archives have been retired in favour of client side processing in web assembly.

22nd January 2019	Ethereum bounty contracts have now been added for anyone that would like to try to push the boundaries of human knowledge. The first contract is a competition for the correct solution to a³+b³+c³ = 33. Tweet me if you need assistance using these contracts!

10th March 2018	Added torrents for the first million primes and first billion prime numbers.

12th November 2017	Site is now running on AWS Lambda, but can still fallback to regular VM hosting if ever needed. Site is now ~40% covered by unit tests.

13th November 2016	Site source code has been converted to PHP7 with Silex framework. Some methods have also been moved to cpp from PHP https://github.com/craigmayhew/bigprimes.net/

28th February 2014	You can now find the websites php source code here https://github.com/craigmayhew/bigprimes.net/

19th November 2011	Thank you to Yu Kwong Yiu Wilson for the donation!

13th July 2011	We are retiring the distributed computing client. Thank you all for your help and processing cycles.
        Watch this space for an open source GPU client coming soon...

10th February 2010	We have added a page that shows the sum of the digits of prime numbers (now retired).

1st February 2010	Thanks to everyone for donating computer time, we are now upto 1.4 billion primes. We now also have a facebook group where you get news updates and show your support for the project!

28th September 2009	Thanks for all your help! We made it to one billion prime numbers! Please keep on donating processor time as we still have plenty of storage for the prime numbers. Our database is now more than double the size (300 million primes) and we've put in the capacity to keep growing. To view our current progress please visit the status page.

18th August 2009	It's been a while but we have been very busy. We've put together a distributed computing client written in javascript. Our database is now more than double the size (300 million primes) and we've put in the capacity to keep growing. To view our current progress please visit the status page.

17th July 2008	We've now added a Forum (now retired) which can be found on the navigation links on the left.

14th July 2008	Someone named Kirk just emailed me to say the download links wern't working. I've now fixed this. Thanks Kirk!

4th July 2008	Added much faster code to the cruncher so that we can handle more of your page loads! Lots of little updates and some reorganizing of the site.

23rd June 2007	Added the Downloads section.

11th February 2007	Added the Fibonacci number archive containing the first 70331 Fibonacci numbers.

16th January 2007	Added the 44th Mersenne Prime number to the archive.

12th January 2007	The Archives are now more organized.

28th September 2005	We have managed to archive the first 100 million prime numbers.

20th May 2005	We have managed to archive the first 75 million prime numbers.

16th May 2005	We have managed to archive the first 50 million prime numbers.

14th May 2005	We have managed to archive the first 10 million prime numbers.

13th May 2005	We have managed to archive the first 1 million prime numbers.

"),
    ]
}<commit_msg>Corrected malformed link<commit_after>use crate::Msg;
use chrono::{NaiveDate};
use seed::prelude::*;

pub fn render() -> seed::dom_types::Node<Msg> {
    div![
        h1!["News"],
        br![],
        br![],
        br![],
        El::from_html("

Date	News

28th July 2019	bigprimes.net has been rewritten from the ground up using rust!
All archives have been retired in favour of client side processing in web assembly.

22nd January 2019	Ethereum bounty contracts have now been added for anyone that would like to try to push the boundaries of human knowledge. The first contract is a competition for the correct solution to a³+b³+c³ = 33. Tweet me if you need assistance using these contracts!

10th March 2018	Added torrents for the first million primes and first billion prime numbers.

12th November 2017	Site is now running on AWS Lambda, but can still fallback to regular VM hosting if ever needed. Site is now ~40% covered by unit tests.

13th November 2016	Site source code has been converted to PHP7 with Silex framework. Some methods have also been moved to cpp from PHP https://github.com/craigmayhew/bigprimes.net/

28th February 2014	You can now find the websites php source code here https://github.com/craigmayhew/bigprimes.net/

19th November 2011	Thank you to Yu Kwong Yiu Wilson for the donation!

13th July 2011	We are retiring the distributed computing client. Thank you all for your help and processing cycles.
        Watch this space for an open source GPU client coming soon...

10th February 2010	We have added a page that shows the sum of the digits of prime numbers (now retired).

1st February 2010	Thanks to everyone for donating computer time, we are now upto 1.4 billion primes. We now also have a facebook group where you get news updates and show your support for the project!

28th September 2009	Thanks for all your help! We made it to one billion prime numbers! Please keep on donating processor time as we still have plenty of storage for the prime numbers. Our database is now more than double the size (300 million primes) and we've put in the capacity to keep growing. To view our current progress please visit the status page.

18th August 2009	It's been a while but we have been very busy. We've put together a distributed computing client written in javascript. Our database is now more than double the size (300 million primes) and we've put in the capacity to keep growing. To view our current progress please visit the status page.

17th July 2008	We've now added a Forum (now retired) which can be found on the navigation links on the left.

14th July 2008	Someone named Kirk just emailed me to say the download links wern't working. I've now fixed this. Thanks Kirk!

4th July 2008	Added much faster code to the cruncher so that we can handle more of your page loads! Lots of little updates and some reorganizing of the site.

23rd June 2007	Added the Downloads section.

11th February 2007	Added the Fibonacci number archive containing the first 70331 Fibonacci numbers.

16th January 2007	Added the 44th Mersenne Prime number to the archive.

12th January 2007	The Archives are now more organized.

28th September 2005	We have managed to archive the first 100 million prime numbers.

20th May 2005	We have managed to archive the first 75 million prime numbers.

16th May 2005	We have managed to archive the first 50 million prime numbers.

14th May 2005	We have managed to archive the first 10 million prime numbers.

13th May 2005	We have managed to archive the first 1 million prime numbers.

"),
    ]
}<|endoftext|>


<commit_before>use ::quote::Tokens;
use ::syn::Ident;
use ::yaml_rust::Yaml;

use infer::datatype;
use infer::path;
use infer::TokensResult;

type FieldsAndSupportingTypes = (Vec<Tokens>, Tokens, Vec<Tokens>);

fn infer_ref(schema: &Yaml, required: &Vec<Yaml>) -> FieldsAndSupportingTypes {
    let mut fields: Vec<Tokens> = Vec::new();
    let mut additional_types: Vec<Tokens> = Vec::new();
    let mut lifetime = quote!();

    for (field, schema) in schema["properties"].as_hash()
        .expect("Properties must be a map.")
    {
        let field_name = field.as_str()
            .expect("Property must be a string.");
        let field_ident = Ident::new(field_name);
        let (field_type, has_lifetime, additional_type) = datatype::infer_v3(&schema).unwrap();
        let mandate: Tokens;

        if let Some(true) = schema["required"].as_bool() {
            mandate = quote!(::tapioca::datatype::Required);
        } else if required.contains(field) {
            mandate = quote!(::tapioca::datatype::Required);
        } else {
            mandate = quote!(::tapioca::datatype::Optional);
        }

        if has_lifetime {
            lifetime = quote!('a);
            fields.push(quote!{
                #[serde(borrow)]
                #field_ident: #mandate<#field_type>
            });
        } else {
            fields.push(quote!{ #field_ident: #mandate<#field_type> });
        }

        if let Some(additional_type) = additional_type {
            additional_types.push(additional_type);
        }
    }

    (fields, lifetime, additional_types)
}

pub(super) fn infer_v3(schema: &Yaml) -> TokensResult {
    let paths = schema["paths"].clone();
    let path_impls: Vec<Tokens> = paths.as_hash()
        .expect("Paths must be a map.")
        .iter()
        .map(|(path, path_schema)| path::infer_v3(
            path.as_str().expect("Path must be a string."), &path_schema
        ).unwrap())
        .collect();

    let api_url = schema["servers"][0]["url"].as_str()
        .expect("Must have at least one server URL.");

    let mut schema_ref_struct_defs: Vec<Tokens> = Vec::new();
    for (schema_ref, schema) in schema["components"]["schemas"].as_hash()
        .expect("#/components/schemas must be a map.")
    {
        let schema_ref_name = schema_ref.as_str()
            .expect("$ref name must be a string.");
        let ident = Ident::new(schema_ref_name);
        let (fields, lifetime, additional_types) = infer_ref(
            schema,
            schema["required"].as_vec().unwrap_or(&Vec::new())
        );

        schema_ref_struct_defs.push(quote! {
            #(#additional_types)*

            #[derive(Deserialize)]
            pub struct #ident<#lifetime> {
                #(#fields),*
            }
        });
    }

    Ok(quote! {
        mod schema_ref {
            use super::schema_ref;

            #(#schema_ref_struct_defs)*
        }

        const API_URL: &'static str = #api_url;

        #(#path_impls)*
    })
}
<commit_msg>Support $ref type schemata for non-object types<commit_after>use ::quote::Tokens;
use ::syn::Ident;
use ::yaml_rust::Yaml;

use infer::datatype;
use infer::path;
use infer::TokensResult;

type FieldsAndSupportingTypes = (Vec<Tokens>, Tokens, Vec<Tokens>);

fn infer_ref_obj(schema: &Yaml, required: &Vec<Yaml>) -> FieldsAndSupportingTypes {
    let mut fields: Vec<Tokens> = Vec::new();
    let mut additional_types: Vec<Tokens> = Vec::new();
    let mut lifetime = quote!();

    for (field, schema) in schema["properties"].as_hash()
        .expect("Properties must be a map.")
    {
        let field_name = field.as_str()
            .expect("Property must be a string.");
        let field_ident = Ident::new(field_name);
        let (ty, has_lt, maybe_at) = datatype::infer_v3(&schema).unwrap();
        let mandate: Tokens;

        if let Some(true) = schema["required"].as_bool() {
            mandate = quote!(::tapioca::datatype::Required);
        } else if required.contains(field) {
            mandate = quote!(::tapioca::datatype::Required);
        } else {
            mandate = quote!(::tapioca::datatype::Optional);
        }

        if has_lt {
            lifetime = quote!('a);
            fields.push(quote!{
                #[serde(borrow)]
                #field_ident: #mandate<#ty>
            });
        } else {
            fields.push(quote!{ #field_ident: #mandate<#ty> });
        }

        if let Some(additional_type) = maybe_at {
            additional_types.push(additional_type);
        }
    }

    (fields, lifetime, additional_types)
}

fn infer_ref(ident: &Ident, schema: &Yaml, required: &Vec<Yaml>) -> TokensResult {
    match schema["properties"].as_hash() {
        Some(_) => {
            let (fields, lifetime, additionals) = infer_ref_obj(&schema, &required);

            Ok(quote! {
                #(#additionals)*

                #[derive(Deserialize)]
                pub struct #ident<#lifetime> {
                    #(#fields),*
                }
            })
        },
        None => {
            let (alias_to, has_lt, additional) = match datatype::infer_v3(&schema)? {
                (ty, has_lt, Some(additional)) => (ty, has_lt, additional),
                (ty, has_lt, None) => (ty, has_lt, quote!{}),
            };
            let lifetime = match has_lt {
                true => quote!('a),
                false => quote!(),
            };

            Ok(quote! {
                #additional

                pub type #ident<#lifetime> = #alias_to;
            })
        },
    }
}

pub(super) fn infer_v3(schema: &Yaml) -> TokensResult {
    let paths = schema["paths"].clone();
    let path_impls: Vec<Tokens> = paths.as_hash()
        .expect("Paths must be a map.")
        .iter()
        .map(|(path, path_schema)| path::infer_v3(
            path.as_str().expect("Path must be a string."), &path_schema
        ).unwrap())
        .collect();

    let api_url = schema["servers"][0]["url"].as_str()
        .expect("Must have at least one server URL.");

    let mut schema_ref_defs: Vec<Tokens> = Vec::new();
    for (schema_ref, schema) in schema["components"]["schemas"].as_hash()
        .expect("#/components/schemas must be a map.")
    {
        let schema_ref_name = schema_ref.as_str()
            .expect("$ref name must be a string.");
        schema_ref_defs.push(infer_ref(
                &Ident::new(schema_ref_name),
                &schema,
                &schema["required"].as_vec().unwrap_or(&Vec::new())
        )?);
    }

    Ok(quote! {
        mod schema_ref {
            use super::schema_ref;

            #(#schema_ref_defs)*
        }

        const API_URL: &'static str = #api_url;

        #(#path_impls)*
    })
}
<|endoftext|>


<commit_before>use core::ptr::*;
use core::cell::RefCell;

#[test]
fn test() {
    unsafe {
        struct Pair {
            fst: isize,
            snd: isize
        };
        let mut p = Pair {fst: 10, snd: 20};
        let pptr: *mut Pair = &mut p;
        let iptr: *mut isize = pptr as *mut isize;
        assert_eq!(*iptr, 10);
        *iptr = 30;
        assert_eq!(*iptr, 30);
        assert_eq!(p.fst, 30);

        *pptr = Pair {fst: 50, snd: 60};
        assert_eq!(*iptr, 50);
        assert_eq!(p.fst, 50);
        assert_eq!(p.snd, 60);

        let v0 = vec![32000u16, 32001u16, 32002u16];
        let mut v1 = vec![0u16, 0u16, 0u16];

        copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1);
        assert!((v1[0] == 0u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 0u16));
        copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1);
        assert!((v1[0] == 32002u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 0u16));
        copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1);
        assert!((v1[0] == 32002u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 32000u16));
    }
}

#[test]
#[cfg(not(miri))] // This test performs invalid OOB pointer arithmetic
fn test_is_null() {
    let p: *const isize = null();
    assert!(p.is_null());

    let q = unsafe { p.offset(1) };
    assert!(!q.is_null());

    let mp: *mut isize = null_mut();
    assert!(mp.is_null());

    let mq = unsafe { mp.offset(1) };
    assert!(!mq.is_null());

    // Pointers to unsized types -- slices
    let s: &mut [u8] = &mut [1, 2, 3];
    let cs: *const [u8] = s;
    assert!(!cs.is_null());

    let ms: *mut [u8] = s;
    assert!(!ms.is_null());

    let cz: *const [u8] = &[];
    assert!(!cz.is_null());

    let mz: *mut [u8] = &mut [];
    assert!(!mz.is_null());

    let ncs: *const [u8] = null::<[u8; 3]>();
    assert!(ncs.is_null());

    let nms: *mut [u8] = null_mut::<[u8; 3]>();
    assert!(nms.is_null());

    // Pointers to unsized types -- trait objects
    let ci: *const dyn ToString = &3;
    assert!(!ci.is_null());

    let mi: *mut dyn ToString = &mut 3;
    assert!(!mi.is_null());

    let nci: *const dyn ToString = null::<isize>();
    assert!(nci.is_null());

    let nmi: *mut dyn ToString = null_mut::<isize>();
    assert!(nmi.is_null());
}

#[test]
fn test_as_ref() {
    unsafe {
        let p: *const isize = null();
        assert_eq!(p.as_ref(), None);

        let q: *const isize = &2;
        assert_eq!(q.as_ref().unwrap(), &2);

        let p: *mut isize = null_mut();
        assert_eq!(p.as_ref(), None);

        let q: *mut isize = &mut 2;
        assert_eq!(q.as_ref().unwrap(), &2);

        // Lifetime inference
        let u = 2isize;
        {
            let p = &u as *const isize;
            assert_eq!(p.as_ref().unwrap(), &2);
        }

        // Pointers to unsized types -- slices
        let s: &mut [u8] = &mut [1, 2, 3];
        let cs: *const [u8] = s;
        assert_eq!(cs.as_ref(), Some(&*s));

        let ms: *mut [u8] = s;
        assert_eq!(ms.as_ref(), Some(&*s));

        let cz: *const [u8] = &[];
        assert_eq!(cz.as_ref(), Some(&[][..]));

        let mz: *mut [u8] = &mut [];
        assert_eq!(mz.as_ref(), Some(&[][..]));

        let ncs: *const [u8] = null::<[u8; 3]>();
        assert_eq!(ncs.as_ref(), None);

        let nms: *mut [u8] = null_mut::<[u8; 3]>();
        assert_eq!(nms.as_ref(), None);

        // Pointers to unsized types -- trait objects
        let ci: *const dyn ToString = &3;
        assert!(ci.as_ref().is_some());

        let mi: *mut dyn ToString = &mut 3;
        assert!(mi.as_ref().is_some());

        let nci: *const dyn ToString = null::<isize>();
        assert!(nci.as_ref().is_none());

        let nmi: *mut dyn ToString = null_mut::<isize>();
        assert!(nmi.as_ref().is_none());
    }
}

#[test]
#[cfg(not(miri))] // This test is UB according to Stacked Borrows
fn test_as_mut() {
    unsafe {
        let p: *mut isize = null_mut();
        assert!(p.as_mut() == None);

        let q: *mut isize = &mut 2;
        assert!(q.as_mut().unwrap() == &mut 2);

        // Lifetime inference
        let mut u = 2isize;
        {
            let p = &mut u as *mut isize;
            assert!(p.as_mut().unwrap() == &mut 2);
        }

        // Pointers to unsized types -- slices
        let s: &mut [u8] = &mut [1, 2, 3];
        let ms: *mut [u8] = s;
        assert_eq!(ms.as_mut(), Some(s));

        let mz: *mut [u8] = &mut [];
        assert_eq!(mz.as_mut(), Some(&mut [][..]));

        let nms: *mut [u8] = null_mut::<[u8; 3]>();
        assert_eq!(nms.as_mut(), None);

        // Pointers to unsized types -- trait objects
        let mi: *mut dyn ToString = &mut 3;
        assert!(mi.as_mut().is_some());

        let nmi: *mut dyn ToString = null_mut::<isize>();
        assert!(nmi.as_mut().is_none());
    }
}

#[test]
fn test_ptr_addition() {
    unsafe {
        let xs = vec![5; 16];
        let mut ptr = xs.as_ptr();
        let end = ptr.offset(16);

        while ptr < end {
            assert_eq!(*ptr, 5);
            ptr = ptr.offset(1);
        }

        let mut xs_mut = xs;
        let mut m_ptr = xs_mut.as_mut_ptr();
        let m_end = m_ptr.offset(16);

        while m_ptr < m_end {
            *m_ptr += 5;
            m_ptr = m_ptr.offset(1);
        }

        assert!(xs_mut == vec![10; 16]);
    }
}

#[test]
#[cfg(not(miri))] // This test performs invalid OOB pointer arithmetic
fn test_ptr_subtraction() {
    unsafe {
        let xs = vec![0,1,2,3,4,5,6,7,8,9];
        let mut idx = 9;
        let ptr = xs.as_ptr();

        while idx >= 0 {
            assert_eq!(*(ptr.offset(idx as isize)), idx as isize);
            idx = idx - 1;
        }

        let mut xs_mut = xs;
        let m_start = xs_mut.as_mut_ptr();
        let mut m_ptr = m_start.offset(9);

        while m_ptr >= m_start {
            *m_ptr += *m_ptr;
            m_ptr = m_ptr.offset(-1);
        }

        assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
    }
}

#[test]
fn test_set_memory() {
    let mut xs = [0u8; 20];
    let ptr = xs.as_mut_ptr();
    unsafe { write_bytes(ptr, 5u8, xs.len()); }
    assert!(xs == [5u8; 20]);
}

#[test]
fn test_unsized_nonnull() {
    let xs: &[i32] = &[1, 2, 3];
    let ptr = unsafe { NonNull::new_unchecked(xs as *const [i32] as *mut [i32]) };
    let ys = unsafe { ptr.as_ref() };
    let zs: &[i32] = &[1, 2, 3];
    assert!(ys == zs);
}

#[test]
#[allow(warnings)]
#[cfg(not(miri))] // Miri cannot hash pointers
// Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
// ABI, or even point to an actual executable code, because the function itself is never invoked.
#[no_mangle]
pub fn test_variadic_fnptr() {
    use core::hash::{Hash, SipHasher};
    extern {
        fn test_variadic_fnptr(_: u64, ...) -> f64;
    }
    let p: unsafe extern fn(u64, ...) -> f64 = test_variadic_fnptr;
    let q = p.clone();
    assert_eq!(p, q);
    assert!(!(p < q));
    let mut s = SipHasher::new();
    assert_eq!(p.hash(&mut s), q.hash(&mut s));
}

#[test]
fn write_unaligned_drop() {
    thread_local! {
        static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
    }

    struct Dropper(u32);

    impl Drop for Dropper {
        fn drop(&mut self) {
            DROPS.with(|d| d.borrow_mut().push(self.0));
        }
    }

    {
        let c = Dropper(0);
        let mut t = Dropper(1);
        unsafe { write_unaligned(&mut t, c); }
    }
    DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
}

#[test]
#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
fn align_offset_zst() {
    // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
    // all, because no amount of elements will align the pointer.
    let mut p = 1;
    while p < 1024 {
        assert_eq!((p as *const ()).align_offset(p), 0);
        if p != 1 {
            assert_eq!(((p + 1) as *const ()).align_offset(p), !0);
        }
        p = (p + 1).next_power_of_two();
    }
}

#[test]
#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
fn align_offset_stride1() {
    // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
    // number of bytes.
    let mut align = 1;
    while align < 1024 {
        for ptr in 1..2*align {
            let expected = ptr % align;
            let offset = if expected == 0 { 0 } else { align - expected };
            assert_eq!((ptr as *const u8).align_offset(align), offset,
            "ptr = {}, align = {}, size = 1", ptr, align);
        }
        align = (align + 1).next_power_of_two();
    }
}

#[test]
#[cfg(not(miri))] // Miri is too slow
fn align_offset_weird_strides() {
    #[repr(packed)]
    struct A3(u16, u8);
    struct A4(u32);
    #[repr(packed)]
    struct A5(u32, u8);
    #[repr(packed)]
    struct A6(u32, u16);
    #[repr(packed)]
    struct A7(u32, u16, u8);
    #[repr(packed)]
    struct A8(u32, u32);
    #[repr(packed)]
    struct A9(u32, u32, u8);
    #[repr(packed)]
    struct A10(u32, u32, u16);

    unsafe fn test_weird_stride<T>(ptr: *const T, align: usize) -> bool {
        let numptr = ptr as usize;
        let mut expected = usize::max_value();
        // Naive but definitely correct way to find the *first* aligned element of stride::<T>.
        for el in 0..align {
            if (numptr + el * ::std::mem::size_of::<T>()) % align == 0 {
                expected = el;
                break;
            }
        }
        let got = ptr.align_offset(align);
        if got != expected {
            eprintln!("aligning {:p} (with stride of {}) to {}, expected {}, got {}", ptr,
                      ::std::mem::size_of::<T>(), align, expected, got);
            return true;
        }
        return false;
    }

    // For pointers of stride != 1, we verify the algorithm against the naivest possible
    // implementation
    let mut align = 1;
    let mut x = false;
    while align < 1024 {
        for ptr in 1usize..4*align {
            unsafe {
                x |= test_weird_stride::<A3>(ptr as *const A3, align);
                x |= test_weird_stride::<A4>(ptr as *const A4, align);
                x |= test_weird_stride::<A5>(ptr as *const A5, align);
                x |= test_weird_stride::<A6>(ptr as *const A6, align);
                x |= test_weird_stride::<A7>(ptr as *const A7, align);
                x |= test_weird_stride::<A8>(ptr as *const A8, align);
                x |= test_weird_stride::<A9>(ptr as *const A9, align);
                x |= test_weird_stride::<A10>(ptr as *const A10, align);
            }
        }
        align = (align + 1).next_power_of_two();
    }
    assert!(!x);
}
<commit_msg>Rollup merge of #58536 - xfix:remove-ub-in-pointer-tests, r=RalfJung<commit_after>use core::ptr::*;
use core::cell::RefCell;

#[test]
fn test() {
    unsafe {
        struct Pair {
            fst: isize,
            snd: isize
        };
        let mut p = Pair {fst: 10, snd: 20};
        let pptr: *mut Pair = &mut p;
        let iptr: *mut isize = pptr as *mut isize;
        assert_eq!(*iptr, 10);
        *iptr = 30;
        assert_eq!(*iptr, 30);
        assert_eq!(p.fst, 30);

        *pptr = Pair {fst: 50, snd: 60};
        assert_eq!(*iptr, 50);
        assert_eq!(p.fst, 50);
        assert_eq!(p.snd, 60);

        let v0 = vec![32000u16, 32001u16, 32002u16];
        let mut v1 = vec![0u16, 0u16, 0u16];

        copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1);
        assert!((v1[0] == 0u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 0u16));
        copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1);
        assert!((v1[0] == 32002u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 0u16));
        copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1);
        assert!((v1[0] == 32002u16 &&
                 v1[1] == 32001u16 &&
                 v1[2] == 32000u16));
    }
}

#[test]
fn test_is_null() {
    let p: *const isize = null();
    assert!(p.is_null());

    let q = p.wrapping_offset(1);
    assert!(!q.is_null());

    let mp: *mut isize = null_mut();
    assert!(mp.is_null());

    let mq = mp.wrapping_offset(1);
    assert!(!mq.is_null());

    // Pointers to unsized types -- slices
    let s: &mut [u8] = &mut [1, 2, 3];
    let cs: *const [u8] = s;
    assert!(!cs.is_null());

    let ms: *mut [u8] = s;
    assert!(!ms.is_null());

    let cz: *const [u8] = &[];
    assert!(!cz.is_null());

    let mz: *mut [u8] = &mut [];
    assert!(!mz.is_null());

    let ncs: *const [u8] = null::<[u8; 3]>();
    assert!(ncs.is_null());

    let nms: *mut [u8] = null_mut::<[u8; 3]>();
    assert!(nms.is_null());

    // Pointers to unsized types -- trait objects
    let ci: *const dyn ToString = &3;
    assert!(!ci.is_null());

    let mi: *mut dyn ToString = &mut 3;
    assert!(!mi.is_null());

    let nci: *const dyn ToString = null::<isize>();
    assert!(nci.is_null());

    let nmi: *mut dyn ToString = null_mut::<isize>();
    assert!(nmi.is_null());
}

#[test]
fn test_as_ref() {
    unsafe {
        let p: *const isize = null();
        assert_eq!(p.as_ref(), None);

        let q: *const isize = &2;
        assert_eq!(q.as_ref().unwrap(), &2);

        let p: *mut isize = null_mut();
        assert_eq!(p.as_ref(), None);

        let q: *mut isize = &mut 2;
        assert_eq!(q.as_ref().unwrap(), &2);

        // Lifetime inference
        let u = 2isize;
        {
            let p = &u as *const isize;
            assert_eq!(p.as_ref().unwrap(), &2);
        }

        // Pointers to unsized types -- slices
        let s: &mut [u8] = &mut [1, 2, 3];
        let cs: *const [u8] = s;
        assert_eq!(cs.as_ref(), Some(&*s));

        let ms: *mut [u8] = s;
        assert_eq!(ms.as_ref(), Some(&*s));

        let cz: *const [u8] = &[];
        assert_eq!(cz.as_ref(), Some(&[][..]));

        let mz: *mut [u8] = &mut [];
        assert_eq!(mz.as_ref(), Some(&[][..]));

        let ncs: *const [u8] = null::<[u8; 3]>();
        assert_eq!(ncs.as_ref(), None);

        let nms: *mut [u8] = null_mut::<[u8; 3]>();
        assert_eq!(nms.as_ref(), None);

        // Pointers to unsized types -- trait objects
        let ci: *const dyn ToString = &3;
        assert!(ci.as_ref().is_some());

        let mi: *mut dyn ToString = &mut 3;
        assert!(mi.as_ref().is_some());

        let nci: *const dyn ToString = null::<isize>();
        assert!(nci.as_ref().is_none());

        let nmi: *mut dyn ToString = null_mut::<isize>();
        assert!(nmi.as_ref().is_none());
    }
}

#[test]
#[cfg(not(miri))] // This test is UB according to Stacked Borrows
fn test_as_mut() {
    unsafe {
        let p: *mut isize = null_mut();
        assert!(p.as_mut() == None);

        let q: *mut isize = &mut 2;
        assert!(q.as_mut().unwrap() == &mut 2);

        // Lifetime inference
        let mut u = 2isize;
        {
            let p = &mut u as *mut isize;
            assert!(p.as_mut().unwrap() == &mut 2);
        }

        // Pointers to unsized types -- slices
        let s: &mut [u8] = &mut [1, 2, 3];
        let ms: *mut [u8] = s;
        assert_eq!(ms.as_mut(), Some(s));

        let mz: *mut [u8] = &mut [];
        assert_eq!(mz.as_mut(), Some(&mut [][..]));

        let nms: *mut [u8] = null_mut::<[u8; 3]>();
        assert_eq!(nms.as_mut(), None);

        // Pointers to unsized types -- trait objects
        let mi: *mut dyn ToString = &mut 3;
        assert!(mi.as_mut().is_some());

        let nmi: *mut dyn ToString = null_mut::<isize>();
        assert!(nmi.as_mut().is_none());
    }
}

#[test]
fn test_ptr_addition() {
    unsafe {
        let xs = vec![5; 16];
        let mut ptr = xs.as_ptr();
        let end = ptr.offset(16);

        while ptr < end {
            assert_eq!(*ptr, 5);
            ptr = ptr.offset(1);
        }

        let mut xs_mut = xs;
        let mut m_ptr = xs_mut.as_mut_ptr();
        let m_end = m_ptr.offset(16);

        while m_ptr < m_end {
            *m_ptr += 5;
            m_ptr = m_ptr.offset(1);
        }

        assert!(xs_mut == vec![10; 16]);
    }
}

#[test]
fn test_ptr_subtraction() {
    unsafe {
        let xs = vec![0,1,2,3,4,5,6,7,8,9];
        let mut idx = 9;
        let ptr = xs.as_ptr();

        while idx >= 0 {
            assert_eq!(*(ptr.offset(idx as isize)), idx as isize);
            idx = idx - 1;
        }

        let mut xs_mut = xs;
        let m_start = xs_mut.as_mut_ptr();
        let mut m_ptr = m_start.offset(9);

        loop {
            *m_ptr += *m_ptr;
            if m_ptr == m_start {
                break;
            }
            m_ptr = m_ptr.offset(-1);
        }

        assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
    }
}

#[test]
fn test_set_memory() {
    let mut xs = [0u8; 20];
    let ptr = xs.as_mut_ptr();
    unsafe { write_bytes(ptr, 5u8, xs.len()); }
    assert!(xs == [5u8; 20]);
}

#[test]
fn test_unsized_nonnull() {
    let xs: &[i32] = &[1, 2, 3];
    let ptr = unsafe { NonNull::new_unchecked(xs as *const [i32] as *mut [i32]) };
    let ys = unsafe { ptr.as_ref() };
    let zs: &[i32] = &[1, 2, 3];
    assert!(ys == zs);
}

#[test]
#[allow(warnings)]
#[cfg(not(miri))] // Miri cannot hash pointers
// Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
// ABI, or even point to an actual executable code, because the function itself is never invoked.
#[no_mangle]
pub fn test_variadic_fnptr() {
    use core::hash::{Hash, SipHasher};
    extern {
        fn test_variadic_fnptr(_: u64, ...) -> f64;
    }
    let p: unsafe extern fn(u64, ...) -> f64 = test_variadic_fnptr;
    let q = p.clone();
    assert_eq!(p, q);
    assert!(!(p < q));
    let mut s = SipHasher::new();
    assert_eq!(p.hash(&mut s), q.hash(&mut s));
}

#[test]
fn write_unaligned_drop() {
    thread_local! {
        static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
    }

    struct Dropper(u32);

    impl Drop for Dropper {
        fn drop(&mut self) {
            DROPS.with(|d| d.borrow_mut().push(self.0));
        }
    }

    {
        let c = Dropper(0);
        let mut t = Dropper(1);
        unsafe { write_unaligned(&mut t, c); }
    }
    DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
}

#[test]
#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
fn align_offset_zst() {
    // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
    // all, because no amount of elements will align the pointer.
    let mut p = 1;
    while p < 1024 {
        assert_eq!((p as *const ()).align_offset(p), 0);
        if p != 1 {
            assert_eq!(((p + 1) as *const ()).align_offset(p), !0);
        }
        p = (p + 1).next_power_of_two();
    }
}

#[test]
#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
fn align_offset_stride1() {
    // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
    // number of bytes.
    let mut align = 1;
    while align < 1024 {
        for ptr in 1..2*align {
            let expected = ptr % align;
            let offset = if expected == 0 { 0 } else { align - expected };
            assert_eq!((ptr as *const u8).align_offset(align), offset,
            "ptr = {}, align = {}, size = 1", ptr, align);
        }
        align = (align + 1).next_power_of_two();
    }
}

#[test]
#[cfg(not(miri))] // Miri is too slow
fn align_offset_weird_strides() {
    #[repr(packed)]
    struct A3(u16, u8);
    struct A4(u32);
    #[repr(packed)]
    struct A5(u32, u8);
    #[repr(packed)]
    struct A6(u32, u16);
    #[repr(packed)]
    struct A7(u32, u16, u8);
    #[repr(packed)]
    struct A8(u32, u32);
    #[repr(packed)]
    struct A9(u32, u32, u8);
    #[repr(packed)]
    struct A10(u32, u32, u16);

    unsafe fn test_weird_stride<T>(ptr: *const T, align: usize) -> bool {
        let numptr = ptr as usize;
        let mut expected = usize::max_value();
        // Naive but definitely correct way to find the *first* aligned element of stride::<T>.
        for el in 0..align {
            if (numptr + el * ::std::mem::size_of::<T>()) % align == 0 {
                expected = el;
                break;
            }
        }
        let got = ptr.align_offset(align);
        if got != expected {
            eprintln!("aligning {:p} (with stride of {}) to {}, expected {}, got {}", ptr,
                      ::std::mem::size_of::<T>(), align, expected, got);
            return true;
        }
        return false;
    }

    // For pointers of stride != 1, we verify the algorithm against the naivest possible
    // implementation
    let mut align = 1;
    let mut x = false;
    while align < 1024 {
        for ptr in 1usize..4*align {
            unsafe {
                x |= test_weird_stride::<A3>(ptr as *const A3, align);
                x |= test_weird_stride::<A4>(ptr as *const A4, align);
                x |= test_weird_stride::<A5>(ptr as *const A5, align);
                x |= test_weird_stride::<A6>(ptr as *const A6, align);
                x |= test_weird_stride::<A7>(ptr as *const A7, align);
                x |= test_weird_stride::<A8>(ptr as *const A8, align);
                x |= test_weird_stride::<A9>(ptr as *const A9, align);
                x |= test_weird_stride::<A10>(ptr as *const A10, align);
            }
        }
        align = (align + 1).next_power_of_two();
    }
    assert!(!x);
}
<|endoftext|>


<commit_before>// TODO: close events (port from old stdweb branch)
// TODO: pointer locking (stdweb PR required)
// TODO: fullscreen API (stdweb PR required)

mod device;
mod error;
mod event_loop;
mod monitor;
mod window;

#[cfg(feature = "web-sys")]
#[path = "web_sys/mod.rs"]
mod backend;

#[cfg(feature = "stdweb")]
#[path = "stdweb/mod.rs"]
mod backend;

pub use self::device::Id as DeviceId;
pub use self::error::OsError;
pub use self::event_loop::{
    EventLoop, Proxy as EventLoopProxy, WindowTarget as EventLoopWindowTarget,
};
pub use self::monitor::{Handle as MonitorHandle, Mode as VideoMode};
pub use self::window::{
    Id as WindowId, PlatformSpecificBuilderAttributes as PlatformSpecificWindowBuilderAttributes,
    Window,
};
<commit_msg>Add error message when building for web without selecting a feature. (#1253)<commit_after>// TODO: close events (port from old stdweb branch)
// TODO: pointer locking (stdweb PR required)
// TODO: fullscreen API (stdweb PR required)

mod device;
mod error;
mod event_loop;
mod monitor;
mod window;

#[cfg(feature = "web-sys")]
#[path = "web_sys/mod.rs"]
mod backend;

#[cfg(feature = "stdweb")]
#[path = "stdweb/mod.rs"]
mod backend;

#[cfg(not(any(feature = "web-sys", feature = "stdweb")))]
compile_error!("Please select a feature to build for web: `web-sys`, `stdweb`");

pub use self::device::Id as DeviceId;
pub use self::error::OsError;
pub use self::event_loop::{
    EventLoop, Proxy as EventLoopProxy, WindowTarget as EventLoopWindowTarget,
};
pub use self::monitor::{Handle as MonitorHandle, Mode as VideoMode};
pub use self::window::{
    Id as WindowId, PlatformSpecificBuilderAttributes as PlatformSpecificWindowBuilderAttributes,
    Window,
};
<|endoftext|>


<commit_before>//! Represents JavaScript exceptions as a Rust [`Result`](std::result) type.
//!
//! Most interactions with the JavaScript engine can throw a JavaScript exception. Neon APIs
//! that can throw an exception are called _throwing APIs_ and return the type
//! [`NeonResult`](NeonResult) (or its shorthand [`JsResult`](JsResult)).
//!
//! When a throwing API triggers a JavaScript exception, it returns an [Err](std::result::Result::Err)
//! result. This indicates that the thread associated with the [`Context`](crate::context::Context)
//! is now throwing, and allows Rust code to perform any cleanup. See the
//! [`neon::context`](crate::context#throwing-exceptions) module documentation for more about
//! contexts and exceptions.
//!
//! Typically, Neon code can manage JavaScript exceptions correctly and conveniently by
//! using Rust's [question mark (`?`)][question-mark] operator. This ensures that Rust code
//! "short-circuits" when an exception is thrown and returns back to JavaScript without
//! calling any throwing APIs.
//!
//! ## Example
//!
//! Neon functions typically use [`JsResult`](JsResult) for their return type. This
//! example defines a function that extracts a property called `"message"` from an object,
//! throwing an exception if the argument is not of the right type or extracting the property
//! fails:
//!
//! ```ignore
//! fn get_message(mut cx: FunctionContext) -> JsResult<JsValue> {
//!     let obj: Handle<JsObject> = cx.argument(0)?;
//!     let prop: Handle<JsValue> = obj.get(&mut cx, "message")?;
//!     Ok(prop)
//! }
//! ```
//!
//! [question-mark]: https://doc.rust-lang.org/edition-guide/rust-2018/error-handling-and-panics/the-question-mark-operator-for-easier-error-handling.html

use context::Context;
use handle::Handle;
use std::fmt::{Display, Formatter, Result as FmtResult};
use types::Value;

/// A [unit type][unit] indicating that the JavaScript thread is throwing an exception.
///
/// `Throw` deliberately does not implement [`std::error::Error`](std::error::Error). It's
/// not recommended to chain JavaScript exceptions with other kinds of Rust errors,
/// since throwing means that the JavaScript thread is unavailable until the exception
/// is handled.
///
/// [unit]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#unit-like-structs-without-any-fields
#[derive(Debug)]
pub struct Throw;

impl Display for Throw {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        fmt.write_str("JavaScript Error")
    }
}

/// The result type for throwing APIs.
pub type NeonResult<T> = Result<T, Throw>;

/// Shorthand for a [`NeonResult`](NeonResult) that produces JavaScript values.
pub type JsResult<'b, T> = NeonResult<Handle<'b, T>>;

/// Extension trait for converting Rust [`Result`](std::result::Result) values
/// into [`JsResult`](JsResult) values by throwing JavaScript exceptions.
pub trait JsResultExt<'a, V: Value> {
    fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, V>;
}
<commit_msg>Better links to context docs from result docs.<commit_after>//! Represents JavaScript exceptions as a Rust [`Result`](std::result) type.
//!
//! Most interactions with the JavaScript engine can throw a JavaScript exception. Neon APIs
//! that can throw an exception are called _throwing APIs_ and return the type
//! [`NeonResult`](NeonResult) (or its shorthand [`JsResult`](JsResult)).
//!
//! When a throwing API triggers a JavaScript exception, it returns an [Err](std::result::Result::Err)
//! result. This indicates that the thread associated with the [`Context`](crate::context::Context)
//! is now throwing, and allows Rust code to perform any cleanup. See the
//! [`neon::context`](crate::context) module documentation for more about
//! [contexts and exceptions](crate::context#throwing-exceptions).
//!
//! Typically, Neon code can manage JavaScript exceptions correctly and conveniently by
//! using Rust's [question mark (`?`)][question-mark] operator. This ensures that Rust code
//! "short-circuits" when an exception is thrown and returns back to JavaScript without
//! calling any throwing APIs.
//!
//! ## Example
//!
//! Neon functions typically use [`JsResult`](JsResult) for their return type. This
//! example defines a function that extracts a property called `"message"` from an object,
//! throwing an exception if the argument is not of the right type or extracting the property
//! fails:
//!
//! ```ignore
//! fn get_message(mut cx: FunctionContext) -> JsResult<JsValue> {
//!     let obj: Handle<JsObject> = cx.argument(0)?;
//!     let prop: Handle<JsValue> = obj.get(&mut cx, "message")?;
//!     Ok(prop)
//! }
//! ```
//!
//! [question-mark]: https://doc.rust-lang.org/edition-guide/rust-2018/error-handling-and-panics/the-question-mark-operator-for-easier-error-handling.html

use context::Context;
use handle::Handle;
use std::fmt::{Display, Formatter, Result as FmtResult};
use types::Value;

/// A [unit type][unit] indicating that the JavaScript thread is throwing an exception.
///
/// `Throw` deliberately does not implement [`std::error::Error`](std::error::Error). It's
/// not recommended to chain JavaScript exceptions with other kinds of Rust errors,
/// since throwing means that the JavaScript thread is unavailable until the exception
/// is handled.
///
/// [unit]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#unit-like-structs-without-any-fields
#[derive(Debug)]
pub struct Throw;

impl Display for Throw {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        fmt.write_str("JavaScript Error")
    }
}

/// The result type for throwing APIs.
pub type NeonResult<T> = Result<T, Throw>;

/// Shorthand for a [`NeonResult`](NeonResult) that produces JavaScript values.
pub type JsResult<'b, T> = NeonResult<Handle<'b, T>>;

/// Extension trait for converting Rust [`Result`](std::result::Result) values
/// into [`JsResult`](JsResult) values by throwing JavaScript exceptions.
pub trait JsResultExt<'a, V: Value> {
    fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, V>;
}
<|endoftext|>


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

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(not(feature="clippy"), allow(unknown_lints))]

#[macro_use]
extern crate cfg_if;

#[macro_use]
mod macros;

// default: pregen/mod.rs
// build    OUT_DIR/mod.rs
// pregen:  pregen/mod.rs

cfg_if! {
    if #[cfg(all(feature="amqp0-build-primitives", not(feature="amqp0-pregen-primitives")))] {
        include!(concat!(env!("OUT_DIR"), "/mod.rs"));
    }
    else {
        include!(concat!("../pregen/mod.rs"));
    }
}

pub mod field;

#[derive(Clone)]
pub struct Frame
 {
    channel: u16,
    payload: P
}

impl<'a, P> Frame

    where P: ProtocolFramePayload<'a>
{
    pub fn channel(&self) -> u16 {
        self.channel
    }
    pub fn payload(&self) -> &P {
        &self.payload
    }
}

impl<'a, P> Encodable for Frame

    where P: ProtocolFramePayload<'a>
{
    fn encoded_size(&self) -> usize {
        4 + self.payload.encoded_size()
    }
}

use std::borrow::Cow;

impl<'a> Encodable for Cow<'a, [u8]> {
    fn encoded_size(&self) -> usize {
        self.len()
    }
}
impl<'a> Encodable for Cow<'a, str> {
    fn encoded_size(&self) -> usize {
        self.len()
    }
}

pub trait Protocol<'a> {
    type Frame: 'a;

    fn protocol_header() -> &'static [u8];
}

pub trait ProtocolFramePayload<'a>: Encodable {
    type Method: ProtocolMethod<'a>;

    fn as_method(&self) -> Option<&Self::Method>;
}

pub trait ProtocolMethod<'a> {
    type Start: ProtocolMethodPayload + 'a;
    fn as_start(&self) -> Option<&Self::Start>;
}

pub trait ProtocolMethodPayload: Encodable {
    fn class_id(&self) -> u16;
    fn method_id(&self) -> u16;
}

pub trait Encodable {
    fn encoded_size(&self) -> usize;
}

<commit_msg>[primitives] Remove Frame (Frame varies depending on the Spec)<commit_after>// Copyright 2016 Alexander Reece
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(not(feature="clippy"), allow(unknown_lints))]

#[macro_use]
extern crate cfg_if;

#[macro_use]
mod macros;

pub mod field;

// default: pregen/mod.rs
// build    OUT_DIR/mod.rs
// pregen:  pregen/mod.rs

cfg_if! {
    if #[cfg(all(feature="amqp0-build-primitives", not(feature="amqp0-pregen-primitives")))] {
        include!(concat!(env!("OUT_DIR"), "/mod.rs"));
    }
    else {
        include!(concat!("../pregen/mod.rs"));
    }
}

use std::borrow::Cow;

pub trait Encodable {
    fn encoded_size(&self) -> usize;
}

impl<'a> Encodable for Cow<'a, [u8]> {
    fn encoded_size(&self) -> usize {
        self.len()
    }
}
impl<'a> Encodable for Cow<'a, str> {
    fn encoded_size(&self) -> usize {
        self.len()
    }
}

pub trait Protocol<'a> {
    type Frame: 'a;

    fn protocol_header() -> &'static [u8];
}

pub trait ProtocolFramePayload<'a>: Encodable {
    type Method: ProtocolMethod<'a>;

    fn as_method(&self) -> Option<&Self::Method>;
}

pub trait ProtocolMethod<'a> {
    type Start: ProtocolMethodPayload + 'a;
    fn as_start(&self) -> Option<&Self::Start>;
}

pub trait ProtocolMethodPayload: Encodable {
    fn class_id(&self) -> u16;
    fn method_id(&self) -> u16;
}
<|endoftext|>