<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
//use common::*;
use message::*;
use serialize::*;
use std::rt::io::ReaderUtil;

pub struct PackedInputStream<T> {
    inner : T
}

impl <T : std::rt::io::Reader> std::rt::io::Reader for PackedInputStream<T> {
    fn eof(&mut self) -> bool {
        self.inner.eof()
    }

    fn read(&mut self, outBuf: &mut [u8]) -> Option<uint> {
        let len = outBuf.len();

        if (len == 0) { return Some(0); }

        assert!(len % 8 == 0, "PackInputStream reads must be word-aligned");

        let mut outPos = 0;
        while (outPos < len && ! self.inner.eof() ) {

            let tag : u8 = self.inner.read_byte().unwrap();

            for n in range(0, 8) {
                let isNonzero = (tag & (1 as u8 << n)) != 0;//..as bool;
                if (isNonzero) {
                    // TODO capnproto-c++ gets away without using a
                    // conditional here. Can we do something like that
                    // and would it speed things up?
                    outBuf[outPos] = self.inner.read_byte().unwrap();
                    outPos += 1;
                } else {
                    outBuf[outPos] = 0;
                    outPos += 1;
                }
            }

            if (tag == 0) {

                let runLength : uint = self.inner.read_byte().unwrap() as uint * 8;

                unsafe {
                    std::ptr::set_memory(outBuf.unsafe_mut_ref(outPos),
                                         0, runLength);
                };
                outPos += runLength;

            } else if (tag == 0xff) {
                let runLength : uint = self.inner.read_byte().unwrap() as uint * 8;

                let mut bytes_read = 0;
                loop {
                    if bytes_read >= runLength { break }
                    let pos = outPos + bytes_read;
                    match self.inner.read(outBuf.mut_slice(pos, outPos + runLength)) {
                        Some(n) => bytes_read += n,
                        None => fail!("failed to read bytes")
                    }
                }
                outPos += runLength;
            }

        }

        return Some(outPos);
    }

}

pub struct PackedOutputStream<T> {
    inner : T
}

impl <T : std::rt::io::Writer> std::rt::io::Writer for PackedOutputStream<T> {
    fn write(&mut self, inBuf : &[u8]) {

        // Yuck. It'd be better to have a BufferedOutputStream, but
        // that seems difficult with the current state of Rust.
        // For now, just make this big enough to handle the worst case.
        let mut buffer : ~[u8] = std::vec::from_elem(inBuf.len() * 3 / 2, 0u8);

        let mut inPos : uint = 0;
        let mut outPos : uint = 0;

        while (inPos < inBuf.len()) {

            let tagPos = outPos;
            outPos += 1;

            let bit0 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit0 as uint; inPos += 1;

            let bit1 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit1 as uint; inPos += 1;

            let bit2 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit2 as uint; inPos += 1;

            let bit3 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit3 as uint; inPos += 1;

            let bit4 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit4 as uint; inPos += 1;

            let bit5 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit5 as uint; inPos += 1;

            let bit6 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit6 as uint; inPos += 1;

            let bit7 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit7 as uint; inPos += 1;

            let tag : u8 = (bit0 << 0) | (bit1 << 1) | (bit2 << 2) | (bit3 << 3)
                         | (bit4 << 4) | (bit5 << 5) | (bit6 << 6) | (bit7 << 7);

            buffer[tagPos] = tag;

            if (tag == 0) {
                //# An all-zero word is followed by a count of
                //# consecutive zero words (not including the first
                //# one).

                let mut count : u8 = 0;
                unsafe {
                    let mut inWord : *u64 =
                        std::cast::transmute(inBuf.unsafe_ref(inPos));
                    while (count < 255 && *inWord == 0) {
                        inWord = std::ptr::offset(inWord, 1);
                        count += 1;
                    }
                }
                buffer[outPos] = count;
                outPos += 1;

                inPos += count as uint * 8;

            } else if (tag == 0xff) {
                //# An all-nonzero word is followed by a count of
                //# consecutive uncompressed words, followed by the
                //# uncompressed words themselves.

                //# Count the number of consecutive words in the input
                //# which have no more than a single zero-byte. We look
                //# for at least two zeros because that's the point
                //# where our compression scheme becomes a net win.
                let mut count : u8 = 0;
                let runStart = inPos;
                while (inPos < inBuf.len() && count < 255) {
                    let mut c = 0;

                    for _ in range(0,8) {
                        c += (inBuf[inPos] == 0) as u8;
                        inPos += 1;
                    }

                    if (c >= 2) {
                        //# Un-read the word with multiple zeros, since
                        //# we'll want to compress that one.
                        inPos -= 8;
                        break;
                    }

                    count += 1;
                }
                buffer[outPos] = count;
                outPos += 1;

                unsafe {
                    let dst : *mut u8 = buffer.unsafe_mut_ref(outPos);
                    let src : *u8 = inBuf.unsafe_ref(runStart);
                    std::ptr::copy_memory(dst, src, 8 * count as uint);
                }
                outPos += count as uint * 8;

            }
        }

        self.inner.write(buffer.slice(0, outPos));
    }

   fn flush(&mut self) { self.inner.flush(); }
}

pub fn writePackedMessage<T : std::rt::io::Writer>(outputStream : T,
                                                   message : &MessageBuilder) {

    let mut packedOutputStream = PackedOutputStream {inner : outputStream};

    writeMessage(&mut packedOutputStream, message);
}
<commit_msg>use read_u8_()<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
//use common::*;
use message::*;
use serialize::*;
use std::rt::io::ReaderByteConversions;

pub struct PackedInputStream<T> {
    inner : T
}

impl <T : std::rt::io::Reader> std::rt::io::Reader for PackedInputStream<T> {
    fn eof(&mut self) -> bool {
        self.inner.eof()
    }

    fn read(&mut self, outBuf: &mut [u8]) -> Option<uint> {
        let len = outBuf.len();

        if (len == 0) { return Some(0); }

        assert!(len % 8 == 0, "PackInputStream reads must be word-aligned");

        let mut outPos = 0;
        while (outPos < len && ! self.inner.eof() ) {

            let tag : u8 = self.inner.read_u8_();

            for n in range(0, 8) {
                let isNonzero = (tag & (1 as u8 << n)) != 0;//..as bool;
                if (isNonzero) {
                    // TODO capnproto-c++ gets away without using a
                    // conditional here. Can we do something like that
                    // and would it speed things up?
                    outBuf[outPos] = self.inner.read_u8_();
                    outPos += 1;
                } else {
                    outBuf[outPos] = 0;
                    outPos += 1;
                }
            }

            if (tag == 0) {

                let runLength : uint = self.inner.read_u8_() as uint * 8;

                unsafe {
                    std::ptr::set_memory(outBuf.unsafe_mut_ref(outPos),
                                         0, runLength);
                };
                outPos += runLength;

            } else if (tag == 0xff) {
                let runLength : uint = self.inner.read_u8_() as uint * 8;

                let mut bytes_read = 0;
                loop {
                    if bytes_read >= runLength { break }
                    let pos = outPos + bytes_read;
                    match self.inner.read(outBuf.mut_slice(pos, outPos + runLength)) {
                        Some(n) => bytes_read += n,
                        None => fail!("failed to read bytes")
                    }
                }
                outPos += runLength;
            }

        }

        return Some(outPos);
    }

}

pub struct PackedOutputStream<T> {
    inner : T
}

impl <T : std::rt::io::Writer> std::rt::io::Writer for PackedOutputStream<T> {
    fn write(&mut self, inBuf : &[u8]) {

        // Yuck. It'd be better to have a BufferedOutputStream, but
        // that seems difficult with the current state of Rust.
        // For now, just make this big enough to handle the worst case.
        let mut buffer : ~[u8] = std::vec::from_elem(inBuf.len() * 3 / 2, 0u8);

        let mut inPos : uint = 0;
        let mut outPos : uint = 0;

        while (inPos < inBuf.len()) {

            let tagPos = outPos;
            outPos += 1;

            let bit0 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit0 as uint; inPos += 1;

            let bit1 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit1 as uint; inPos += 1;

            let bit2 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit2 as uint; inPos += 1;

            let bit3 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit3 as uint; inPos += 1;

            let bit4 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit4 as uint; inPos += 1;

            let bit5 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit5 as uint; inPos += 1;

            let bit6 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit6 as uint; inPos += 1;

            let bit7 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit7 as uint; inPos += 1;

            let tag : u8 = (bit0 << 0) | (bit1 << 1) | (bit2 << 2) | (bit3 << 3)
                         | (bit4 << 4) | (bit5 << 5) | (bit6 << 6) | (bit7 << 7);

            buffer[tagPos] = tag;

            if (tag == 0) {
                //# An all-zero word is followed by a count of
                //# consecutive zero words (not including the first
                //# one).

                let mut count : u8 = 0;
                unsafe {
                    let mut inWord : *u64 =
                        std::cast::transmute(inBuf.unsafe_ref(inPos));
                    while (count < 255 && *inWord == 0) {
                        inWord = std::ptr::offset(inWord, 1);
                        count += 1;
                    }
                }
                buffer[outPos] = count;
                outPos += 1;

                inPos += count as uint * 8;

            } else if (tag == 0xff) {
                //# An all-nonzero word is followed by a count of
                //# consecutive uncompressed words, followed by the
                //# uncompressed words themselves.

                //# Count the number of consecutive words in the input
                //# which have no more than a single zero-byte. We look
                //# for at least two zeros because that's the point
                //# where our compression scheme becomes a net win.
                let mut count : u8 = 0;
                let runStart = inPos;
                while (inPos < inBuf.len() && count < 255) {
                    let mut c = 0;

                    for _ in range(0,8) {
                        c += (inBuf[inPos] == 0) as u8;
                        inPos += 1;
                    }

                    if (c >= 2) {
                        //# Un-read the word with multiple zeros, since
                        //# we'll want to compress that one.
                        inPos -= 8;
                        break;
                    }

                    count += 1;
                }
                buffer[outPos] = count;
                outPos += 1;

                unsafe {
                    let dst : *mut u8 = buffer.unsafe_mut_ref(outPos);
                    let src : *u8 = inBuf.unsafe_ref(runStart);
                    std::ptr::copy_memory(dst, src, 8 * count as uint);
                }
                outPos += count as uint * 8;

            }
        }

        self.inner.write(buffer.slice(0, outPos));
    }

   fn flush(&mut self) { self.inner.flush(); }
}

pub fn writePackedMessage<T : std::rt::io::Writer>(outputStream : T,
                                                   message : &MessageBuilder) {

    let mut packedOutputStream = PackedOutputStream {inner : outputStream};

    writeMessage(&mut packedOutputStream, message);
}
<|endoftext|>


<commit_before>// Passthrough decoder for librespot
use super::{AudioDecoder, AudioError, AudioPacket};
use ogg::{OggReadError, Packet, PacketReader, PacketWriteEndInfo, PacketWriter};
use std::fmt;
use std::io::{Read, Seek};
use std::time::{SystemTime, UNIX_EPOCH};

fn write_headers<T: Read + Seek>(
    rdr: &mut PacketReader<T>,
    wtr: &mut PacketWriter<Vec<u8>>,
) -> Result<u32, PassthroughError> {
    let mut stream_serial: u32 = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_millis() as u32;

    // search for ident, comment, setup
    get_header(1, rdr, wtr, &mut stream_serial, PacketWriteEndInfo::EndPage)?;
    get_header(
        3,
        rdr,
        wtr,
        &mut stream_serial,
        PacketWriteEndInfo::NormalPacket,
    )?;
    get_header(5, rdr, wtr, &mut stream_serial, PacketWriteEndInfo::EndPage)?;

    // remove un-needed packets
    rdr.delete_unread_packets();
    return Ok(stream_serial);
}

fn get_header<T>(
    code: u8,
    rdr: &mut PacketReader<T>,
    wtr: &mut PacketWriter<Vec<u8>>,
    stream_serial: &mut u32,
    info: PacketWriteEndInfo,
) -> Result<u32, PassthroughError>
where
    T: Read + Seek,
{
    let pck: Packet = rdr.read_packet_expected()?;

    // set a unique serial number
    if pck.stream_serial() != 0 {
        *stream_serial = pck.stream_serial();
    }

    let pkt_type = pck.data[0];
    debug!("Vorbis header type{}", &pkt_type);

    // all headers are mandatory
    if pkt_type != code {
        return Err(PassthroughError(OggReadError::InvalidData));
    }

    // headers keep original granule number
    let absgp_page = pck.absgp_page();
    wtr.write_packet(
        pck.data.into_boxed_slice(),
        *stream_serial,
        info,
        absgp_page,
    )
    .unwrap();

    return Ok(*stream_serial);
}

pub struct PassthroughDecoder<R: Read + Seek> {
    rdr: PacketReader<R>,
    wtr: PacketWriter<Vec<u8>>,
    lastgp_page: Option<u64>,
    absgp_page: u64,
    stream_serial: u32,
}

pub struct PassthroughError(ogg::OggReadError);

impl<R: Read + Seek> PassthroughDecoder<R> {
    /// Constructs a new Decoder from a given implementation of `Read + Seek`.
    pub fn new(rdr: R) -> Result<Self, PassthroughError> {
        let mut rdr = PacketReader::new(rdr);
        let mut wtr = PacketWriter::new(Vec::new());

        let stream_serial = write_headers(&mut rdr, &mut wtr)?;
        info!("Starting passthrough track with serial {}", stream_serial);

        return Ok(PassthroughDecoder {
            rdr,
            wtr,
            lastgp_page: Some(0),
            absgp_page: 0,
            stream_serial,
        });
    }
}

impl<R: Read + Seek> AudioDecoder for PassthroughDecoder<R> {
    fn seek(&mut self, ms: i64) -> Result<(), AudioError> {
        info!("Seeking to {}", ms);
        self.lastgp_page = match ms {
            0 => Some(0),
            _ => None,
        };

        // hard-coded to 44.1 kHz
        match self.rdr.seek_absgp(None, (ms * 44100 / 1000) as u64) {
            Ok(_) => return Ok(()),
            Err(err) => return Err(AudioError::PassthroughError(err.into())),
        }
    }

    fn next_packet(&mut self) -> Result<Option<AudioPacket>, AudioError> {
        let mut skip = self.lastgp_page.is_none();
        loop {
            let pck = match self.rdr.read_packet() {
                Ok(Some(pck)) => pck,

                Ok(None) | Err(OggReadError::NoCapturePatternFound) => {
                    info!("end of streaming");
                    return Ok(None);
                }

                Err(err) => return Err(AudioError::PassthroughError(err.into())),
            };

            let pckgp_page = pck.absgp_page();
            let lastgp_page = self.lastgp_page.get_or_insert(pckgp_page);

            // consume packets till next page to get a granule reference
            if skip {
                if *lastgp_page == pckgp_page {
                    debug!("skipping packet");
                    continue;
                }
                skip = false;
                info!("skipped at {}", pckgp_page);
            }

            // now we can calculate absolute granule
            self.absgp_page += pckgp_page - *lastgp_page;
            self.lastgp_page = Some(pckgp_page);

            // set packet type
            let inf = if pck.last_in_stream() {
                self.lastgp_page = Some(0);
                PacketWriteEndInfo::EndStream
            } else if pck.last_in_page() {
                PacketWriteEndInfo::EndPage
            } else {
                PacketWriteEndInfo::NormalPacket
            };

            self.wtr
                .write_packet(
                    pck.data.into_boxed_slice(),
                    self.stream_serial,
                    inf,
                    self.absgp_page,
                )
                .unwrap();

            let data = self.wtr.inner_mut();

            if data.len() > 0 {
                let result = AudioPacket::OggData(std::mem::take(data));
                return Ok(Some(result));
            }
        }
    }
}

impl fmt::Debug for PassthroughError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, f)
    }
}

impl From<ogg::OggReadError> for PassthroughError {
    fn from(err: OggReadError) -> PassthroughError {
        PassthroughError(err)
    }
}

impl fmt::Display for PassthroughError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}
<commit_msg>separated stream for each seek<commit_after>// Passthrough decoder for librespot
use super::{AudioDecoder, AudioError, AudioPacket};
use ogg::{OggReadError, Packet, PacketReader, PacketWriteEndInfo, PacketWriter};
use std::fmt;
use std::io::{Read, Seek};
use std::time::{SystemTime, UNIX_EPOCH};

fn get_header<T>(code: u8, rdr: &mut PacketReader<T>) -> Result<Box<[u8]>, PassthroughError>
where
    T: Read + Seek,
{
    let pck: Packet = rdr.read_packet_expected()?;

    let pkt_type = pck.data[0];
    debug!("Vorbis header type{}", &pkt_type);

    if pkt_type != code {
        return Err(PassthroughError(OggReadError::InvalidData));
    }

    return Ok(pck.data.into_boxed_slice());
}

pub struct PassthroughDecoder<R: Read + Seek> {
    rdr: PacketReader<R>,
    wtr: PacketWriter<Vec<u8>>,
    eos: bool,
    bos: bool,
    ofsgp_page: u64,
    stream_serial: u32,
    ident: Box<[u8]>,
    comment: Box<[u8]>,
    setup: Box<[u8]>,
}

pub struct PassthroughError(ogg::OggReadError);

impl<R: Read + Seek> PassthroughDecoder<R> {
    /// Constructs a new Decoder from a given implementation of `Read + Seek`.
    pub fn new(rdr: R) -> Result<Self, PassthroughError> {
        let mut rdr = PacketReader::new(rdr);
        let stream_serial = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_millis() as u32;

        info!("Starting passthrough track with serial {}", stream_serial);

        // search for ident, comment, setup
        let ident = get_header(1, &mut rdr)?;
        let comment = get_header(3, &mut rdr)?;
        let setup = get_header(5, &mut rdr)?;

        // remove un-needed packets
        rdr.delete_unread_packets();

        return Ok(PassthroughDecoder {
            rdr,
            wtr: PacketWriter::new(Vec::new()),
            ofsgp_page: 0,
            stream_serial,
            ident,
            comment,
            setup,
            eos: false,
            bos: false,
        });
    }
}

impl<R: Read + Seek> AudioDecoder for PassthroughDecoder<R> {
    fn seek(&mut self, ms: i64) -> Result<(), AudioError> {
        info!("Seeking to {}", ms);

        // add an eos to previous stream if missing
        if self.bos == true && self.eos == false {
            match self.rdr.read_packet() {
                Ok(Some(pck)) => {
                    let absgp_page = pck.absgp_page() - self.ofsgp_page;
                    self.wtr
                        .write_packet(
                            pck.data.into_boxed_slice(),
                            self.stream_serial,
                            PacketWriteEndInfo::EndStream,
                            absgp_page,
                        )
                        .unwrap();
                }
                _ => warn! {"Cannot write EoS after seeking"},
            };
        }

        self.eos = false;
        self.bos = false;
        self.ofsgp_page = 0;
        self.stream_serial += 1;

        // hard-coded to 44.1 kHz
        match self.rdr.seek_absgp(None, (ms * 44100 / 1000) as u64) {
            Ok(_) => {
                // need to set some offset for next_page()
                let pck = self.rdr.read_packet().unwrap().unwrap();
                self.ofsgp_page = pck.absgp_page();
                debug!("Seek to offset page {}", self.ofsgp_page);
                return Ok(());
            }
            Err(err) => return Err(AudioError::PassthroughError(err.into())),
        }
    }

    fn next_packet(&mut self) -> Result<Option<AudioPacket>, AudioError> {
        // write headers if we are (re)starting
        if self.bos == false {
            self.wtr
                .write_packet(
                    self.ident.clone(),
                    self.stream_serial,
                    PacketWriteEndInfo::EndPage,
                    0,
                )
                .unwrap();
            self.wtr
                .write_packet(
                    self.comment.clone(),
                    self.stream_serial,
                    PacketWriteEndInfo::NormalPacket,
                    0,
                )
                .unwrap();
            self.wtr
                .write_packet(
                    self.setup.clone(),
                    self.stream_serial,
                    PacketWriteEndInfo::EndPage,
                    0,
                )
                .unwrap();
            self.bos = true;
            debug!("Wrote Ogg headers");
        }

        loop {
            let pck = match self.rdr.read_packet() {
                Ok(Some(pck)) => pck,
                Ok(None) | Err(OggReadError::NoCapturePatternFound) => {
                    info!("end of streaming");
                    return Ok(None);
                }
                Err(err) => return Err(AudioError::PassthroughError(err.into())),
            };

            let pckgp_page = pck.absgp_page();

            // skip till we have audio and a calculable granule position
            if pckgp_page == 0 || pckgp_page == self.ofsgp_page {
                continue;
            }

            // set packet type
            let inf = if pck.last_in_stream() {
                self.eos = true;
                PacketWriteEndInfo::EndStream
            } else if pck.last_in_page() {
                PacketWriteEndInfo::EndPage
            } else {
                PacketWriteEndInfo::NormalPacket
            };

            self.wtr
                .write_packet(
                    pck.data.into_boxed_slice(),
                    self.stream_serial,
                    inf,
                    pckgp_page - self.ofsgp_page,
                )
                .unwrap();

            let data = self.wtr.inner_mut();

            if data.len() > 0 {
                let result = AudioPacket::OggData(std::mem::take(data));
                return Ok(Some(result));
            }
        }
    }
}

impl fmt::Debug for PassthroughError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, f)
    }
}

impl From<ogg::OggReadError> for PassthroughError {
    fn from(err: OggReadError) -> PassthroughError {
        PassthroughError(err)
    }
}

impl fmt::Display for PassthroughError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}
<|endoftext|>


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

extern crate grin_core;
extern crate grin_chain;
extern crate env_logger;
extern crate time;
extern crate rand;
extern crate secp256k1zkp as secp;

extern crate grin_grin as grin;

use std::sync::Arc;
use std::thread;
use rand::os::OsRng;

use grin_chain::types::*;
use grin_core::core::hash::Hashed;
use grin_core::core::target::Difficulty;
use grin_core::pow;
use grin_core::core;
use grin_core::consensus;
use grin_core::pow::cuckoo;
use grin_core::global;
use grin_core::global::MiningParameterMode;

use grin_core::pow::MiningWorker;

#[test]
fn mine_empty_chain() {
	let _ = env_logger::init();
    global::set_mining_mode(MiningParameterMode::AutomatedTesting);
	let mut rng = OsRng::new().unwrap();
	let chain = grin_chain::Chain::init(".grin".to_string(), Arc::new(NoopAdapter {}))
		.unwrap();

	// mine and add a few blocks
	let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
	let reward_key = secp::key::SecretKey::new(&secp, &mut rng);

	let mut miner_config = grin::MinerConfig {
		enable_mining: true,
		burn_reward: true,
		..Default::default()
	};
	miner_config.cuckoo_miner_plugin_dir = Some(String::from("../target/debug/deps"));

	let mut cuckoo_miner = cuckoo::Miner::new(consensus::EASINESS, global::sizeshift() as u32, global::proofsize());
	for n in 1..4 {
		let prev = chain.head_header().unwrap();
		let mut b = core::Block::new(&prev, vec![], reward_key).unwrap();
		b.header.timestamp = prev.timestamp + time::Duration::seconds(60);

		let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
		b.header.difficulty = difficulty.clone();

		pow::pow_size(
			&mut cuckoo_miner,
			&mut b.header,
			difficulty,
			global::sizeshift() as u32,
		).unwrap();

		let bhash = b.hash();
		chain.process_block(b, grin_chain::EASY_POW).unwrap();

		// checking our new head
		let head = chain.head().unwrap();
		assert_eq!(head.height, n);
		assert_eq!(head.last_block_h, bhash);
	}
}

#[test]
fn mine_forks() {
	let _ = env_logger::init();
	let mut rng = OsRng::new().unwrap();
	let chain = grin_chain::Chain::init(".grin2".to_string(), Arc::new(NoopAdapter {}))
		.unwrap();

	// mine and add a few blocks
	let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
	let reward_key = secp::key::SecretKey::new(&secp, &mut rng);

	for n in 1..4 {
		let prev = chain.head_header().unwrap();
		let mut b = core::Block::new(&prev, vec![], reward_key).unwrap();
		b.header.timestamp = prev.timestamp + time::Duration::seconds(60);
		b.header.total_difficulty = Difficulty::from_num(2 * n);
		let bhash = b.hash();
		chain.process_block(b, grin_chain::SKIP_POW).unwrap();

		// checking our new head
		thread::sleep(::std::time::Duration::from_millis(50));
		let head = chain.head().unwrap();
		assert_eq!(head.height, n as u64);
		assert_eq!(head.last_block_h, bhash);
		assert_eq!(head.prev_block_h, prev.hash());

		// build another block with higher difficulty
		let mut b = core::Block::new(&prev, vec![], reward_key).unwrap();
		b.header.timestamp = prev.timestamp + time::Duration::seconds(60);
		b.header.total_difficulty = Difficulty::from_num(2 * n + 1);
		let bhash = b.hash();
		chain.process_block(b, grin_chain::SKIP_POW).unwrap();

		// checking head switch
		thread::sleep(::std::time::Duration::from_millis(50));
		let head = chain.head().unwrap();
		assert_eq!(head.height, n as u64);
		assert_eq!(head.last_block_h, bhash);
		assert_eq!(head.prev_block_h, prev.hash());
	}
}
<commit_msg>clean up .grin and .grin2 dirs before running the respective tests (#93)<commit_after>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate grin_core;
extern crate grin_chain;
extern crate env_logger;
extern crate time;
extern crate rand;
extern crate secp256k1zkp as secp;

extern crate grin_grin as grin;

use std::fs;
use std::sync::Arc;
use std::thread;
use rand::os::OsRng;

use grin_chain::types::*;
use grin_core::core::hash::Hashed;
use grin_core::core::target::Difficulty;
use grin_core::pow;
use grin_core::core;
use grin_core::consensus;
use grin_core::pow::cuckoo;
use grin_core::global;
use grin_core::global::MiningParameterMode;

use grin_core::pow::MiningWorker;

fn clean_output_dir(dir_name:&str){
    let _ = fs::remove_dir_all(dir_name);
}

#[test]
fn mine_empty_chain() {
    let _ = env_logger::init();
	clean_output_dir(".grin");
    global::set_mining_mode(MiningParameterMode::AutomatedTesting);

	let mut rng = OsRng::new().unwrap();
	let chain = grin_chain::Chain::init(".grin".to_string(), Arc::new(NoopAdapter {}))
		.unwrap();

	// mine and add a few blocks
	let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
	let reward_key = secp::key::SecretKey::new(&secp, &mut rng);

	let mut miner_config = grin::MinerConfig {
		enable_mining: true,
		burn_reward: true,
		..Default::default()
	};
	miner_config.cuckoo_miner_plugin_dir = Some(String::from("../target/debug/deps"));

	let mut cuckoo_miner = cuckoo::Miner::new(consensus::EASINESS, global::sizeshift() as u32, global::proofsize());
	for n in 1..4 {
		let prev = chain.head_header().unwrap();
		let mut b = core::Block::new(&prev, vec![], reward_key).unwrap();
		b.header.timestamp = prev.timestamp + time::Duration::seconds(60);

		let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
		b.header.difficulty = difficulty.clone();

		pow::pow_size(
			&mut cuckoo_miner,
			&mut b.header,
			difficulty,
			global::sizeshift() as u32,
		).unwrap();

		let bhash = b.hash();
		chain.process_block(b, grin_chain::EASY_POW).unwrap();

		// checking our new head
		let head = chain.head().unwrap();
		assert_eq!(head.height, n);
		assert_eq!(head.last_block_h, bhash);
	}
}

#[test]
fn mine_forks() {
    let _ = env_logger::init();
	clean_output_dir(".grin2");

	let mut rng = OsRng::new().unwrap();
	let chain = grin_chain::Chain::init(".grin2".to_string(), Arc::new(NoopAdapter {}))
		.unwrap();

	// mine and add a few blocks
	let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
	let reward_key = secp::key::SecretKey::new(&secp, &mut rng);

	for n in 1..4 {
		let prev = chain.head_header().unwrap();
		let mut b = core::Block::new(&prev, vec![], reward_key).unwrap();
		b.header.timestamp = prev.timestamp + time::Duration::seconds(60);
		b.header.total_difficulty = Difficulty::from_num(2 * n);
		let bhash = b.hash();
		chain.process_block(b, grin_chain::SKIP_POW).unwrap();

		// checking our new head
		thread::sleep(::std::time::Duration::from_millis(50));
		let head = chain.head().unwrap();
		assert_eq!(head.height, n as u64);
		assert_eq!(head.last_block_h, bhash);
		assert_eq!(head.prev_block_h, prev.hash());

		// build another block with higher difficulty
		let mut b = core::Block::new(&prev, vec![], reward_key).unwrap();
		b.header.timestamp = prev.timestamp + time::Duration::seconds(60);
		b.header.total_difficulty = Difficulty::from_num(2 * n + 1);
		let bhash = b.hash();
		chain.process_block(b, grin_chain::SKIP_POW).unwrap();

		// checking head switch
		thread::sleep(::std::time::Duration::from_millis(50));
		let head = chain.head().unwrap();
		assert_eq!(head.height, n as u64);
		assert_eq!(head.last_block_h, bhash);
		assert_eq!(head.prev_block_h, prev.hash());
	}
}
<|endoftext|>


<commit_before>use std::num::{Zero, Orderable};
use std::uint;
use std::vec;
use nalgebra::traits::division_ring::DivisionRing;

pub fn projected_gauss_seidel_solve<N: DivisionRing + Orderable + Copy>
       (J:              &mut [N],
        MJ:             &mut [N],
        b:              &mut [N],
        lambda:         &mut [N],
        bounds:         &mut [N],
        idx:            &mut [int],
        sparcity:       uint,
        num_equations:  uint,
        num_bodies:     uint,
        num_iterations: uint) -> ~[N]
{
  // JMJ matrix’s diagonal.
  let mut d        = vec::from_elem(num_equations, Zero::zero::<N>());
  // MJLambda = MJ * lambda
  let mut MJLambda = vec::from_elem(sparcity * num_bodies, Zero::zero::<N>());

  /*
   * compute MJLambda = MJ * lambda
   */
  // warm start
  for uint::iterate(0u, num_equations) |i|
  {
    let b1 = idx[i * 2];
    let b2 = idx[i * 2 + 1];

    if (b1 >= 0)
    {
      for uint::iterate(0u, sparcity) |j|
      { MJLambda[b1 as uint * sparcity + j] += MJ[i * sparcity * 2 + j] * lambda[i]; }
    }

    if (b2 >= 0)
    {
      for uint::iterate(0u, sparcity) |j|
      { MJLambda[b2 as uint * sparcity + j] += MJ[i * sparcity * 2 + sparcity + j] * lambda[i]; }
    }
  }

  /*
   * init JB's diagonal
   */
  for uint::iterate(0u, num_equations) |i|
  {
    /*
     * J and MJ^t have the same sparcity
     */
    d[i] = Zero::zero();

    for uint::iterate(0u, sparcity) |j|
    {
      d[i] +=
        J[i * sparcity * 2 + j] * MJ[i * sparcity * 2 + j]
        + J[i * sparcity * 2 + j + sparcity] * MJ[sparcity + i * sparcity * 2 + j];
    }
  }

  /*
   * solve the system
   */
  for num_iterations.times
  {
    for uint::iterate(0u, num_equations) |i|
    {
      let b1 = idx[i * 2 + 0] * (sparcity as int);
      let b2 = idx[i * 2 + 1] * (sparcity as int);

      let mut d_lambda_i = b[i];

      if (b1 >= 0)
      {
        for uint::iterate(0u, sparcity) |j|
        { d_lambda_i -= J[2 * sparcity * i + j] * MJLambda[b1 as uint + j] }
      }

      if (b2 >= 0)
      {
        for uint::iterate(0u, sparcity) |j|
        { d_lambda_i -= J[2 * sparcity * i + sparcity + j] * MJLambda[b2 as uint + j] }
      }

      d_lambda_i /= d[i];

      /*
       * clamp the value such that: lambda- <= lambda <= lambda+
       * (this is the ``projected'' flavour of Gauss-Seidel
       */
      let lambda_i_0 = lambda[i];

      // FIXME: clamp takes pointers as arguments… would it be faster if it did
      // not?
      lambda[i] = (lambda_i_0 + d_lambda_i).clamp(&bounds[i * 2], &bounds[i * 2 + 1]);

      d_lambda_i = lambda[i] - lambda_i_0;

      if (b1 >= 0)
      {
        for uint::iterate(0u, sparcity) |j|
        { MJLambda[b1 as uint + j] += d_lambda_i * MJ[i * sparcity * 2 + j] }
      }

      if (b2 >= 0)
      {
        for uint::iterate(0u, sparcity) |j|
        { MJLambda[b2 as uint + j] += d_lambda_i * MJ[i * sparcity * 2 + sparcity + j] }
      }
    }
  }

  MJLambda
}
<commit_msg>Use unsafe indexing on constraint solver loop.<commit_after>use std::num::{Zero, Orderable};
use std::uint;
use std::vec;
use nalgebra::traits::division_ring::DivisionRing;

pub fn projected_gauss_seidel_solve<N: DivisionRing + Orderable + Copy>
       (J:              &mut [N],
        MJ:             &mut [N],
        b:              &mut [N],
        lambda:         &mut [N],
        bounds:         &mut [N],
        idx:            &mut [int],
        sparcity:       uint,
        num_equations:  uint,
        num_bodies:     uint,
        num_iterations: uint) -> ~[N]
{
  // JMJ matrix’s diagonal.
  let mut d        = vec::from_elem(num_equations, Zero::zero::<N>());
  // MJLambda = MJ * lambda
  let mut MJLambda = vec::from_elem(sparcity * num_bodies, Zero::zero::<N>());

  /*
   * compute MJLambda = MJ * lambda
   */
  // warm start
  for uint::iterate(0u, num_equations) |i|
  {
    let b1 = unsafe { idx.unsafe_get(i * 2)     };
    let b2 = unsafe { idx.unsafe_get(i * 2 + 1) };

    if (b1 >= 0)
    {
      for uint::iterate(0u, sparcity) |j|
      {
        unsafe {
          *MJLambda.unsafe_mut_ref(b1 as uint * sparcity + j) +=
            MJ.unsafe_get(i * sparcity * 2 + j) * lambda.unsafe_get(i);
        }
      }
    }

    if (b2 >= 0)
    {
      for uint::iterate(0u, sparcity) |j|
      {
        unsafe {
          *MJLambda.unsafe_mut_ref(b2 as uint * sparcity + j) +=
            MJ.unsafe_get(i * sparcity * 2 + sparcity + j) *
            lambda.unsafe_get(i);
        }
      }
    }
  }

  /*
   * init JB's diagonal
   */
  for uint::iterate(0u, num_equations) |i|
  {
    /*
     * J and MJ^t have the same sparcity
     */
    unsafe {
      d.unsafe_set(i, Zero::zero());
    }

    for uint::iterate(0u, sparcity) |j|
    {
      unsafe {
        *d.unsafe_mut_ref(i) +=
          J.unsafe_get(i * sparcity * 2 + j) *
          MJ.unsafe_get(i * sparcity * 2 + j)
          + J.unsafe_get(i * sparcity * 2 + j + sparcity) *
            MJ.unsafe_get(sparcity + i * sparcity * 2 + j);
      }
    }
  }

  /*
   * solve the system
   */
  for num_iterations.times
  {
    for uint::iterate(0u, num_equations) |i|
    {
      let b1 = unsafe { idx.unsafe_get(i * 2 + 0) } * (sparcity as int);
      let b2 = unsafe { idx.unsafe_get(i * 2 + 1) } * (sparcity as int);

      let mut d_lambda_i = unsafe { b.unsafe_get(i) };

      if (b1 >= 0)
      {
        for uint::iterate(0u, sparcity) |j|
        {
          unsafe {
            d_lambda_i -= J.unsafe_get(2 * sparcity * i + j) *
                          MJLambda.unsafe_get(b1 as uint + j)
          }
        }
      }

      if (b2 >= 0)
      {
        for uint::iterate(0u, sparcity) |j|
        {
          unsafe {
            d_lambda_i -= J.unsafe_get(2 * sparcity * i + sparcity + j) *
                          MJLambda.unsafe_get(b2 as uint + j)
          }
        }
      }

      d_lambda_i /= unsafe { d.unsafe_get(i) };

      /*
       * clamp the value such that: lambda- <= lambda <= lambda+
       * (this is the ``projected'' flavour of Gauss-Seidel
       */
      let lambda_i_0 = unsafe { lambda.unsafe_get(i) };

      // FIXME: clamp takes pointers as arguments… would it be faster if it did
      // not?
      unsafe {
        lambda.unsafe_set(
          i,
          (lambda_i_0 + d_lambda_i).clamp(&bounds.unsafe_get(i * 2),
                                          &bounds.unsafe_get(i * 2 + 1))
        );
      }

      d_lambda_i = unsafe { lambda.unsafe_get(i) } - lambda_i_0;

      if (b1 >= 0)
      {
        for uint::iterate(0u, sparcity) |j|
        {
          unsafe {
            *MJLambda.unsafe_mut_ref(b1 as uint + j) +=
              d_lambda_i * MJ.unsafe_get(i * sparcity * 2 + j)
          }
        }
      }

      if (b2 >= 0)
      {
        for uint::iterate(0u, sparcity) |j|
        {
          unsafe {
            *MJLambda.unsafe_mut_ref(b2 as uint + j) +=
              d_lambda_i * MJ.unsafe_get(i * sparcity * 2 + sparcity + j)
          }
        }
      }
    }
  }

  MJLambda
}
<|endoftext|>


<commit_before>// Test for issue #67776: binding named the same as enum variant
// should report a warning even when matching against a borrow

// check-pass

#![allow(unused_variables)]
#![allow(non_snake_case)]

enum Foo {
    Bar,
    Baz,
}

fn fn1(e: Foo) {
    match e {
        Bar => {},
        //~^ WARNING named the same as one of the variants of the type `Foo`
        Baz => {},
        //~^ WARNING named the same as one of the variants of the type `Foo`
    }
}

fn fn2(e: &Foo) {
    match e {
        Bar => {},
        //~^ WARNING named the same as one of the variants of the type `Foo`
        Baz => {},
        //~^ WARNING named the same as one of the variants of the type `Foo`
    }
}

fn fn3(e: &mut &&mut Foo) {
    match e {
        Bar => {},
        //~^ WARNING named the same as one of the variants of the type `Foo`
        Baz => {},
        //~^ WARNING named the same as one of the variants of the type `Foo`
    }
}

fn main() {}
<commit_msg>Reformulate test description<commit_after>// Test for issue #67776: binding named the same as enum variant
// should report a warning even when matching against a reference type

// check-pass

#![allow(unused_variables)]
#![allow(non_snake_case)]

enum Foo {
    Bar,
    Baz,
}

fn fn1(e: Foo) {
    match e {
        Bar => {},
        //~^ WARNING named the same as one of the variants of the type `Foo`
        Baz => {},
        //~^ WARNING named the same as one of the variants of the type `Foo`
    }
}

fn fn2(e: &Foo) {
    match e {
        Bar => {},
        //~^ WARNING named the same as one of the variants of the type `Foo`
        Baz => {},
        //~^ WARNING named the same as one of the variants of the type `Foo`
    }
}

fn fn3(e: &mut &&mut Foo) {
    match e {
        Bar => {},
        //~^ WARNING named the same as one of the variants of the type `Foo`
        Baz => {},
        //~^ WARNING named the same as one of the variants of the type `Foo`
    }
}

fn main() {}
<|endoftext|>


<commit_before>use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};

use clap::{App, Arg, ArgMatches};
use walkdir::WalkDir;
use which::which;

use CliResult;
use commands::Config;
use macho::is_macho_file;

fn invoke_dsymutil(path: &Path, output_path: &Path) -> CliResult<()> {
    let status = Command::new("dsymutil")
        .arg("-o")
        .arg(output_path)
        .arg("--flat")
        .arg(&path)
        .stderr(Stdio::null())
        .status()?;
    if !status.success() {
        fail!("dsymutil failed to extract symbols");
    }
    Ok(())
}

fn extract_symbols(src: &Path, dst: &Path) -> CliResult<()> {
    for dent_rv in WalkDir::new(src) {
        let dent = dent_rv?;
        let md = dent.metadata()?;
        if !md.is_file() || !is_macho_file(dent.path()) {
            continue;
        }

        let local_name = dent.path().strip_prefix(&src).unwrap();
        let full_path = dst.join(local_name);
        fs::create_dir_all(&full_path.parent().unwrap())?;
        invoke_dsymutil(dent.path(), &full_path)?;

        println!("  {}", local_name.display());
    }
    Ok(())
}

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b>
{
    app
        .about("extract iOS device support symbols")
        .after_help("This command extracts debug symbols from the iOS Device Support \
                     folder of the system for a given version of IOS and stores them \
                     in a new folder.  This can then later be uploaded into the \
                     global symbol store of a Sentry installation.")
        .arg(Arg::with_name("version")
             .value_name("VERSION")
             .help("The iOS version to convert symbols for.")
             .required(true)
             .index(1))
        .arg(Arg::with_name("path")
             .value_name("PATH")
             .long("path")
             .short("p")
             .help("The path to the iOS Device Support folder if different."))
        .arg(Arg::with_name("output")
             .long("--output")
             .short("-o")
             .help("The output path folder.  If not provided a new folder in the \
                    current folder is used."))
}

pub fn execute<'a>(matches: &ArgMatches<'a>, _config: &Config) -> CliResult<()> {
    let version = matches.value_of("version").unwrap();
    let base_path = matches.value_of("path")
        .map(|p| PathBuf::from(p))
        .unwrap_or_else(|| {
            let mut path = env::home_dir().unwrap();
            path.push("Library/Developer/Xcode/iOS DeviceSupport");
            path
        });
    let source_path = base_path.read_dir()?.filter_map(|ent_rv| {
        if let Ok(ent) = ent_rv {
            let name = ent.file_name();
            if name.to_string_lossy().split_whitespace().nth(0) == Some(version) {
                return Some(ent.path());
            }
        }
        None
    }).next().ok_or_else(|| format!("Could not find symbols for iOS version {} in {}",
                                    version, base_path.display()))?;
    let output = matches.value_of("output")
        .map(|p| PathBuf::from(p))
        .unwrap_or_else(|| {
            let mut path = env::current_dir().unwrap();
            path.push(format!("{}.symbols", version.replace(".", "_")));
            path
        });

    if output.exists() {
        fail!("Cannot proceed because the output path ({}) already exists.",
              output.display());
    }

    if which("dsymutil").is_err() {
        fail!("dsymutil is not installed on this machine but required.");
    }

    println!("Extracting iOS Device Support Symbols");
    println!("  iOS Version: {}", version);
    println!("  Source path: {}", source_path.display());
    println!("  Output path: {}", output.display());

    extract_symbols(&source_path, &output)?;

    println!("All done!");

    Ok(())
}
<commit_msg>Do not fail if dsymutil fails<commit_after>use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};

use clap::{App, Arg, ArgMatches};
use walkdir::WalkDir;
use which::which;

use CliResult;
use commands::Config;
use macho::is_macho_file;

fn invoke_dsymutil(path: &Path, output_path: &Path) -> CliResult<()> {
    let status = Command::new("dsymutil")
        .arg("-o")
        .arg(output_path)
        .arg("--flat")
        .arg(&path)
        .stderr(Stdio::null())
        .status()?;
    if !status.success() {
        println!("    warning: dsymutil failed to extract symbols");
    }
    Ok(())
}

fn extract_symbols(src: &Path, dst: &Path) -> CliResult<()> {
    for dent_rv in WalkDir::new(src) {
        let dent = dent_rv?;
        let md = dent.metadata()?;
        if !md.is_file() || !is_macho_file(dent.path()) {
            continue;
        }

        let local_name = dent.path().strip_prefix(&src).unwrap();
        let full_path = dst.join(local_name);
        fs::create_dir_all(&full_path.parent().unwrap())?;
        invoke_dsymutil(dent.path(), &full_path)?;

        println!("  {}", local_name.display());
    }
    Ok(())
}

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b>
{
    app
        .about("extract iOS device support symbols")
        .after_help("This command extracts debug symbols from the iOS Device Support \
                     folder of the system for a given version of IOS and stores them \
                     in a new folder.  This can then later be uploaded into the \
                     global symbol store of a Sentry installation.")
        .arg(Arg::with_name("version")
             .value_name("VERSION")
             .help("The iOS version to convert symbols for.")
             .required(true)
             .index(1))
        .arg(Arg::with_name("path")
             .value_name("PATH")
             .long("path")
             .short("p")
             .help("The path to the iOS Device Support folder if different."))
        .arg(Arg::with_name("output")
             .long("--output")
             .short("-o")
             .help("The output path folder.  If not provided a new folder in the \
                    current folder is used."))
}

pub fn execute<'a>(matches: &ArgMatches<'a>, _config: &Config) -> CliResult<()> {
    let version = matches.value_of("version").unwrap();
    let base_path = matches.value_of("path")
        .map(|p| PathBuf::from(p))
        .unwrap_or_else(|| {
            let mut path = env::home_dir().unwrap();
            path.push("Library/Developer/Xcode/iOS DeviceSupport");
            path
        });
    let source_path = base_path.read_dir()?.filter_map(|ent_rv| {
        if let Ok(ent) = ent_rv {
            let name = ent.file_name();
            if name.to_string_lossy().split_whitespace().nth(0) == Some(version) {
                return Some(ent.path());
            }
        }
        None
    }).next().ok_or_else(|| format!("Could not find symbols for iOS version {} in {}",
                                    version, base_path.display()))?;
    let output = matches.value_of("output")
        .map(|p| PathBuf::from(p))
        .unwrap_or_else(|| {
            let mut path = env::current_dir().unwrap();
            path.push(format!("{}.symbols", version.replace(".", "_")));
            path
        });

    if output.exists() {
        fail!("Cannot proceed because the output path ({}) already exists.",
              output.display());
    }

    if which("dsymutil").is_err() {
        fail!("dsymutil is not installed on this machine but required.");
    }

    println!("Extracting iOS Device Support Symbols");
    println!("  iOS Version: {}", version);
    println!("  Source path: {}", source_path.display());
    println!("  Output path: {}", output.display());

    extract_symbols(&source_path, &output)?;

    println!("All done!");

    Ok(())
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Base classes to work with IDL callbacks.

use dom::bindings::error::{Error, Fallible, report_pending_exception};
use dom::bindings::js::Root;
use dom::bindings::reflector::DomObject;
use dom::bindings::settings_stack::AutoEntryScript;
use dom::globalscope::GlobalScope;
use js::jsapi::{Heap, MutableHandleObject};
use js::jsapi::{IsCallable, JSContext, JSObject, JS_WrapObject};
use js::jsapi::{JSCompartment, JS_EnterCompartment, JS_LeaveCompartment};
use js::jsapi::JSAutoCompartment;
use js::jsapi::JS_GetProperty;
use js::jsval::{JSVal, UndefinedValue};
use std::default::Default;
use std::ffi::CString;
use std::mem::drop;
use std::ptr;
use std::rc::Rc;

/// The exception handling used for a call.
#[derive(Copy, Clone, PartialEq)]
pub enum ExceptionHandling {
    /// Report any exception and don't throw it to the caller code.
    Report,
    /// Throw any exception to the caller code.
    Rethrow,
}

/// A common base class for representing IDL callback function types.
#[derive(JSTraceable, PartialEq)]
pub struct CallbackFunction {
    object: CallbackObject,
}

impl CallbackFunction {
    /// Create a new `CallbackFunction` for this object.
    pub fn new() -> CallbackFunction {
        CallbackFunction {
            object: CallbackObject {
                callback: Heap::default(),
            },
        }
    }

    /// Initialize the callback function with a value.
    /// Should be called once this object is done moving.
    pub fn init(&mut self, callback: *mut JSObject) {
        self.object.callback.set(callback);
    }
}

/// A common base class for representing IDL callback interface types.
#[derive(JSTraceable, PartialEq)]
pub struct CallbackInterface {
    object: CallbackObject,
}

/// A common base class for representing IDL callback function and
/// callback interface types.
#[derive(JSTraceable)]
struct CallbackObject {
    /// The underlying `JSObject`.
    callback: Heap<*mut JSObject>,
}

impl PartialEq for CallbackObject {
    fn eq(&self, other: &CallbackObject) -> bool {
        self.callback.get() == other.callback.get()
    }
}

/// A trait to be implemented by concrete IDL callback function and
/// callback interface types.
pub trait CallbackContainer {
    /// Create a new CallbackContainer object for the given `JSObject`.
    fn new(callback: *mut JSObject) -> Rc<Self>;
    /// Returns the underlying `JSObject`.
    fn callback(&self) -> *mut JSObject;
}

impl CallbackInterface {
    /// Returns the underlying `JSObject`.
    pub fn callback(&self) -> *mut JSObject {
        self.object.callback.get()
    }
}

impl CallbackFunction {
    /// Returns the underlying `JSObject`.
    pub fn callback(&self) -> *mut JSObject {
        self.object.callback.get()
    }
}

impl CallbackInterface {
    /// Create a new CallbackInterface object for the given `JSObject`.
    pub fn new() -> CallbackInterface {
        CallbackInterface {
            object: CallbackObject {
                callback: Heap::default(),
            },
        }
    }

    /// Initialize the callback function with a value.
    /// Should be called once this object is done moving.
    pub fn init(&mut self, callback: *mut JSObject) {
        self.object.callback.set(callback);
    }

    /// Returns the property with the given `name`, if it is a callable object,
    /// or an error otherwise.
    pub fn get_callable_property(&self, cx: *mut JSContext, name: &str) -> Fallible<JSVal> {
        rooted!(in(cx) let mut callable = UndefinedValue());
        rooted!(in(cx) let obj = self.callback());
        unsafe {
            let c_name = CString::new(name).unwrap();
            if !JS_GetProperty(cx, obj.handle(), c_name.as_ptr(), callable.handle_mut()) {
                return Err(Error::JSFailed);
            }

            if !callable.is_object() || !IsCallable(callable.to_object()) {
                return Err(Error::Type(format!("The value of the {} property is not callable",
                                               name)));
            }
        }
        Ok(callable.get())
    }
}

/// Wraps the reflector for `p` into the compartment of `cx`.
pub fn wrap_call_this_object<T: DomObject>(cx: *mut JSContext,
                                           p: &T,
                                           rval: MutableHandleObject) {
    rval.set(p.reflector().get_jsobject().get());
    assert!(!rval.get().is_null());

    unsafe {
        if !JS_WrapObject(cx, rval) {
            rval.set(ptr::null_mut());
        }
    }
}

/// A class that performs whatever setup we need to safely make a call while
/// this class is on the stack. After `new` returns, the call is safe to make.
pub struct CallSetup {
    /// The global for reporting exceptions. This is the global object of the
    /// (possibly wrapped) callback object.
    exception_global: Root<GlobalScope>,
    /// The `JSContext` used for the call.
    cx: *mut JSContext,
    /// The compartment we were in before the call.
    old_compartment: *mut JSCompartment,
    /// The exception handling used for the call.
    handling: ExceptionHandling,
    /// https://heycam.github.io/webidl/#es-invoking-callback-functions
    /// steps 8 and 18.2.
    entry_script: Option<AutoEntryScript>,
}

impl CallSetup {
    /// Performs the setup needed to make a call.
    #[allow(unrooted_must_root)]
    pub fn new<T: CallbackContainer>(callback: &T,
                                     handling: ExceptionHandling)
                                     -> CallSetup {
        let global = unsafe { GlobalScope::from_object(callback.callback()) };
        let cx = global.get_cx();

        let aes = AutoEntryScript::new(&global);
        CallSetup {
            exception_global: global,
            cx: cx,
            old_compartment: unsafe { JS_EnterCompartment(cx, callback.callback()) },
            handling: handling,
            entry_script: Some(aes),
        }
    }

    /// Returns the `JSContext` used for the call.
    pub fn get_context(&self) -> *mut JSContext {
        self.cx
    }
}

impl Drop for CallSetup {
    fn drop(&mut self) {
        unsafe {
            JS_LeaveCompartment(self.cx, self.old_compartment);
            if self.handling == ExceptionHandling::Report {
                let _ac = JSAutoCompartment::new(self.cx,
                                                 self.exception_global.reflector().get_jsobject().get());
                report_pending_exception(self.cx, true);
            }
            drop(self.entry_script.take().unwrap());
        }
    }
}
<commit_msg>Change the order of code in callback.rs to make more sense.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Base classes to work with IDL callbacks.

use dom::bindings::error::{Error, Fallible, report_pending_exception};
use dom::bindings::js::Root;
use dom::bindings::reflector::DomObject;
use dom::bindings::settings_stack::AutoEntryScript;
use dom::globalscope::GlobalScope;
use js::jsapi::{Heap, MutableHandleObject};
use js::jsapi::{IsCallable, JSContext, JSObject, JS_WrapObject};
use js::jsapi::{JSCompartment, JS_EnterCompartment, JS_LeaveCompartment};
use js::jsapi::JSAutoCompartment;
use js::jsapi::JS_GetProperty;
use js::jsval::{JSVal, UndefinedValue};
use std::default::Default;
use std::ffi::CString;
use std::mem::drop;
use std::ptr;
use std::rc::Rc;

/// The exception handling used for a call.
#[derive(Copy, Clone, PartialEq)]
pub enum ExceptionHandling {
    /// Report any exception and don't throw it to the caller code.
    Report,
    /// Throw any exception to the caller code.
    Rethrow,
}

/// A common base class for representing IDL callback function and
/// callback interface types.
#[derive(JSTraceable)]
struct CallbackObject {
    /// The underlying `JSObject`.
    callback: Heap<*mut JSObject>,
}

impl PartialEq for CallbackObject {
    fn eq(&self, other: &CallbackObject) -> bool {
        self.callback.get() == other.callback.get()
    }
}

/// A trait to be implemented by concrete IDL callback function and
/// callback interface types.
pub trait CallbackContainer {
    /// Create a new CallbackContainer object for the given `JSObject`.
    fn new(callback: *mut JSObject) -> Rc<Self>;
    /// Returns the underlying `JSObject`.
    fn callback(&self) -> *mut JSObject;
}

/// A common base class for representing IDL callback function types.
#[derive(JSTraceable, PartialEq)]
pub struct CallbackFunction {
    object: CallbackObject,
}

impl CallbackFunction {
    /// Create a new `CallbackFunction` for this object.
    pub fn new() -> CallbackFunction {
        CallbackFunction {
            object: CallbackObject {
                callback: Heap::default(),
            },
        }
    }

    /// Initialize the callback function with a value.
    /// Should be called once this object is done moving.
    pub fn init(&mut self, callback: *mut JSObject) {
        self.object.callback.set(callback);
    }

    /// Returns the underlying `JSObject`.
    pub fn callback(&self) -> *mut JSObject {
        self.object.callback.get()
    }
}

/// A common base class for representing IDL callback interface types.
#[derive(JSTraceable, PartialEq)]
pub struct CallbackInterface {
    object: CallbackObject,
}

impl CallbackInterface {
    /// Create a new CallbackInterface object for the given `JSObject`.
    pub fn new() -> CallbackInterface {
        CallbackInterface {
            object: CallbackObject {
                callback: Heap::default(),
            },
        }
    }

    /// Initialize the callback function with a value.
    /// Should be called once this object is done moving.
    pub fn init(&mut self, callback: *mut JSObject) {
        self.object.callback.set(callback);
    }

    /// Returns the underlying `JSObject`.
    pub fn callback(&self) -> *mut JSObject {
        self.object.callback.get()
    }

    /// Returns the property with the given `name`, if it is a callable object,
    /// or an error otherwise.
    pub fn get_callable_property(&self, cx: *mut JSContext, name: &str) -> Fallible<JSVal> {
        rooted!(in(cx) let mut callable = UndefinedValue());
        rooted!(in(cx) let obj = self.callback());
        unsafe {
            let c_name = CString::new(name).unwrap();
            if !JS_GetProperty(cx, obj.handle(), c_name.as_ptr(), callable.handle_mut()) {
                return Err(Error::JSFailed);
            }

            if !callable.is_object() || !IsCallable(callable.to_object()) {
                return Err(Error::Type(format!("The value of the {} property is not callable",
                                               name)));
            }
        }
        Ok(callable.get())
    }
}

/// Wraps the reflector for `p` into the compartment of `cx`.
pub fn wrap_call_this_object<T: DomObject>(cx: *mut JSContext,
                                           p: &T,
                                           rval: MutableHandleObject) {
    rval.set(p.reflector().get_jsobject().get());
    assert!(!rval.get().is_null());

    unsafe {
        if !JS_WrapObject(cx, rval) {
            rval.set(ptr::null_mut());
        }
    }
}

/// A class that performs whatever setup we need to safely make a call while
/// this class is on the stack. After `new` returns, the call is safe to make.
pub struct CallSetup {
    /// The global for reporting exceptions. This is the global object of the
    /// (possibly wrapped) callback object.
    exception_global: Root<GlobalScope>,
    /// The `JSContext` used for the call.
    cx: *mut JSContext,
    /// The compartment we were in before the call.
    old_compartment: *mut JSCompartment,
    /// The exception handling used for the call.
    handling: ExceptionHandling,
    /// https://heycam.github.io/webidl/#es-invoking-callback-functions
    /// steps 8 and 18.2.
    entry_script: Option<AutoEntryScript>,
}

impl CallSetup {
    /// Performs the setup needed to make a call.
    #[allow(unrooted_must_root)]
    pub fn new<T: CallbackContainer>(callback: &T,
                                     handling: ExceptionHandling)
                                     -> CallSetup {
        let global = unsafe { GlobalScope::from_object(callback.callback()) };
        let cx = global.get_cx();

        let aes = AutoEntryScript::new(&global);
        CallSetup {
            exception_global: global,
            cx: cx,
            old_compartment: unsafe { JS_EnterCompartment(cx, callback.callback()) },
            handling: handling,
            entry_script: Some(aes),
        }
    }

    /// Returns the `JSContext` used for the call.
    pub fn get_context(&self) -> *mut JSContext {
        self.cx
    }
}

impl Drop for CallSetup {
    fn drop(&mut self) {
        unsafe {
            JS_LeaveCompartment(self.cx, self.old_compartment);
            if self.handling == ExceptionHandling::Report {
                let _ac = JSAutoCompartment::new(self.cx,
                                                 self.exception_global.reflector().get_jsobject().get());
                report_pending_exception(self.cx, true);
            }
            drop(self.entry_script.take().unwrap());
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{errors::JsonRpcError, views::AccountView, JsonRpcResponse};
use anyhow::{ensure, format_err, Error, Result};
use libra_types::{account_address::AccountAddress, transaction::SignedTransaction};
use reqwest::{Client, ClientBuilder, Url};
use serde_json::{json, Value};
use std::{collections::HashSet, convert::TryFrom, fmt, time::Duration};

#[derive(Clone, Default)]
pub struct JsonRpcBatch {
    pub requests: Vec<(String, Vec<Value>)>,
}

impl JsonRpcBatch {
    pub fn new() -> Self {
        Self { requests: vec![] }
    }

    pub fn json_request(&self) -> Value {
        let requests = self
            .requests
            .iter()
            .enumerate()
            .map(|(id, (method, params))| {
                serde_json::json!({"jsonrpc": "2.0", "method": method, "params": params, "id": id})
            })
            .collect();
        serde_json::Value::Array(requests)
    }

    pub fn add_request(&mut self, method_name: String, parameters: Vec<Value>) {
        self.requests.push((method_name, parameters));
    }

    pub fn add_submit_request(&mut self, transaction: SignedTransaction) -> Result<()> {
        let txn_payload = hex::encode(lcs::to_bytes(&transaction)?);
        self.add_request("submit".to_string(), vec![Value::String(txn_payload)]);
        Ok(())
    }

    pub fn add_get_account_request(&mut self, address: AccountAddress) {
        self.add_request(
            "get_account".to_string(),
            vec![Value::String(address.to_string())],
        );
    }

    pub fn add_get_metadata_request(&mut self, version: Option<u64>) {
        self.add_request("get_metadata".to_string(), vec![json!(version)]);
    }

    pub fn add_get_currencies_info(&mut self) {
        self.add_request("get_currencies".to_string(), vec![]);
    }

    pub fn add_get_transactions_request(
        &mut self,
        start_version: u64,
        limit: u64,
        include_events: bool,
    ) {
        self.add_request(
            "get_transactions".to_string(),
            vec![json!(start_version), json!(limit), json!(include_events)],
        );
    }

    pub fn add_get_account_transaction_request(
        &mut self,
        account: AccountAddress,
        sequence: u64,
        include_events: bool,
    ) {
        self.add_request(
            "get_account_transaction".to_string(),
            vec![
                json!(account.to_string()),
                json!(sequence),
                json!(include_events),
            ],
        );
    }

    pub fn add_get_events_request(&mut self, event_key: String, start: u64, limit: u64) {
        self.add_request(
            "get_events".to_string(),
            vec![json!(event_key), json!(start), json!(limit)],
        );
    }

    pub fn add_get_state_proof_request(&mut self, known_version: u64) {
        self.add_request("get_state_proof".to_string(), vec![json!(known_version)]);
    }

    pub fn add_get_account_state_with_proof_request(
        &mut self,
        account: AccountAddress,
        version: Option<u64>,
        ledger_version: Option<u64>,
    ) {
        self.add_request(
            "get_account_state_with_proof".to_string(),
            vec![
                json!(account.to_string()),
                json!(version),
                json!(ledger_version),
            ],
        );
    }

    pub fn add_get_network_status_request(&mut self) {
        self.add_request("get_network_status".to_string(), vec![]);
    }
}

#[derive(Debug)]
pub enum JsonRpcAsyncClientError {
    ClientError(reqwest::Error),
    InvalidServerResponse(String),
}

impl JsonRpcAsyncClientError {
    pub fn is_retriable(&self) -> bool {
        match self {
            JsonRpcAsyncClientError::ClientError(e) => {
                // TODO: Add following condition when is_request is added to reqwest stable release
                // // Error sending request
                //  if e.is_request() {
                //      return true;
                //  }
                if let Some(status) = e.status() {
                    // Returned status code indicates a server error
                    return status.is_server_error();
                }
                false
            }
            JsonRpcAsyncClientError::InvalidServerResponse(_) => false,
        }
    }
}

impl std::convert::From<JsonRpcAsyncClientError> for anyhow::Error {
    fn from(e: JsonRpcAsyncClientError) -> Self {
        anyhow::Error::msg(e.to_string())
    }
}

impl std::fmt::Display for JsonRpcAsyncClientError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "JsonRpcAsyncClientError {}", self)
    }
}

#[derive(Clone)]
pub struct JsonRpcAsyncClient {
    address: String,
    client: Client,
}

impl JsonRpcAsyncClient {
    /// Pass in full url for endpoint, supports HTTPS
    pub fn new(url: Url) -> Self {
        Self {
            address: url.to_string(),
            client: ClientBuilder::new()
                .timeout(Duration::from_secs(30))
                .build()
                .expect("Unable to build Client."),
        }
    }

    pub fn new_with_client(client: Client, url: Url) -> Self {
        Self {
            address: url.to_string(),
            client,
        }
    }

    pub async fn get_accounts(
        &self,
        accounts: &[AccountAddress],
    ) -> Result<Vec<Option<AccountView>>, JsonRpcAsyncClientError> {
        let mut batch = JsonRpcBatch::new();
        for account in accounts {
            batch.add_get_account_request(*account);
        }
        let exec_results = self.execute(batch).await?;
        let mut results = vec![];
        for exec_result in exec_results {
            let exec_result = exec_result
                .map_err(|e| JsonRpcAsyncClientError::InvalidServerResponse(e.to_string()))?;
            if let JsonRpcResponse::AccountResponse(r) = exec_result {
                results.push(r);
            } else {
                panic!("Unexpected response for get_accounts {:?}", exec_result)
            }
        }

        if results.len() != accounts.len() {
            return Err(JsonRpcAsyncClientError::InvalidServerResponse(format!(
                "Received unexpected number of JSON RPC responses ({}) for {} requests",
                results.len(),
                accounts.len()
            )));
        }

        Ok(results)
    }

    pub async fn submit_transaction(
        &self,
        txn: SignedTransaction,
    ) -> Result<(), JsonRpcAsyncClientError> {
        let mut batch = JsonRpcBatch::new();
        batch
            .add_submit_request(txn)
            .map_err(|e| JsonRpcAsyncClientError::InvalidServerResponse(e.to_string()))?;
        let mut exec_result = self.execute(batch).await?;
        assert!(exec_result.len() == 1);
        exec_result
            .remove(0)
            .map(|_| ())
            .map_err(|e| JsonRpcAsyncClientError::InvalidServerResponse(e.to_string()))
    }

    pub async fn execute(
        &self,
        batch: JsonRpcBatch,
    ) -> Result<Vec<Result<JsonRpcResponse>>, JsonRpcAsyncClientError> {
        let requests = batch.json_request();
        let resp = self
            .client
            .post(&self.address)
            .json(&requests)
            .send()
            .await
            .map_err(JsonRpcAsyncClientError::ClientError)?;

        if resp.status() != 200 {
            return Err(JsonRpcAsyncClientError::InvalidServerResponse(format!(
                "Http error code {}",
                resp.status()
            )));
        }

        let responses: Vec<Value> = resp
            .json()
            .await
            .map_err(|e| JsonRpcAsyncClientError::InvalidServerResponse(e.to_string()))?;
        process_batch_response(batch, responses)
            .map_err(|e| JsonRpcAsyncClientError::InvalidServerResponse(e.to_string()))
    }
}

impl fmt::Debug for JsonRpcAsyncClient {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.address)
    }
}

////////////////////////////////////////////////////
/// Helper methods for basic payload processing ///
///////////////////////////////////////////////////

pub fn process_batch_response(
    batch: JsonRpcBatch,
    responses: Vec<Value>,
) -> Result<Vec<Result<JsonRpcResponse>>> {
    let mut result = batch
        .requests
        .iter()
        .map(|_| Err(format_err!("response is missing")))
        .collect::<Vec<_>>();

    let mut seen_ids = HashSet::new();
    for response in responses {
        // check JSON RPC protocol
        let json_rpc_protocol = response.get("jsonrpc");
        ensure!(
            json_rpc_protocol == Some(&json!("2.0")),
            "JSON RPC response with incorrect protocol: {:?}",
            json_rpc_protocol
        );

        if let Ok(req_id) = fetch_id(&response) {
            ensure!(
                !seen_ids.contains(&req_id),
                "received JSON RPC response with duplicate response ID"
            );
            seen_ids.insert(req_id);
            if req_id < result.len() {
                let resp = if let Some(err_data) = response.get("error") {
                    let err_json: JsonRpcError = serde_json::from_value(err_data.clone())?;
                    Err(Error::new(err_json))
                } else if let Some(data) = response.get("result") {
                    let method = batch.requests[req_id].0.clone();
                    Ok(JsonRpcResponse::try_from((method, data.clone()))?)
                } else {
                    continue;
                };
                result[req_id] = resp;
            }
        }
    }

    Ok(result)
}

pub fn get_response_from_batch(
    index: usize,
    batch: &[Result<JsonRpcResponse>],
) -> Result<&Result<JsonRpcResponse>> {
    batch.get(index).ok_or_else(|| {
        format_err!(
            "[JSON RPC client] response missing in batch at index {}",
            index
        )
    })
}

fn fetch_id(response: &Value) -> Result<usize> {
    match response.get("id") {
        Some(id) => Ok(serde_json::from_value::<usize>(id.clone())?),
        None => Err(format_err!("request id is missing")),
    }
}
<commit_msg>[Small]Add more field to json rpc client error enum<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{errors::JsonRpcError, views::AccountView, JsonRpcResponse};
use anyhow::{ensure, format_err, Error, Result};
use libra_types::{account_address::AccountAddress, transaction::SignedTransaction};
use reqwest::{Client, ClientBuilder, Url};
use serde_json::{json, Value};
use std::{collections::HashSet, convert::TryFrom, fmt, time::Duration};

#[derive(Clone, Default)]
pub struct JsonRpcBatch {
    pub requests: Vec<(String, Vec<Value>)>,
}

impl JsonRpcBatch {
    pub fn new() -> Self {
        Self { requests: vec![] }
    }

    pub fn json_request(&self) -> Value {
        let requests = self
            .requests
            .iter()
            .enumerate()
            .map(|(id, (method, params))| {
                serde_json::json!({"jsonrpc": "2.0", "method": method, "params": params, "id": id})
            })
            .collect();
        serde_json::Value::Array(requests)
    }

    pub fn add_request(&mut self, method_name: String, parameters: Vec<Value>) {
        self.requests.push((method_name, parameters));
    }

    pub fn add_submit_request(&mut self, transaction: SignedTransaction) -> Result<()> {
        let txn_payload = hex::encode(lcs::to_bytes(&transaction)?);
        self.add_request("submit".to_string(), vec![Value::String(txn_payload)]);
        Ok(())
    }

    pub fn add_get_account_request(&mut self, address: AccountAddress) {
        self.add_request(
            "get_account".to_string(),
            vec![Value::String(address.to_string())],
        );
    }

    pub fn add_get_metadata_request(&mut self, version: Option<u64>) {
        self.add_request("get_metadata".to_string(), vec![json!(version)]);
    }

    pub fn add_get_currencies_info(&mut self) {
        self.add_request("get_currencies".to_string(), vec![]);
    }

    pub fn add_get_transactions_request(
        &mut self,
        start_version: u64,
        limit: u64,
        include_events: bool,
    ) {
        self.add_request(
            "get_transactions".to_string(),
            vec![json!(start_version), json!(limit), json!(include_events)],
        );
    }

    pub fn add_get_account_transaction_request(
        &mut self,
        account: AccountAddress,
        sequence: u64,
        include_events: bool,
    ) {
        self.add_request(
            "get_account_transaction".to_string(),
            vec![
                json!(account.to_string()),
                json!(sequence),
                json!(include_events),
            ],
        );
    }

    pub fn add_get_events_request(&mut self, event_key: String, start: u64, limit: u64) {
        self.add_request(
            "get_events".to_string(),
            vec![json!(event_key), json!(start), json!(limit)],
        );
    }

    pub fn add_get_state_proof_request(&mut self, known_version: u64) {
        self.add_request("get_state_proof".to_string(), vec![json!(known_version)]);
    }

    pub fn add_get_account_state_with_proof_request(
        &mut self,
        account: AccountAddress,
        version: Option<u64>,
        ledger_version: Option<u64>,
    ) {
        self.add_request(
            "get_account_state_with_proof".to_string(),
            vec![
                json!(account.to_string()),
                json!(version),
                json!(ledger_version),
            ],
        );
    }

    pub fn add_get_network_status_request(&mut self) {
        self.add_request("get_network_status".to_string(), vec![]);
    }
}

#[derive(Debug)]
pub enum JsonRpcAsyncClientError {
    ClientError(reqwest::Error),
    InvalidArgument(String),
    InvalidServerResponse(String),
}

impl JsonRpcAsyncClientError {
    pub fn is_retriable(&self) -> bool {
        match self {
            JsonRpcAsyncClientError::ClientError(e) => {
                // TODO: Add following condition when is_request is added to reqwest stable release
                // // Error sending request
                //  if e.is_request() {
                //      return true;
                //  }
                if let Some(status) = e.status() {
                    // Returned status code indicates a server error
                    return status.is_server_error();
                }
                false
            }
            JsonRpcAsyncClientError::InvalidServerResponse(_)
            | JsonRpcAsyncClientError::InvalidArgument(_) => false,
        }
    }
}

impl std::convert::From<JsonRpcAsyncClientError> for anyhow::Error {
    fn from(e: JsonRpcAsyncClientError) -> Self {
        anyhow::Error::msg(e.to_string())
    }
}

impl std::fmt::Display for JsonRpcAsyncClientError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "JsonRpcAsyncClientError {}", self)
    }
}

#[derive(Clone)]
pub struct JsonRpcAsyncClient {
    address: String,
    client: Client,
}

impl JsonRpcAsyncClient {
    /// Pass in full url for endpoint, supports HTTPS
    pub fn new(url: Url) -> Self {
        Self {
            address: url.to_string(),
            client: ClientBuilder::new()
                .timeout(Duration::from_secs(30))
                .build()
                .expect("Unable to build Client."),
        }
    }

    pub fn new_with_client(client: Client, url: Url) -> Self {
        Self {
            address: url.to_string(),
            client,
        }
    }

    pub async fn get_accounts(
        &self,
        accounts: &[AccountAddress],
    ) -> Result<Vec<Option<AccountView>>, JsonRpcAsyncClientError> {
        let mut batch = JsonRpcBatch::new();
        for account in accounts {
            batch.add_get_account_request(*account);
        }
        let exec_results = self.execute(batch).await?;
        let mut results = vec![];
        for exec_result in exec_results {
            let exec_result = exec_result
                .map_err(|e| JsonRpcAsyncClientError::InvalidServerResponse(e.to_string()))?;
            if let JsonRpcResponse::AccountResponse(r) = exec_result {
                results.push(r);
            } else {
                panic!("Unexpected response for get_accounts {:?}", exec_result)
            }
        }

        if results.len() != accounts.len() {
            return Err(JsonRpcAsyncClientError::InvalidServerResponse(format!(
                "Received unexpected number of JSON RPC responses ({}) for {} requests",
                results.len(),
                accounts.len()
            )));
        }

        Ok(results)
    }

    pub async fn submit_transaction(
        &self,
        txn: SignedTransaction,
    ) -> Result<(), JsonRpcAsyncClientError> {
        let mut batch = JsonRpcBatch::new();
        batch
            .add_submit_request(txn)
            .map_err(|e| JsonRpcAsyncClientError::InvalidArgument(e.to_string()))?;
        let mut exec_result = self.execute(batch).await?;
        assert!(exec_result.len() == 1);
        exec_result
            .remove(0)
            .map(|_| ())
            .map_err(|e| JsonRpcAsyncClientError::InvalidServerResponse(e.to_string()))
    }

    pub async fn execute(
        &self,
        batch: JsonRpcBatch,
    ) -> Result<Vec<Result<JsonRpcResponse>>, JsonRpcAsyncClientError> {
        let requests = batch.json_request();
        let resp = self
            .client
            .post(&self.address)
            .json(&requests)
            .send()
            .await
            .map_err(JsonRpcAsyncClientError::ClientError)?;

        if resp.status() != 200 {
            return Err(JsonRpcAsyncClientError::InvalidServerResponse(format!(
                "Http error code {}",
                resp.status()
            )));
        }

        let responses: Vec<Value> = resp
            .json()
            .await
            .map_err(|e| JsonRpcAsyncClientError::InvalidServerResponse(e.to_string()))?;
        process_batch_response(batch, responses)
            .map_err(|e| JsonRpcAsyncClientError::InvalidServerResponse(e.to_string()))
    }
}

impl fmt::Debug for JsonRpcAsyncClient {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.address)
    }
}

////////////////////////////////////////////////////
/// Helper methods for basic payload processing ///
///////////////////////////////////////////////////

pub fn process_batch_response(
    batch: JsonRpcBatch,
    responses: Vec<Value>,
) -> Result<Vec<Result<JsonRpcResponse>>> {
    let mut result = batch
        .requests
        .iter()
        .map(|_| Err(format_err!("response is missing")))
        .collect::<Vec<_>>();

    let mut seen_ids = HashSet::new();
    for response in responses {
        // check JSON RPC protocol
        let json_rpc_protocol = response.get("jsonrpc");
        ensure!(
            json_rpc_protocol == Some(&json!("2.0")),
            "JSON RPC response with incorrect protocol: {:?}",
            json_rpc_protocol
        );

        if let Ok(req_id) = fetch_id(&response) {
            ensure!(
                !seen_ids.contains(&req_id),
                "received JSON RPC response with duplicate response ID"
            );
            seen_ids.insert(req_id);
            if req_id < result.len() {
                let resp = if let Some(err_data) = response.get("error") {
                    let err_json: JsonRpcError = serde_json::from_value(err_data.clone())?;
                    Err(Error::new(err_json))
                } else if let Some(data) = response.get("result") {
                    let method = batch.requests[req_id].0.clone();
                    Ok(JsonRpcResponse::try_from((method, data.clone()))?)
                } else {
                    continue;
                };
                result[req_id] = resp;
            }
        }
    }

    Ok(result)
}

pub fn get_response_from_batch(
    index: usize,
    batch: &[Result<JsonRpcResponse>],
) -> Result<&Result<JsonRpcResponse>> {
    batch.get(index).ok_or_else(|| {
        format_err!(
            "[JSON RPC client] response missing in batch at index {}",
            index
        )
    })
}

fn fetch_id(response: &Value) -> Result<usize> {
    match response.get("id") {
        Some(id) => Ok(serde_json::from_value::<usize>(id.clone())?),
        None => Err(format_err!("request id is missing")),
    }
}
<|endoftext|>


<commit_before>extern crate dataloader;
extern crate futures;

use dataloader::{BatchFn, BatchFuture, Loader};
use futures::future::ok;
use futures::Future;

struct Batcher;
impl BatchFn<i32, i32> for Batcher {
    type Error = ();

    fn load(&self, keys: &[i32]) -> BatchFuture<i32, Self::Error> {
        println!("load batch {:?}", keys);
        Box::new(ok(keys.into_iter().map(|v| v * 10).collect()))
    }
}

fn main() {
    let loader = Loader::new(Batcher);
    println!("\n -- Using Loader --");
    {
        let v1 = loader
            .load(3)
            .and_then(|v| loader.load_many(vec![v, v + 5, v + 10]));
        let v2 = loader
            .load(4)
            .and_then(|v| loader.load_many(vec![v, v + 5, v + 10]));
        let all = v1.join(v2);
        let output = all.wait().unwrap();
        let expected = (vec![300, 350, 400], vec![400, 450, 500]);
        assert_eq!(expected, output);
    }

    let ld = loader.cached();
    println!("\n -- Using Cached Loader --");
    {
        let v1 = ld
            .load(3)
            .and_then(|v| ld.load_many(vec![v, v + 5, v + 10]));
        let v2 = ld
            .load(4)
            .and_then(|v| ld.load_many(vec![v, v + 5, v + 10]));
        let all = v1.join(v2);
        let output = all.wait().unwrap();
        let expected = (vec![300, 350, 400], vec![400, 450, 500]);
        assert_eq!(expected, output);
    }
}
<commit_msg>Upd 'simple' example<commit_after>use dataloader::{BatchFn, BatchFuture, Loader};
use futures::{future, FutureExt as _, TryFutureExt as _};
use tokio::runtime::current_thread;

struct Batcher;

impl BatchFn<i32, i32> for Batcher {
    type Error = ();

    fn load(&self, keys: &[i32]) -> BatchFuture<i32, Self::Error> {
        println!("load batch {:?}", keys);
        future::ready(keys.into_iter().map(|v| v * 10).collect())
            .unit_error()
            .boxed()
    }
}

fn main() {
    let mut rt = current_thread::Runtime::new().unwrap();

    let loader = Loader::new(Batcher);
    println!("\n -- Using Loader --");
    {
        let v1 = loader
            .load(3)
            .and_then(|v| loader.load_many(vec![v, v + 5, v + 10]));
        let v2 = loader
            .load(4)
            .and_then(|v| loader.load_many(vec![v, v + 5, v + 10]));
        let all = future::try_join(v1, v2);
        let output = rt.block_on(all.boxed_local().compat()).unwrap();
        let expected = (vec![300, 350, 400], vec![400, 450, 500]);
        assert_eq!(expected, output);
    }

    let ld = loader.cached();
    println!("\n -- Using Cached Loader --");
    {
        let v1 = ld
            .load(3)
            .and_then(|v| ld.load_many(vec![v, v + 5, v + 10]));
        let v2 = ld
            .load(4)
            .and_then(|v| ld.load_many(vec![v, v + 5, v + 10]));
        let all = future::try_join(v1, v2);
        let output = rt.block_on(all.boxed_local().compat()).unwrap();
        let expected = (vec![300, 350, 400], vec![400, 450, 500]);
        assert_eq!(expected, output);
    }
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use rustc::hir::*;
use utils::{paths, method_chain_args, span_help_and_lint, match_type, snippet};

/// **What it does:*** Checks for unnecessary `ok()` in if let.
///
/// **Why is this bad?** Calling `ok()` in if let is unnecessary, instead match on `Ok(pat)`
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rustc
/// for result in iter {
///     if let Some(bench) = try!(result).parse().ok() {
///         vec.push(bench)
///     }
/// }
/// ```
declare_lint! {
    pub IF_LET_SOME_RESULT,
    Warn,
    "usage of `ok()` in `if let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead"
}

#[derive(Copy, Clone)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(IF_LET_SOME_RESULT)
    }
}

impl LateLintPass for Pass {
    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
        if_let_chain! {[ //begin checking variables
            let ExprMatch(ref op, ref body, ref source) = expr.node, //test if expr is a match
            let MatchSource::IfLetDesugar { .. } = *source, //test if it is an If Let
            let ExprMethodCall(_, _, ref result_types) = op.node, //check is expr.ok() has type Result<T,E>.ok()
            let PatKind::TupleStruct(ref x, ref y, _)  = body[0].pats[0].node, //get operation
            method_chain_args(op, &["ok"]).is_some() //test to see if using ok() methoduse std::marker::Sized;

        ], {
            let is_result_type = match_type(cx, cx.tcx.expr_ty(&result_types[0]), &paths::RESULT);
            let some_expr_string = snippet(cx, y[0].span, "");
            if print::path_to_string(x) == "Some" && is_result_type {
                span_help_and_lint(cx, IF_LET_SOME_RESULT, expr.span,
                "Matching on `Some` with `ok()` is redundant",
                &format!("Consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string));
            }
        }}
    }
}
<commit_msg>Add to docs for if_let_some_result<commit_after>use rustc::lint::*;
use rustc::hir::*;
use utils::{paths, method_chain_args, span_help_and_lint, match_type, snippet};

/// **What it does:*** Checks for unnecessary `ok()` in if let.
///
/// **Why is this bad?** Calling `ok()` in if let is unnecessary, instead match on `Ok(pat)`
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// for result in iter {
///     if let Some(bench) = try!(result).parse().ok() {
///         vec.push(bench)
///     }
/// }
///```
/// Could be written:
///
/// ```rust
/// for result in iter {
///     if let Ok(bench) = try!(result).parse() {
///         vec.push(bench)
///     }
/// }
/// ```
declare_lint! {
    pub IF_LET_SOME_RESULT,
    Warn,
    "usage of `ok()` in `if let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead"
}

#[derive(Copy, Clone)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(IF_LET_SOME_RESULT)
    }
}

impl LateLintPass for Pass {
    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
        if_let_chain! {[ //begin checking variables
            let ExprMatch(ref op, ref body, ref source) = expr.node, //test if expr is a match
            let MatchSource::IfLetDesugar { .. } = *source, //test if it is an If Let
            let ExprMethodCall(_, _, ref result_types) = op.node, //check is expr.ok() has type Result<T,E>.ok()
            let PatKind::TupleStruct(ref x, ref y, _)  = body[0].pats[0].node, //get operation
            method_chain_args(op, &["ok"]).is_some() //test to see if using ok() methoduse std::marker::Sized;

        ], {
            let is_result_type = match_type(cx, cx.tcx.expr_ty(&result_types[0]), &paths::RESULT);
            let some_expr_string = snippet(cx, y[0].span, "");
            if print::path_to_string(x) == "Some" && is_result_type {
                span_help_and_lint(cx, IF_LET_SOME_RESULT, expr.span,
                "Matching on `Some` with `ok()` is redundant",
                &format!("Consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string));
            }
        }}
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use crate::{
    AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange,
    algo::generate,
};

/// A pointer to a syntax node inside a file. It can be used to remember a
/// specific node across reparses of the same file.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SyntaxNodePtr {
    range: TextRange,
    kind: SyntaxKind,
}

impl SyntaxNodePtr {
    pub fn new(node: &SyntaxNode) -> SyntaxNodePtr {
        SyntaxNodePtr {
            range: node.range(),
            kind: node.kind(),
        }
    }

    pub fn to_node(self, source_file: &SourceFile) -> &SyntaxNode {
        generate(Some(source_file.syntax()), |&node| {
            node.children()
                .find(|it| self.range.is_subrange(&it.range()))
        })
        .find(|it| it.range() == self.range && it.kind() == self.kind)
        .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
    }

    pub fn range(self) -> TextRange {
        self.range
    }

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

/// Like `SyntaxNodePtr`, but remembers the type of node
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct AstPtr<N: AstNode> {
    ptr: SyntaxNodePtr,
    _ty: PhantomData<N>,
}

impl<N: AstNode> Copy for AstPtr<N> {}
impl<N: AstNode> Clone for AstPtr<N> {
    fn clone(&self) -> AstPtr<N> {
        *self
    }
}

impl<N: AstNode> AstPtr<N> {
    pub fn new(node: &N) -> AstPtr<N> {
        AstPtr {
            ptr: SyntaxNodePtr::new(node.syntax()),
            _ty: PhantomData,
        }
    }

    pub fn to_node(self, source_file: &SourceFile) -> &N {
        let syntax_node = self.ptr.to_node(source_file);
        N::cast(syntax_node).unwrap()
    }

    pub fn syntax_node_ptr(self) -> SyntaxNodePtr {
        self.ptr
    }
}

#[test]
fn test_local_syntax_ptr() {
    use crate::{ast, AstNode};

    let file = SourceFile::parse("struct Foo { f: u32, }");
    let field = file
        .syntax()
        .descendants()
        .find_map(ast::NamedFieldDef::cast)
        .unwrap();
    let ptr = SyntaxNodePtr::new(field.syntax());
    let field_syntax = ptr.to_node(&file);
    assert_eq!(field.syntax(), &*field_syntax);
}
<commit_msg>minor rename<commit_after>use std::marker::PhantomData;

use crate::{
    AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange,
    algo::generate,
};

/// A pointer to a syntax node inside a file. It can be used to remember a
/// specific node across reparses of the same file.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SyntaxNodePtr {
    range: TextRange,
    kind: SyntaxKind,
}

impl SyntaxNodePtr {
    pub fn new(node: &SyntaxNode) -> SyntaxNodePtr {
        SyntaxNodePtr {
            range: node.range(),
            kind: node.kind(),
        }
    }

    pub fn to_node(self, source_file: &SourceFile) -> &SyntaxNode {
        generate(Some(source_file.syntax()), |&node| {
            node.children()
                .find(|it| self.range.is_subrange(&it.range()))
        })
        .find(|it| it.range() == self.range && it.kind() == self.kind)
        .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
    }

    pub fn range(self) -> TextRange {
        self.range
    }

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

/// Like `SyntaxNodePtr`, but remembers the type of node
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct AstPtr<N: AstNode> {
    raw: SyntaxNodePtr,
    _ty: PhantomData<N>,
}

impl<N: AstNode> Copy for AstPtr<N> {}
impl<N: AstNode> Clone for AstPtr<N> {
    fn clone(&self) -> AstPtr<N> {
        *self
    }
}

impl<N: AstNode> AstPtr<N> {
    pub fn new(node: &N) -> AstPtr<N> {
        AstPtr {
            raw: SyntaxNodePtr::new(node.syntax()),
            _ty: PhantomData,
        }
    }

    pub fn to_node(self, source_file: &SourceFile) -> &N {
        let syntax_node = self.raw.to_node(source_file);
        N::cast(syntax_node).unwrap()
    }

    pub fn syntax_node_ptr(self) -> SyntaxNodePtr {
        self.raw
    }
}

#[test]
fn test_local_syntax_ptr() {
    use crate::{ast, AstNode};

    let file = SourceFile::parse("struct Foo { f: u32, }");
    let field = file
        .syntax()
        .descendants()
        .find_map(ast::NamedFieldDef::cast)
        .unwrap();
    let ptr = SyntaxNodePtr::new(field.syntax());
    let field_syntax = ptr.to_node(&file);
    assert_eq!(field.syntax(), &*field_syntax);
}
<|endoftext|>