<commit_before>//  Copyright 2019 Twitter, Inc
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  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.

use crate::client::{MICROSECOND, MILLISECOND, SECOND};
use crate::codec::Codec;
use crate::stats::SimpleRecorder;
use crate::stats::Stat;
use rand::rngs::ThreadRng;
use rand::seq::SliceRandom;
use rand::thread_rng;

use bytes::BytesMut;
use mio::{Events, Poll, Token};
use ratelimiter::Ratelimiter;
use timer::Wheel;

use std::collections::VecDeque;
use std::sync::Arc;

pub struct Common {
    id: usize,
    close_rate: Option<Arc<Ratelimiter>>,
    connect_ratelimiter: Option<Arc<Ratelimiter>>,
    connect_queue: VecDeque<Token>,
    connect_timeout: usize,
    events: Option<Events>,
    event_loop: Poll,
    codec: Box<Codec>,
    poolsize: usize,
    ready_queue: VecDeque<Token>,
    request_ratelimiter: Option<Arc<Ratelimiter>>,
    request_timeout: usize,
    stats: Option<SimpleRecorder>,
    timers: Wheel<Token>,
    last_timeouts: u64,
    tcp_nodelay: bool,
}

impl Common {
    pub fn new(id: usize, codec: Box<Codec>) -> Self {
        Self {
            id,
            close_rate: None,
            connect_ratelimiter: None,
            connect_queue: VecDeque::new(),
            connect_timeout: 200 * MILLISECOND / MICROSECOND,
            codec,
            events: None,
            event_loop: Poll::new().expect("Failed to create new event loop"),
            poolsize: 1,
            ready_queue: VecDeque::new(),
            request_ratelimiter: None,
            request_timeout: 200 * MILLISECOND / MICROSECOND,
            stats: None,
            timers: Wheel::<Token>::new(SECOND / MICROSECOND),
            last_timeouts: time::precise_time_ns(),
            tcp_nodelay: false,
        }
    }

    pub fn id(&self) -> usize {
        self.id
    }

    pub fn set_connect_ratelimit(&mut self, ratelimiter: Option<Arc<Ratelimiter>>) {
        self.connect_ratelimiter = ratelimiter;
    }

    pub fn try_connect_wait(&self) -> Result<(), ()> {
        if let Some(ref ratelimiter) = self.connect_ratelimiter {
            ratelimiter.try_wait()
        } else {
            Ok(())
        }
    }

    pub fn set_connect_timeout(&mut self, microseconds: usize) {
        self.connect_timeout = microseconds;
    }

    pub fn connect_timeout(&self) -> usize {
        self.connect_timeout
    }

    pub fn set_request_timeout(&mut self, microseconds: usize) {
        self.request_timeout = microseconds;
    }

    pub fn request_timeout(&self) -> usize {
        self.request_timeout
    }

    pub fn set_request_ratelimit(&mut self, ratelimiter: Option<Arc<Ratelimiter>>) {
        self.request_ratelimiter = ratelimiter;
    }

    pub fn try_request_wait(&self) -> Result<(), ()> {
        if let Some(ref ratelimiter) = self.request_ratelimiter {
            ratelimiter.try_wait()
        } else {
            Ok(())
        }
    }

    pub fn set_close_rate(&mut self, rate: Option<Arc<Ratelimiter>>) {
        self.close_rate = rate;
    }

    pub fn should_close(&self) -> bool {
        if let Some(ref ratelimiter) = self.close_rate {
            ratelimiter.try_wait().map(|_| true).unwrap_or(false)
        } else {
            false
        }
    }

    pub fn connect_pending(&self) -> usize {
        self.connect_queue.len()
    }

    pub fn connect_enqueue(&mut self, token: Token) {
        self.connect_queue.push_back(token);
    }

    pub fn connect_requeue(&mut self, token: Token) {
        self.connect_queue.push_front(token);
    }

    pub fn connect_dequeue(&mut self) -> Option<Token> {
        self.connect_queue.pop_front()
    }

    pub fn connect_shuffle(&mut self) {
        let mut tmp: Vec<Token> = self.connect_queue.drain(0..).collect();
        let mut rng = thread_rng();
        tmp.shuffle(&mut rng);
        for token in tmp {
            self.connect_queue.push_back(token);
        }
    }

    pub fn ready_enqueue(&mut self, token: Token) {
        self.ready_queue.push_back(token);
    }

    pub fn ready_requeue(&mut self, token: Token) {
        self.ready_queue.push_front(token);
    }

    pub fn ready_dequeue(&mut self) -> Option<Token> {
        self.ready_queue.pop_front()
    }

    pub fn set_stats(&mut self, recorder: SimpleRecorder) {
        self.stats = Some(recorder);
    }

    pub fn stat_increment(&self, label: Stat) {
        if let Some(ref stats) = self.stats {
            stats.increment(label);
        }
    }

    pub fn stat_interval(&self, label: Stat, start: u64, stop: u64) {
        if let Some(ref stats) = self.stats {
            stats.time_interval(label, start, stop);
        }
    }

    pub fn heatmap_increment(&self, start: u64, stop: u64) {
        if let Some(ref stats) = self.stats {
            stats.heatmap_increment(start, stop);
        }
    }

    pub fn set_poolsize(&mut self, connections: usize) {
        self.poolsize = connections;
    }

    pub fn poolsize(&self) -> usize {
        self.poolsize
    }

    pub fn set_tcp_nodelay(&mut self, nodelay: bool) {
        self.tcp_nodelay = nodelay;
    }

    pub fn tcp_nodelay(&self) -> bool {
        self.tcp_nodelay
    }

    pub fn decode(&self, data: &[u8]) -> Result<codec::Response, codec::Error> {
        self.codec.decode(data)
    }

    pub fn encode(&mut self, buffer: &mut BytesMut, rng: &mut ThreadRng) {
        self.codec.encode(buffer, rng);
    }

    pub fn take_events(&mut self) -> Option<Events> {
        self.events.take()
    }

    pub fn set_events(&mut self, events: Option<Events>) {
        self.events = events;
    }

    pub fn event_loop(&self) -> &Poll {
        &self.event_loop
    }

    pub fn add_timer(&mut self, token: Token, microseconds: usize) {
        self.timers.add(token, microseconds);
    }

    pub fn cancel_timer(&mut self, token: Token) {
        self.timers.cancel(token);
    }

    pub fn get_timers(&mut self) -> Vec<Token> {
        let now = time::precise_time_ns();
        let last = self.last_timeouts;
        let ticks = (now - last) as usize / MICROSECOND;
        self.last_timeouts = now;
        self.timers.tick(ticks)
    }
}
<commit_msg>add tracing to request buffer<commit_after>//  Copyright 2019 Twitter, Inc
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  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.

use crate::client::{MICROSECOND, MILLISECOND, SECOND};
use crate::codec::Codec;
use crate::stats::SimpleRecorder;
use crate::stats::Stat;

use bytes::BytesMut;
use logger::*;
use mio::{Events, Poll, Token};
use rand::rngs::ThreadRng;
use rand::seq::SliceRandom;
use rand::thread_rng;
use ratelimiter::Ratelimiter;
use timer::Wheel;

use std::collections::VecDeque;
use std::sync::Arc;

pub struct Common {
    id: usize,
    close_rate: Option<Arc<Ratelimiter>>,
    connect_ratelimiter: Option<Arc<Ratelimiter>>,
    connect_queue: VecDeque<Token>,
    connect_timeout: usize,
    events: Option<Events>,
    event_loop: Poll,
    codec: Box<Codec>,
    poolsize: usize,
    ready_queue: VecDeque<Token>,
    request_ratelimiter: Option<Arc<Ratelimiter>>,
    request_timeout: usize,
    stats: Option<SimpleRecorder>,
    timers: Wheel<Token>,
    last_timeouts: u64,
    tcp_nodelay: bool,
}

impl Common {
    pub fn new(id: usize, codec: Box<Codec>) -> Self {
        Self {
            id,
            close_rate: None,
            connect_ratelimiter: None,
            connect_queue: VecDeque::new(),
            connect_timeout: 200 * MILLISECOND / MICROSECOND,
            codec,
            events: None,
            event_loop: Poll::new().expect("Failed to create new event loop"),
            poolsize: 1,
            ready_queue: VecDeque::new(),
            request_ratelimiter: None,
            request_timeout: 200 * MILLISECOND / MICROSECOND,
            stats: None,
            timers: Wheel::<Token>::new(SECOND / MICROSECOND),
            last_timeouts: time::precise_time_ns(),
            tcp_nodelay: false,
        }
    }

    pub fn id(&self) -> usize {
        self.id
    }

    pub fn set_connect_ratelimit(&mut self, ratelimiter: Option<Arc<Ratelimiter>>) {
        self.connect_ratelimiter = ratelimiter;
    }

    pub fn try_connect_wait(&self) -> Result<(), ()> {
        if let Some(ref ratelimiter) = self.connect_ratelimiter {
            ratelimiter.try_wait()
        } else {
            Ok(())
        }
    }

    pub fn set_connect_timeout(&mut self, microseconds: usize) {
        self.connect_timeout = microseconds;
    }

    pub fn connect_timeout(&self) -> usize {
        self.connect_timeout
    }

    pub fn set_request_timeout(&mut self, microseconds: usize) {
        self.request_timeout = microseconds;
    }

    pub fn request_timeout(&self) -> usize {
        self.request_timeout
    }

    pub fn set_request_ratelimit(&mut self, ratelimiter: Option<Arc<Ratelimiter>>) {
        self.request_ratelimiter = ratelimiter;
    }

    pub fn try_request_wait(&self) -> Result<(), ()> {
        if let Some(ref ratelimiter) = self.request_ratelimiter {
            ratelimiter.try_wait()
        } else {
            Ok(())
        }
    }

    pub fn set_close_rate(&mut self, rate: Option<Arc<Ratelimiter>>) {
        self.close_rate = rate;
    }

    pub fn should_close(&self) -> bool {
        if let Some(ref ratelimiter) = self.close_rate {
            ratelimiter.try_wait().map(|_| true).unwrap_or(false)
        } else {
            false
        }
    }

    pub fn connect_pending(&self) -> usize {
        self.connect_queue.len()
    }

    pub fn connect_enqueue(&mut self, token: Token) {
        self.connect_queue.push_back(token);
    }

    pub fn connect_requeue(&mut self, token: Token) {
        self.connect_queue.push_front(token);
    }

    pub fn connect_dequeue(&mut self) -> Option<Token> {
        self.connect_queue.pop_front()
    }

    pub fn connect_shuffle(&mut self) {
        let mut tmp: Vec<Token> = self.connect_queue.drain(0..).collect();
        let mut rng = thread_rng();
        tmp.shuffle(&mut rng);
        for token in tmp {
            self.connect_queue.push_back(token);
        }
    }

    pub fn ready_enqueue(&mut self, token: Token) {
        self.ready_queue.push_back(token);
    }

    pub fn ready_requeue(&mut self, token: Token) {
        self.ready_queue.push_front(token);
    }

    pub fn ready_dequeue(&mut self) -> Option<Token> {
        self.ready_queue.pop_front()
    }

    pub fn set_stats(&mut self, recorder: SimpleRecorder) {
        self.stats = Some(recorder);
    }

    pub fn stat_increment(&self, label: Stat) {
        if let Some(ref stats) = self.stats {
            stats.increment(label);
        }
    }

    pub fn stat_interval(&self, label: Stat, start: u64, stop: u64) {
        if let Some(ref stats) = self.stats {
            stats.time_interval(label, start, stop);
        }
    }

    pub fn heatmap_increment(&self, start: u64, stop: u64) {
        if let Some(ref stats) = self.stats {
            stats.heatmap_increment(start, stop);
        }
    }

    pub fn set_poolsize(&mut self, connections: usize) {
        self.poolsize = connections;
    }

    pub fn poolsize(&self) -> usize {
        self.poolsize
    }

    pub fn set_tcp_nodelay(&mut self, nodelay: bool) {
        self.tcp_nodelay = nodelay;
    }

    pub fn tcp_nodelay(&self) -> bool {
        self.tcp_nodelay
    }

    pub fn decode(&self, data: &[u8]) -> Result<codec::Response, codec::Error> {
        self.codec.decode(data)
    }

    pub fn encode(&mut self, buffer: &mut BytesMut, rng: &mut ThreadRng) {
        self.codec.encode(buffer, rng);
        trace!("encoded request: {:?}", buffer);
    }

    pub fn take_events(&mut self) -> Option<Events> {
        self.events.take()
    }

    pub fn set_events(&mut self, events: Option<Events>) {
        self.events = events;
    }

    pub fn event_loop(&self) -> &Poll {
        &self.event_loop
    }

    pub fn add_timer(&mut self, token: Token, microseconds: usize) {
        self.timers.add(token, microseconds);
    }

    pub fn cancel_timer(&mut self, token: Token) {
        self.timers.cancel(token);
    }

    pub fn get_timers(&mut self) -> Vec<Token> {
        let now = time::precise_time_ns();
        let last = self.last_timeouts;
        let ticks = (now - last) as usize / MICROSECOND;
        self.last_timeouts = now;
        self.timers.tick(ticks)
    }
}
<|endoftext|>


<commit_before>pub mod some_endpoint {
    use ruma_api::ruma_api;

    ruma_api! {
        metadata {
            description: "Does something.",
            method: GET, // An `http::Method` constant. No imports required.
            name: "some_endpoint",
            path: "/_matrix/some/endpoint/:baz",
            rate_limited: false,
            requires_authentication: false,
        }

        request {
            // With no attribute on the field, it will be put into the body of the request.
            pub foo: String,

            // This value will be put into the "Content-Type" HTTP header.
            #[ruma_api(header = CONTENT_TYPE)]
            pub content_type: String,

            // This value will be put into the query string of the request's URL.
            #[ruma_api(query)]
            pub bar: String,

            // This value will be inserted into the request's URL in place of the
            // ":baz" path component.
            #[ruma_api(path)]
            pub baz: String,
        }

        response {
            // This value will be extracted from the "Content-Type" HTTP header.
            #[ruma_api(header = CONTENT_TYPE)]
            pub content_type: String,

            // With no attribute on the field, it will be extracted from the body of the response.
            pub value: String,
        }
    }
}

pub mod newtype_body_endpoint {
    use ruma_api_macros::ruma_api;

    #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
    pub struct MyCustomType {
        pub foo: String,
    }

    ruma_api! {
        metadata {
            description: "Does something.",
            method: GET,
            name: "newtype_body_endpoint",
            path: "/_matrix/some/newtype/body/endpoint",
            rate_limited: false,
            requires_authentication: false,
        }

        request {
            #[ruma_api(body)]
            pub file: Vec<u8>,
        }

        response {
            #[ruma_api(body)]
            pub my_custom_type: MyCustomType,
        }
    }
}
<commit_msg>Fix tests<commit_after>pub mod some_endpoint {
    use ruma_api::ruma_api;

    ruma_api! {
        metadata {
            description: "Does something.",
            method: POST, // An `http::Method` constant. No imports required.
            name: "some_endpoint",
            path: "/_matrix/some/endpoint/:baz",
            rate_limited: false,
            requires_authentication: false,
        }

        request {
            // With no attribute on the field, it will be put into the body of the request.
            pub foo: String,

            // This value will be put into the "Content-Type" HTTP header.
            #[ruma_api(header = CONTENT_TYPE)]
            pub content_type: String,

            // This value will be put into the query string of the request's URL.
            #[ruma_api(query)]
            pub bar: String,

            // This value will be inserted into the request's URL in place of the
            // ":baz" path component.
            #[ruma_api(path)]
            pub baz: String,
        }

        response {
            // This value will be extracted from the "Content-Type" HTTP header.
            #[ruma_api(header = CONTENT_TYPE)]
            pub content_type: String,

            // With no attribute on the field, it will be extracted from the body of the response.
            pub value: String,
        }
    }
}

pub mod newtype_body_endpoint {
    use ruma_api_macros::ruma_api;

    #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
    pub struct MyCustomType {
        pub foo: String,
    }

    ruma_api! {
        metadata {
            description: "Does something.",
            method: PUT,
            name: "newtype_body_endpoint",
            path: "/_matrix/some/newtype/body/endpoint",
            rate_limited: false,
            requires_authentication: false,
        }

        request {
            #[ruma_api(body)]
            pub file: Vec<u8>,
        }

        response {
            #[ruma_api(body)]
            pub my_custom_type: MyCustomType,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All rights reserved.
//
// 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.

//! Compute line wrapping breaks for text.

use time;

use xi_rope::rope::{Rope, RopeInfo};
use xi_rope::tree::Cursor;
use xi_rope::interval::Interval;
use xi_rope::breaks::{Breaks, BreakBuilder, BreaksBaseMetric};
use xi_rope::spans::Spans;
use xi_unicode::LineBreakLeafIter;

use styles::Style;
use tabs::DocumentCtx;
use width_cache::{Token, WidthCache};

struct LineBreakCursor<'a> {
    inner: Cursor<'a, RopeInfo>,
    lb_iter: LineBreakLeafIter,
    last_byte: u8,
}

impl<'a> LineBreakCursor<'a> {
    fn new(text: &'a Rope, pos: usize) -> LineBreakCursor<'a> {
        let inner = Cursor::new(text, pos);
        let lb_iter = match inner.get_leaf() {
            Some((s, offset)) if !s.is_empty() =>
                LineBreakLeafIter::new(s.as_str(), offset),
            _ => LineBreakLeafIter::default()
        };
        LineBreakCursor {
            inner: inner,
            lb_iter: lb_iter,
            last_byte: 0,
        }
    }

    // position and whether break is hard; up to caller to stop calling after EOT
    fn next(&mut self) -> (usize, bool) {
        let mut leaf = self.inner.get_leaf();
        loop {
            match leaf {
                Some((s, offset)) => {
                    let (next, hard) = self.lb_iter.next(s.as_str());
                    if next < s.len() {
                        return (self.inner.pos() - offset + next, hard);
                    }
                    if !s.is_empty() {
                        self.last_byte = s.as_bytes()[s.len() - 1];
                    }
                    leaf = self.inner.next_leaf();
                }
                // A little hacky but only reports last break as hard if final newline
                None => return (self.inner.pos(), self.last_byte == b'\n')
            }
        }
    }
}

pub fn linewrap(text: &Rope, cols: usize) -> Breaks {
    let start_time = time::now();
    let mut lb_cursor = LineBreakCursor::new(text, 0);
    let mut builder = BreakBuilder::new();
    let mut last_pos = 0;
    let mut last_break_pos = 0;
    let mut width = 0;
    loop {
        let (pos, hard) = lb_cursor.next();
        let word_width = pos - last_pos;
        if width > 0 && width + word_width > cols {
            builder.add_break(width);
            //eprintln!("soft break {}", width);
            last_break_pos += width;
            width = 0;
        }
        width += word_width;
        if hard {
            builder.add_break(width);
            //eprintln!("hard break {}", width);
            last_break_pos += width;
            width = 0;
        }
        last_pos = pos;
        if pos == text.len() { break; }
    }
    builder.add_no_break(text.len() - last_break_pos);
    let result = builder.build();
    let time_ms = (time::now() - start_time).num_nanoseconds().unwrap() as f64 * 1e-6;
    eprintln!("time to wrap {} bytes: {:.2}ms", text.len(), time_ms);
    result
}

// `text` is string _after_ editing.
pub fn rewrap(breaks: &mut Breaks, text: &Rope, iv: Interval, newsize: usize, cols: usize) {
    let (edit_iv, new_breaks) = {
        let start_time = time::now();
        let (start, end) = iv.start_end();
        let mut bk_cursor = Cursor::new(breaks, start);
        // start of range to invalidate
        let mut inval_start = bk_cursor.prev::<BreaksBaseMetric>().unwrap_or(0);
        if inval_start > 0 {
            // edit on this line can invalidate break at end of previous
            inval_start = bk_cursor.prev::<BreaksBaseMetric>().unwrap_or(0);
        }
        bk_cursor.set(end);
        // compute end position in edited rope
        let mut inval_end = bk_cursor.next::<BreaksBaseMetric>().map_or(text.len(), |pos|
            pos - (end - start) + newsize);
        let mut lb_cursor = LineBreakCursor::new(text, inval_start);
        let mut builder = BreakBuilder::new();
        let mut last_pos = inval_start;
        let mut last_break_pos = inval_start;
        let mut width = 0;
        loop {
            let (pos, hard) = lb_cursor.next();
            let word_width = pos - last_pos;
            if width > 0 && width + word_width > cols {
                builder.add_break(width);
                last_break_pos += width;
                width = 0;
                while last_break_pos > inval_end {
                    inval_end = bk_cursor.next::<BreaksBaseMetric>().map_or(text.len(), |pos|
                        pos - (end - start) + newsize);
                }
                if last_break_pos == inval_end {
                    break;
                }
            }
            width += word_width;
            if hard {
                // TODO: DRY
                builder.add_break(width);
                last_break_pos += width;
                width = 0;
                while last_break_pos > inval_end {
                    inval_end = bk_cursor.next::<BreaksBaseMetric>().map_or(text.len(), |pos|
                        pos - (end - start) + newsize);
                }
                if last_break_pos == inval_end {
                    break;
                }
            }
            last_pos = pos;
            if pos == text.len() {
                break;
            }
        }
        builder.add_no_break(inval_end - last_break_pos);
        let time_ms = (time::now() - start_time).num_nanoseconds().unwrap() as f64 * 1e-6;
        eprintln!("time to wrap {} bytes: {:.2}ms (not counting build+edit)",
            inval_end - inval_start, time_ms);
        (Interval::new_open_closed(inval_start, inval_end + (end - start) - newsize), builder.build())
    };
    breaks.edit(edit_iv, new_breaks);
}

/// A potential opportunity to insert a break. In this representation, the widths
/// have been requested (in a batch request) but are not necessarily known until
/// the request is issued.
struct PotentialBreak {
    pos: usize,  // offset within text
    tok: Token,
    hard: bool,
}

/// Wrap the text (in batch mode) using width measurement.
pub fn linewrap_width(text: &Rope, style_spans: &Spans<Style>, doc_ctx: &DocumentCtx,
        max_width: f64) -> Breaks
{
    // TODO: this should be scoped to the FE. However, it will work (just with
    // degraded performance).
    let mut width_cache = WidthCache::new();
    eprintln!("wrapping with width, text len = {} {:?}", text.len(),
        style_spans);
    for (iv, style) in style_spans.iter() {
        let style_id = doc_ctx.get_style_id(&style);
        eprintln!("{}..{}: {}", iv.start(), iv.end(), style_id);
    }
    let style_id = 2;  // TODO: derive from style spans rather than assuming.
    let mut lb_cursor = LineBreakCursor::new(text, 0);

    // Prepare and issue the width request; in a block to limit mutable borrow
    // of width_cache.
    let mut pot_breaks = Vec::new();
    {
        let mut req = width_cache.batch_req();
        let mut last_pos = 0;

        while last_pos < text.len() {
            let (pos, hard) = lb_cursor.next();
            // TODO: avoid allocating string
            let word = &text.slice_to_string(last_pos, pos);
            let tok = req.request(style_id, &word);
            pot_breaks.push(PotentialBreak { pos, tok, hard });
            last_pos = pos;
        }
        req.issue(doc_ctx).unwrap();
    }

    // debug code, should be safe to eliminate
    for p in &pot_breaks {
        eprintln!("pos {}, tok {}, hard {}, width {}",
            p.pos, p.tok, p.hard, width_cache.resolve(p.tok));
    }

    // Compute breaks based on measured widths
    let mut builder = BreakBuilder::new();
    let mut last_break_pos = 0;
    let mut last_hard = false;
    let mut line_width = 0.0;
    for p in &pot_breaks {
        let pos = p.pos;
        let width = width_cache.resolve(p.tok);
        if last_hard || (pos > last_break_pos && line_width + width > max_width) {
            builder.add_break(pos - last_break_pos);
            last_break_pos = pos;
            line_width = 0.0;
        }
        line_width += width;
        last_hard = p.hard;
    }
    builder.add_no_break(text.len() - last_break_pos);
    builder.build()
}
<commit_msg>Refactor width wrap computation<commit_after>// Copyright 2016 Google Inc. All rights reserved.
//
// 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.

//! Compute line wrapping breaks for text.

use time;

use xi_rope::rope::{Rope, RopeInfo};
use xi_rope::tree::Cursor;
use xi_rope::interval::Interval;
use xi_rope::breaks::{Breaks, BreakBuilder, BreaksBaseMetric};
use xi_rope::spans::Spans;
use xi_unicode::LineBreakLeafIter;

use styles::Style;
use tabs::DocumentCtx;
use width_cache::{Token, WidthCache};

struct LineBreakCursor<'a> {
    inner: Cursor<'a, RopeInfo>,
    lb_iter: LineBreakLeafIter,
    last_byte: u8,
}

impl<'a> LineBreakCursor<'a> {
    fn new(text: &'a Rope, pos: usize) -> LineBreakCursor<'a> {
        let inner = Cursor::new(text, pos);
        let lb_iter = match inner.get_leaf() {
            Some((s, offset)) if !s.is_empty() =>
                LineBreakLeafIter::new(s.as_str(), offset),
            _ => LineBreakLeafIter::default()
        };
        LineBreakCursor {
            inner: inner,
            lb_iter: lb_iter,
            last_byte: 0,
        }
    }

    // position and whether break is hard; up to caller to stop calling after EOT
    fn next(&mut self) -> (usize, bool) {
        let mut leaf = self.inner.get_leaf();
        loop {
            match leaf {
                Some((s, offset)) => {
                    let (next, hard) = self.lb_iter.next(s.as_str());
                    if next < s.len() {
                        return (self.inner.pos() - offset + next, hard);
                    }
                    if !s.is_empty() {
                        self.last_byte = s.as_bytes()[s.len() - 1];
                    }
                    leaf = self.inner.next_leaf();
                }
                // A little hacky but only reports last break as hard if final newline
                None => return (self.inner.pos(), self.last_byte == b'\n')
            }
        }
    }
}

pub fn linewrap(text: &Rope, cols: usize) -> Breaks {
    let start_time = time::now();
    let mut lb_cursor = LineBreakCursor::new(text, 0);
    let mut builder = BreakBuilder::new();
    let mut last_pos = 0;
    let mut last_break_pos = 0;
    let mut width = 0;
    loop {
        let (pos, hard) = lb_cursor.next();
        let word_width = pos - last_pos;
        if width > 0 && width + word_width > cols {
            builder.add_break(width);
            //eprintln!("soft break {}", width);
            last_break_pos += width;
            width = 0;
        }
        width += word_width;
        if hard {
            builder.add_break(width);
            //eprintln!("hard break {}", width);
            last_break_pos += width;
            width = 0;
        }
        last_pos = pos;
        if pos == text.len() { break; }
    }
    builder.add_no_break(text.len() - last_break_pos);
    let result = builder.build();
    let time_ms = (time::now() - start_time).num_nanoseconds().unwrap() as f64 * 1e-6;
    eprintln!("time to wrap {} bytes: {:.2}ms", text.len(), time_ms);
    result
}

// `text` is string _after_ editing.
pub fn rewrap(breaks: &mut Breaks, text: &Rope, iv: Interval, newsize: usize, cols: usize) {
    let (edit_iv, new_breaks) = {
        let start_time = time::now();
        let (start, end) = iv.start_end();
        let mut bk_cursor = Cursor::new(breaks, start);
        // start of range to invalidate
        let mut inval_start = bk_cursor.prev::<BreaksBaseMetric>().unwrap_or(0);
        if inval_start > 0 {
            // edit on this line can invalidate break at end of previous
            inval_start = bk_cursor.prev::<BreaksBaseMetric>().unwrap_or(0);
        }
        bk_cursor.set(end);
        // compute end position in edited rope
        let mut inval_end = bk_cursor.next::<BreaksBaseMetric>().map_or(text.len(), |pos|
            pos - (end - start) + newsize);
        let mut lb_cursor = LineBreakCursor::new(text, inval_start);
        let mut builder = BreakBuilder::new();
        let mut last_pos = inval_start;
        let mut last_break_pos = inval_start;
        let mut width = 0;
        loop {
            let (pos, hard) = lb_cursor.next();
            let word_width = pos - last_pos;
            if width > 0 && width + word_width > cols {
                builder.add_break(width);
                last_break_pos += width;
                width = 0;
                while last_break_pos > inval_end {
                    inval_end = bk_cursor.next::<BreaksBaseMetric>().map_or(text.len(), |pos|
                        pos - (end - start) + newsize);
                }
                if last_break_pos == inval_end {
                    break;
                }
            }
            width += word_width;
            if hard {
                // TODO: DRY
                builder.add_break(width);
                last_break_pos += width;
                width = 0;
                while last_break_pos > inval_end {
                    inval_end = bk_cursor.next::<BreaksBaseMetric>().map_or(text.len(), |pos|
                        pos - (end - start) + newsize);
                }
                if last_break_pos == inval_end {
                    break;
                }
            }
            last_pos = pos;
            if pos == text.len() {
                break;
            }
        }
        builder.add_no_break(inval_end - last_break_pos);
        let time_ms = (time::now() - start_time).num_nanoseconds().unwrap() as f64 * 1e-6;
        eprintln!("time to wrap {} bytes: {:.2}ms (not counting build+edit)",
            inval_end - inval_start, time_ms);
        (Interval::new_open_closed(inval_start, inval_end + (end - start) - newsize), builder.build())
    };
    breaks.edit(edit_iv, new_breaks);
}

/// A potential opportunity to insert a break. In this representation, the widths
/// have been requested (in a batch request) but are not necessarily known until
/// the request is issued.
struct PotentialBreak {
    pos: usize,  // offset within text of the end of the word
    tok: Token,
    hard: bool,
}

// State for a rewrap in progress
struct RewrapCtx<'a> {
    text: &'a Rope,
    lb_cursor: LineBreakCursor<'a>,
    lb_cursor_pos: usize,
    width_cache: &'a mut WidthCache,
    doc_ctx: &'a DocumentCtx,
    pot_breaks: Vec<PotentialBreak>,
    pot_break_ix: usize,  // index within pot_breaks
    max_offset: usize, // offset of maximum break (ie hard break following edit)
    max_width: f64,
}

// This constant should be tuned so that the RPC takes about 1ms. Less than that,
// RPC overhead becomes significant. More than that, interactivity suffers.
const MAX_POT_BREAKS: usize = 10_000;

impl<'a> RewrapCtx<'a> {
    fn new(text: &'a Rope, _style_spans: &Spans<Style>, doc_ctx: &'a DocumentCtx,
        max_width: f64, width_cache: &'a mut WidthCache) -> RewrapCtx<'a>
    {
        let lb_cursor_pos = 0;
        let lb_cursor = LineBreakCursor::new(text, 0);
        RewrapCtx {
            text,
            lb_cursor,
            lb_cursor_pos,
            width_cache,
            doc_ctx,
            pot_breaks: Vec::new(),
            pot_break_ix: 0,
            max_offset: text.len(),
            max_width,
        }
    }

    fn refill_pot_breaks(&mut self) {
        let style_id = 2;  // TODO: derive from style spans rather than assuming.

        let mut req = self.width_cache.batch_req();

        self.pot_breaks.clear();
        self.pot_break_ix = 0;
        let mut pos = self.lb_cursor_pos;
        while pos < self.max_offset && self.pot_breaks.len() < MAX_POT_BREAKS {
            let (next, hard) = self.lb_cursor.next();
            // TODO: avoid allocating string
            let word = self.text.slice_to_string(pos, next);
            let tok = req.request(style_id, &word);
            pos = next;
            self.pot_breaks.push(PotentialBreak { pos, tok, hard });
        }
        req.issue(self.doc_ctx).unwrap();
        self.lb_cursor_pos = pos;
    }

    // Compute the next break, assuming `start` is a valid break.
    //
    // Invariant: start corresponds to the start of the word referenced by pot_break_ix.
    fn wrap_one_line(&mut self, start: usize) -> Option<usize> {
        let mut line_width = 0.0;
        let mut pos = start;
        while pos < self.max_offset {
            if self.pot_break_ix >= self.pot_breaks.len() {
                self.refill_pot_breaks();
            }
            let pot_break = &self.pot_breaks[self.pot_break_ix];
            if pot_break.hard {
                self.pot_break_ix += 1;
                return Some(pot_break.pos);
            }
            let width = self.width_cache.resolve(pot_break.tok);
            if line_width == 0.0 && width >= self.max_width {
                self.pot_break_ix += 1;
                return Some(pot_break.pos);
            }
            line_width += width;
            if line_width > self.max_width {
                return Some(pos);
            }
            self.pot_break_ix += 1;
            pos = pot_break.pos;
        }
        None
    }
}

/// Wrap the text (in batch mode) using width measurement.
pub fn linewrap_width(text: &Rope, style_spans: &Spans<Style>, doc_ctx: &DocumentCtx,
        max_width: f64) -> Breaks
{
    // TODO: this should be scoped to the FE. However, it will work (just with
    // degraded performance).
    let mut width_cache = WidthCache::new();
    let mut ctx = RewrapCtx::new(text, style_spans, doc_ctx, max_width, &mut width_cache);
    let mut builder = BreakBuilder::new();
    let mut pos = 0;
    while let Some(next) = ctx.wrap_one_line(pos) {
        builder.add_break(next - pos);
        pos = next;
    }
    builder.add_no_break(text.len() - pos);
    builder.build()
}
<|endoftext|>


<commit_before>use tokio::prelude::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let worker = Worker::new().add_host('::1');
    if let Ok(worker) = worker.connect().await {
        worker.work(|job| {
            job.response(job.data().reverse())
        })
    }
}
<commit_msg>Fix up example worker<commit_after>use std::time::Duration;
use std::thread;

use tokio::prelude::*;

use rustygeard::client::{Worker, WorkerJob};

/// When we use the status method, we need to be async!
async fn status_user(job: WorkerJob) -> Result<(), io::Error> {
    job.status(50, 100).await;
    thread::sleep(Duration::from_secs(1));
    Ok("all done")
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut worker = Worker::new();
    worker
        .connect()
        .await?
        .can_do("reverse", |job| Ok(job.data().reverse()))
        .can_do("alwaysfail", |job| {
            Err(io::Error::new(io::ErrorKind::Other, "Always fails"))
        })
        .can_do_async("status", status_user)
        .work()
        .await?
}
<|endoftext|>


<commit_before><commit_msg>Add boolean recognition<commit_after><|endoftext|>


<commit_before>//! lint when there is an enum with no variants

use crate::utils::span_lint_and_help;
use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// **What it does:** Checks for `enum`s with no variants.
    ///
    /// **Why is this bad?** If you want to introduce a type which
    /// can't be instantiated, you should use `!` (the never type),
    /// or a wrapper around it, because `!` has more extensive
    /// compiler support (type inference, etc...) and wrappers
    /// around it are the conventional way to define an uninhabited type.
    /// For further information visit [never type documentation](https://doc.rust-lang.org/std/primitive.never.html)
    ///
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// Bad:
    /// ```rust
    /// enum Test {}
    /// ```
    ///
    /// Good:
    /// ```rust
    /// #![feature(never_type)]
    ///
    /// struct Test(!);
    /// ```
    pub EMPTY_ENUM,
    pedantic,
    "enum with no variants"
}

declare_lint_pass!(EmptyEnum => [EMPTY_ENUM]);

impl<'tcx> LateLintPass<'tcx> for EmptyEnum {
    fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
        let did = cx.tcx.hir().local_def_id(item.hir_id);
        if let ItemKind::Enum(..) = item.kind {
            let ty = cx.tcx.type_of(did);
            let adt = ty.ty_adt_def().expect("already checked whether this is an enum");

            // Only suggest the never type if the feature is enabled
            if adt.variants.is_empty() && cx.tcx.features().never_type {
                span_lint_and_help(
                    cx,
                    EMPTY_ENUM,
                    item.span,
                    "enum with no variants",
                    None,
                    "consider using the uninhabited type `!` (never type) or a wrapper \
                    around it to introduce a type which can't be instantiated",
                );
            }
        }
    }
}
<commit_msg>Add additional lint doc to known problems section<commit_after>//! lint when there is an enum with no variants

use crate::utils::span_lint_and_help;
use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// **What it does:** Checks for `enum`s with no variants.
    ///
    /// As of this writing, the never type is still a
    /// nightly-only experimental API. Therefore, this lint is only triggered
    /// if the never type is enabled
    ///
    /// **Why is this bad?** If you want to introduce a type which
    /// can't be instantiated, you should use `!` (the never type),
    /// or a wrapper around it, because `!` has more extensive
    /// compiler support (type inference, etc...) and wrappers
    /// around it are the conventional way to define an uninhabited type.
    /// For further information visit [never type documentation](https://doc.rust-lang.org/std/primitive.never.html)
    ///
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// Bad:
    /// ```rust
    /// enum Test {}
    /// ```
    ///
    /// Good:
    /// ```rust
    /// #![feature(never_type)]
    ///
    /// struct Test(!);
    /// ```
    pub EMPTY_ENUM,
    pedantic,
    "enum with no variants"
}

declare_lint_pass!(EmptyEnum => [EMPTY_ENUM]);

impl<'tcx> LateLintPass<'tcx> for EmptyEnum {
    fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
        let did = cx.tcx.hir().local_def_id(item.hir_id);
        if let ItemKind::Enum(..) = item.kind {
            let ty = cx.tcx.type_of(did);
            let adt = ty.ty_adt_def().expect("already checked whether this is an enum");

            // Only suggest the never type if the feature is enabled
            if adt.variants.is_empty() && cx.tcx.features().never_type {
                span_lint_and_help(
                    cx,
                    EMPTY_ENUM,
                    item.span,
                    "enum with no variants",
                    None,
                    "consider using the uninhabited type `!` (never type) or a wrapper \
                    around it to introduce a type which can't be instantiated",
                );
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate tiny_http;
extern crate multipart;

use multipart::server::{Multipart, Entries, SaveResult};
fn main() {
    let server = tiny_http::Server::http("localhost:80").unwrap();
    loop {
        // blocks until the next request is received
        let mut request = server.recv().unwrap();

        let mut multipart = Multipart::from_request(&mut request).unwrap();
        match multipart.save_all() {
            SaveResult::Full(entries) => process_entries(entries).unwrap(),
            SaveResult::Partial(entries, error) => {
                process_entries(entries).unwrap();
                panic!("{:?}", error)
            },
            SaveResult::Error(error) => panic!("{:?}", error)
        }
    }
}

use std::io::prelude::*;
use std::fs::File;
use std::io::Error;
fn process_entries(entries: Entries) -> Result<(), Error> {
    for (name, field) in entries.fields {
        println!(r#"Field "{}": "{}""#, name, field);
    }

    for (name, savedfile) in entries.files {
        let filename = match savedfile.filename {
            Some(s) => s,
            None => "None".into()
        };
        let mut f = try!(File::open(savedfile.path));

        let mut s = String::new();
        try!(f.read_to_string(&mut s));
        println!(r#"Field "{}" is file "{}":"#, name, filename);
        println!("{}", s);
    }
    Ok(())
}
<commit_msg>Commented the sample for tiny_http<commit_after>extern crate tiny_http;
extern crate multipart;

use multipart::server::{Multipart, Entries, SaveResult};
fn main() {
    // Starting a server on `localhost:80`
    let server = tiny_http::Server::http("localhost:80").unwrap();
    loop {
        // This blocks until the next request is received
        let mut request = server.recv().unwrap();

        // Getting a multipart reader wrapper
        let mut multipart = Multipart::from_request(&mut request).unwrap();
        // Fetching all data and processing it
        match multipart.save_all() {
            SaveResult::Full(entries) => process_entries(entries).unwrap(),
            SaveResult::Partial(entries, error) => {
                process_entries(entries).unwrap();
                panic!("{:?}", error)
            },
            SaveResult::Error(error) => panic!("{:?}", error)
        }
    }
}

use std::io::prelude::*;
use std::fs::File;
use std::io::Error;
fn process_entries(entries: Entries) -> Result<(), Error> {
    for (name, field) in entries.fields {
        println!(r#"Field "{}": "{}""#, name, field);
    }

    for (name, savedfile) in entries.files {
        let filename = match savedfile.filename {
            Some(s) => s,
            None => "None".into()
        };
        let mut file = try!(File::open(savedfile.path));
        let mut contents = String::new();
        try!(file.read_to_string(&mut contents));

        println!(r#"Field "{}" is file "{}":"#, name, filename);
        println!("{}", contents);
    }
    Ok(())
}
<|endoftext|>


<commit_before>//! Low-level bindings to libm

#![cfg(target_os = "linux")]

extern crate linux_api;

use linux_api::{c_double, c_float,
                c_long, c_longlong};

#[link(name = "m")] //For -lm
extern {

    ///Returns the cosine of an angle of X radians
    pub fn cos(x: c_double) -> c_double;

    ///Returns the cosine of an angle of X radians
    pub fn cosf(x: c_float) -> c_float;

    //sin
    //tan
    //acos
    //asin
    //atan
    //atan2

    //cosh
    //sinh
    //tanh
    //acosh
    //asinh
    //atanh

    //exp
    //frexp
    //ldexp
    //log
    //log10
    //modf
    //exp2
    //expm1
    //ilogb
    //log1p
    //log2
    //logb
    //scalbn
    //scalbln

    //pow
    //sqrt
    //cbrt
    //hopot

    //erf
    //erfc
    //tgamma
    //lgamma

    //ceil
    //floor
    //fmod
    //trunc
    //round
    //lround
    //llround

    ///Rounds to an integer value in c_double format
    ///
    ///If you want an integer format, use lrint instead
    pub fn rint(x: c_double) -> c_double;

    ///Rounds to an integer value in c_float format
    ///
    ///If you want an integer format, use lrintf instead
    pub fn rintf(x: c_float) -> c_float;

    ///Rounds a c_double to the nearest c_long
    pub fn lrint(x: c_double) -> c_long;

    ///Rounds a c_float to the nearest c_long
    pub fn lrintf(x: c_float) -> c_long;

    ///Rounds a c_double to the nearest c_longlong
    pub fn llrint(x: c_double) -> c_longlong;

    ///Rounds a c_float to the nearest c_longlong
    pub fn llrintf(x: c_float) -> c_longlong;

    ///Rounds to an integer value in c_double format
    ///
    ///If you want an integer format, use lrint instead
    pub fn nearbyint(x: c_double) -> c_double;

    ///Rounds to an integer value in c_float format
    ///
    ///If you want an integer format, use lrintf instead
    pub fn nearbyintf(x: c_float) -> c_float;

    ///Returns the floating-point remainder of numer / denom
    pub fn remainder(numer: c_double, denom: c_double) -> c_double;

    ///Returns the floating-point remainder of numer / denom
    pub fn remainderf(number: c_float, denom: c_float) -> c_float;

    //remquo

    //copysign
    //nan
    //nextafter
    //nexttoward

    //fdim
    //fmax
    //fmin

    //fabs
    //abs
    //fma

}

#[cfg(test)]
#[allow(unused_assignments)] // Unsafe functions
mod test {

    extern crate linux_api;

    use linux_api::{c_long, c_longlong, c_float, c_double};

    use super::*;

    #[test]
    fn test_cos() {
        let pi: c_double = 3.14159265;

        let degrees: c_double = 60.0;

        unsafe {
            let result = cos(degrees * pi / 180.0);

            assert!(result.abs_sub(0.5) <= 0.000001);
        }
    }

    #[test]
    fn test_cosf() {
        let pi: c_float = 3.14159265;

        let degrees: c_float = 60.0;

        unsafe {
            let result = cosf(degrees * pi / 180.0);

            assert!(result.abs_sub(0.5) <= 0.000001);
        }
    }

    #[test]
    fn test_rint() {

        let value = 246.246f64;

        let mut result = 0f64;

        unsafe { result = rint(value); }

        assert_eq!(246.0f64, result);
    }

    #[test]
    fn test_rintf() {

        let value = 2543637.536f32;

        let mut result = 0f32;

        unsafe { result = rintf(value); }

        assert_eq!(2543638.0f32, result);
    }

    #[test]
    fn test_nearbyint() {

        let value = 246.246f64;

        let mut result = 0f64;

        unsafe { result = nearbyint(value); }

        assert_eq!(246.0f64, result);
    }

    #[test]
    fn test_nearbyintf() {

        let value = 2543637.536f32;

        let mut result = 0f32;

        unsafe { result = nearbyintf(value); }

        assert_eq!(2543638.0f32, result);
    }

    #[test]
    fn test_lrint() {

        let value = 2464326.432f64;

        let mut result: c_long = 0;

        unsafe { result = lrint(value); }

        assert_eq!(2464326, result);

    }

    #[test]
    fn test_lrintf() {

        let value = 2464326.432f32;

        let mut result: c_long = 0;

        unsafe { result = lrintf(value); }

        assert_eq!(2464326, result);

    }

    #[test]
    fn test_llrint() {

        let value = 46873283884.432f64;

        let mut result: c_longlong = 0;

        unsafe { result = llrint(value); }

        assert_eq!(46873283884, result);

    }

    #[test]
    fn test_llrintf() {

        let value = 4687328.9732f32;

        let mut result: c_longlong = 0;

        unsafe { result = llrintf(value); }

        assert_eq!(4687329, result);

    }

    #[test]
    fn test_remainder() {
        let number: c_double = 18.5;
        let denominator: c_double = 4.2;

        unsafe {
            assert!(remainder(number, denominator).abs_sub(1.7) <= 0.0000001);
        }
    }

    #[test]
    fn test_remainderf() {
        let number: c_float = 5.3;
        let denominator: c_float = 2.0;

        unsafe {
            assert!(remainderf(number, denominator).abs_sub(0.7) <= 0.0000001);
        }
    }

}
<commit_msg>Add and test sin, sinf, tan, and tanf<commit_after>//! Low-level bindings to libm

#![cfg(target_os = "linux")]

extern crate linux_api;

use linux_api::{c_double, c_float,
                c_long, c_longlong};

#[link(name = "m")] //For -lm
extern {

    ///Returns the cosine of an angle of X radians
    pub fn cos(x: c_double) -> c_double;

    ///Returns the cosine of an angle of X radians
    pub fn cosf(x: c_float) -> c_float;

    ///Returns the sine of an angle of x radians
    pub fn sin(x: c_double) -> c_double;

    ///Returns the sine of an angle of x radians
    pub fn sinf(x: c_float) -> c_float;

    ///Returns the tangent of an angle of x radians
    pub fn tan(x: c_double) -> c_double;

    ///Returns the tangent of an angle of x radians
    pub fn tanf(x: c_float) -> c_float;

    //acos
    //asin
    //atan
    //atan2

    //cosh
    //sinh
    //tanh
    //acosh
    //asinh
    //atanh

    //exp
    //frexp
    //ldexp
    //log
    //log10
    //modf
    //exp2
    //expm1
    //ilogb
    //log1p
    //log2
    //logb
    //scalbn
    //scalbln

    //pow
    //sqrt
    //cbrt
    //hopot

    //erf
    //erfc
    //tgamma
    //lgamma

    //ceil
    //floor
    //fmod
    //trunc
    //round
    //lround
    //llround

    ///Rounds to an integer value in c_double format
    ///
    ///If you want an integer format, use lrint instead
    pub fn rint(x: c_double) -> c_double;

    ///Rounds to an integer value in c_float format
    ///
    ///If you want an integer format, use lrintf instead
    pub fn rintf(x: c_float) -> c_float;

    ///Rounds a c_double to the nearest c_long
    pub fn lrint(x: c_double) -> c_long;

    ///Rounds a c_float to the nearest c_long
    pub fn lrintf(x: c_float) -> c_long;

    ///Rounds a c_double to the nearest c_longlong
    pub fn llrint(x: c_double) -> c_longlong;

    ///Rounds a c_float to the nearest c_longlong
    pub fn llrintf(x: c_float) -> c_longlong;

    ///Rounds to an integer value in c_double format
    ///
    ///If you want an integer format, use lrint instead
    pub fn nearbyint(x: c_double) -> c_double;

    ///Rounds to an integer value in c_float format
    ///
    ///If you want an integer format, use lrintf instead
    pub fn nearbyintf(x: c_float) -> c_float;

    ///Returns the floating-point remainder of numer / denom
    pub fn remainder(numer: c_double, denom: c_double) -> c_double;

    ///Returns the floating-point remainder of numer / denom
    pub fn remainderf(number: c_float, denom: c_float) -> c_float;

    //remquo

    //copysign
    //nan
    //nextafter
    //nexttoward

    //fdim
    //fmax
    //fmin

    //fabs
    //abs
    //fma

}

#[cfg(test)]
#[allow(unused_assignments)] // Unsafe functions
mod test {

    extern crate linux_api;

    use linux_api::{c_long, c_longlong, c_float, c_double};

    use super::*;

    #[test]
    fn test_cos() {
        let pi: c_double = 3.14159265;

        let degrees: c_double = 60.0;

        unsafe {
            let result = cos(degrees * pi / 180.0);

            assert!(result.abs_sub(0.5) <= 0.000001);
        }
    }

    #[test]
    fn test_cosf() {
        let pi: c_float = 3.14159265;

        let degrees: c_float = 60.0;

        unsafe {
            let result = cosf(degrees * pi / 180.0);

            assert!(result.abs_sub(0.5) <= 0.000001);
        }
    }

    #[test]
    fn test_sin() {
        let pi: c_double = 3.14159265;

        let degrees: c_double = 30.0;

        unsafe {
            let result = sin(degrees * pi / 180.0);

            assert!(result.abs_sub(0.5) <= 0.000001);
        }
    }

    #[test]
    fn test_sinf() {
        let pi: c_float = 3.14159265;

        let degrees: c_float = 30.0;

        unsafe {
            let result = sinf(degrees * pi / 180.0);

            assert!(result.abs_sub(0.5) <= 0.000001);
        }
    }

    #[test]
    fn test_tan() {
        let pi: c_double = 3.14159265;

        let degrees: c_double = 45.0;

        unsafe {
            let result = tan(degrees * pi / 180.0);

            assert!(result.abs_sub(1.0) <= 0.000001);
        }
    }

    #[test]
    fn test_tanf() {
        let pi: c_float = 3.14159265;

        let degrees: c_float = 45.0;

        unsafe {
            let result = tanf(degrees * pi / 180.0);

            assert!(result.abs_sub(1.0) <= 0.000001);
        }
    }

    #[test]
    fn test_rint() {

        let value = 246.246f64;

        let mut result = 0f64;

        unsafe { result = rint(value); }

        assert_eq!(246.0f64, result);
    }

    #[test]
    fn test_rintf() {

        let value = 2543637.536f32;

        let mut result = 0f32;

        unsafe { result = rintf(value); }

        assert_eq!(2543638.0f32, result);
    }

    #[test]
    fn test_nearbyint() {

        let value = 246.246f64;

        let mut result = 0f64;

        unsafe { result = nearbyint(value); }

        assert_eq!(246.0f64, result);
    }

    #[test]
    fn test_nearbyintf() {

        let value = 2543637.536f32;

        let mut result = 0f32;

        unsafe { result = nearbyintf(value); }

        assert_eq!(2543638.0f32, result);
    }

    #[test]
    fn test_lrint() {

        let value = 2464326.432f64;

        let mut result: c_long = 0;

        unsafe { result = lrint(value); }

        assert_eq!(2464326, result);

    }

    #[test]
    fn test_lrintf() {

        let value = 2464326.432f32;

        let mut result: c_long = 0;

        unsafe { result = lrintf(value); }

        assert_eq!(2464326, result);

    }

    #[test]
    fn test_llrint() {

        let value = 46873283884.432f64;

        let mut result: c_longlong = 0;

        unsafe { result = llrint(value); }

        assert_eq!(46873283884, result);

    }

    #[test]
    fn test_llrintf() {

        let value = 4687328.9732f32;

        let mut result: c_longlong = 0;

        unsafe { result = llrintf(value); }

        assert_eq!(4687329, result);

    }

    #[test]
    fn test_remainder() {
        let number: c_double = 18.5;
        let denominator: c_double = 4.2;

        unsafe {
            assert!(remainder(number, denominator).abs_sub(1.7) <= 0.0000001);
        }
    }

    #[test]
    fn test_remainderf() {
        let number: c_float = 5.3;
        let denominator: c_float = 2.0;

        unsafe {
            assert!(remainderf(number, denominator).abs_sub(0.7) <= 0.0000001);
        }
    }

}
<|endoftext|>


<commit_before>use super::{SecretKey, BLS_PUBLIC_KEY_BYTE_SIZE};
use bls_aggregates::PublicKey as RawPublicKey;
use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector;
use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use serde_hex::{encode as hex_encode, HexVisitor};
use ssz::{ssz_encode, Decode, DecodeError};
use std::default;
use std::fmt;
use std::hash::{Hash, Hasher};
use tree_hash::tree_hash_ssz_encoding_as_vector;

/// A single BLS signature.
///
/// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ
/// serialization).
#[derive(Debug, Clone, Eq)]
pub struct PublicKey(RawPublicKey);

impl PublicKey {
    pub fn from_secret_key(secret_key: &SecretKey) -> Self {
        PublicKey(RawPublicKey::from_secret_key(secret_key.as_raw()))
    }

    /// Returns the underlying signature.
    pub fn as_raw(&self) -> &RawPublicKey {
        &self.0
    }

    /// Returns the underlying point as compressed bytes.
    ///
    /// Identical to `self.as_uncompressed_bytes()`.
    fn as_bytes(&self) -> Vec<u8> {
        self.as_raw().as_bytes()
    }

    /// Converts compressed bytes to PublicKey
    pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
        let pubkey = RawPublicKey::from_bytes(&bytes).map_err(|_| {
            DecodeError::BytesInvalid(format!("Invalid PublicKey bytes: {:?}", bytes).to_string())
        })?;

        Ok(PublicKey(pubkey))
    }

    /// Returns the PublicKey as (x, y) bytes
    pub fn as_uncompressed_bytes(&self) -> Vec<u8> {
        RawPublicKey::as_uncompressed_bytes(&mut self.0.clone())
    }

    /// Converts (x, y) bytes to PublicKey
    pub fn from_uncompressed_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
        let pubkey = RawPublicKey::from_uncompressed_bytes(&bytes).map_err(|_| {
            DecodeError::BytesInvalid("Invalid PublicKey uncompressed bytes.".to_string())
        })?;
        Ok(PublicKey(pubkey))
    }

    /// Returns the last 6 bytes of the SSZ encoding of the public key, as a hex string.
    ///
    /// Useful for providing a short identifier to the user.
    pub fn concatenated_hex_id(&self) -> String {
        let bytes = ssz_encode(self);
        let end_bytes = &bytes[bytes.len().saturating_sub(6)..bytes.len()];
        hex_encode(end_bytes)
    }
}

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

impl default::Default for PublicKey {
    fn default() -> Self {
        let secret_key = SecretKey::random();
        PublicKey::from_secret_key(&secret_key)
    }
}

impl_ssz!(PublicKey, BLS_PUBLIC_KEY_BYTE_SIZE, "PublicKey");

impl Serialize for PublicKey {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&hex_encode(self.as_raw().as_bytes()))
    }
}

impl<'de> Deserialize<'de> for PublicKey {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let bytes = deserializer.deserialize_str(HexVisitor)?;
        let pubkey = Self::from_ssz_bytes(&bytes[..])
            .map_err(|e| serde::de::Error::custom(format!("invalid pubkey ({:?})", e)))?;
        Ok(pubkey)
    }
}

tree_hash_ssz_encoding_as_vector!(PublicKey);
cached_tree_hash_ssz_encoding_as_vector!(PublicKey, 48);

impl PartialEq for PublicKey {
    fn eq(&self, other: &PublicKey) -> bool {
        ssz_encode(self) == ssz_encode(other)
    }
}

impl Hash for PublicKey {
    /// Note: this is distinct from consensus serialization, it will produce a different hash.
    ///
    /// This method uses the uncompressed bytes, which are much faster to obtain than the
    /// compressed bytes required for consensus serialization.
    ///
    /// Use `ssz::Encode` to obtain the bytes required for consensus hashing.
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.as_uncompressed_bytes().hash(state)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ssz::ssz_encode;
    use tree_hash::TreeHash;

    #[test]
    pub fn test_ssz_round_trip() {
        let sk = SecretKey::random();
        let original = PublicKey::from_secret_key(&sk);

        let bytes = ssz_encode(&original);
        let decoded = PublicKey::from_ssz_bytes(&bytes).unwrap();

        assert_eq!(original, decoded);
    }

    #[test]
    pub fn test_cached_tree_hash() {
        let sk = SecretKey::random();
        let original = PublicKey::from_secret_key(&sk);

        let mut cache = cached_tree_hash::TreeHashCache::new(&original).unwrap();

        assert_eq!(
            cache.tree_hash_root().unwrap().to_vec(),
            original.tree_hash_root()
        );

        let sk = SecretKey::random();
        let modified = PublicKey::from_secret_key(&sk);

        cache.update(&modified).unwrap();

        assert_eq!(
            cache.tree_hash_root().unwrap().to_vec(),
            modified.tree_hash_root()
        );
    }
}
<commit_msg>Use hex encoding for `Debug` fmt of `PublicKey`<commit_after>use super::{SecretKey, BLS_PUBLIC_KEY_BYTE_SIZE};
use bls_aggregates::PublicKey as RawPublicKey;
use cached_tree_hash::cached_tree_hash_ssz_encoding_as_vector;
use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use serde_hex::{encode as hex_encode, HexVisitor};
use ssz::{Decode, DecodeError, Encode};
use std::default;
use std::fmt;
use std::hash::{Hash, Hasher};
use tree_hash::tree_hash_ssz_encoding_as_vector;

/// A single BLS signature.
///
/// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ
/// serialization).
#[derive(Clone, Eq)]
pub struct PublicKey(RawPublicKey);

impl PublicKey {
    pub fn from_secret_key(secret_key: &SecretKey) -> Self {
        PublicKey(RawPublicKey::from_secret_key(secret_key.as_raw()))
    }

    /// Returns the underlying signature.
    pub fn as_raw(&self) -> &RawPublicKey {
        &self.0
    }

    /// Returns the underlying point as compressed bytes.
    ///
    /// Identical to `self.as_uncompressed_bytes()`.
    fn as_bytes(&self) -> Vec<u8> {
        self.as_raw().as_bytes()
    }

    /// Converts compressed bytes to PublicKey
    pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
        let pubkey = RawPublicKey::from_bytes(&bytes).map_err(|_| {
            DecodeError::BytesInvalid(format!("Invalid PublicKey bytes: {:?}", bytes).to_string())
        })?;

        Ok(PublicKey(pubkey))
    }

    /// Returns the PublicKey as (x, y) bytes
    pub fn as_uncompressed_bytes(&self) -> Vec<u8> {
        RawPublicKey::as_uncompressed_bytes(&mut self.0.clone())
    }

    /// Converts (x, y) bytes to PublicKey
    pub fn from_uncompressed_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
        let pubkey = RawPublicKey::from_uncompressed_bytes(&bytes).map_err(|_| {
            DecodeError::BytesInvalid("Invalid PublicKey uncompressed bytes.".to_string())
        })?;
        Ok(PublicKey(pubkey))
    }

    /// Returns the last 6 bytes of the SSZ encoding of the public key, as a hex string.
    ///
    /// Useful for providing a short identifier to the user.
    pub fn concatenated_hex_id(&self) -> String {
        self.as_hex_string()[0..6].to_string()
    }

    /// Returns the point as a hex string of the SSZ encoding.
    ///
    /// Note: the string is prefixed with `0x`.
    pub fn as_hex_string(&self) -> String {
        hex_encode(self.as_ssz_bytes())
    }
}

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

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

impl default::Default for PublicKey {
    fn default() -> Self {
        let secret_key = SecretKey::random();
        PublicKey::from_secret_key(&secret_key)
    }
}

impl_ssz!(PublicKey, BLS_PUBLIC_KEY_BYTE_SIZE, "PublicKey");

impl Serialize for PublicKey {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&hex_encode(self.as_raw().as_bytes()))
    }
}

impl<'de> Deserialize<'de> for PublicKey {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let bytes = deserializer.deserialize_str(HexVisitor)?;
        let pubkey = Self::from_ssz_bytes(&bytes[..])
            .map_err(|e| serde::de::Error::custom(format!("invalid pubkey ({:?})", e)))?;
        Ok(pubkey)
    }
}

tree_hash_ssz_encoding_as_vector!(PublicKey);
cached_tree_hash_ssz_encoding_as_vector!(PublicKey, 48);

impl PartialEq for PublicKey {
    fn eq(&self, other: &PublicKey) -> bool {
        self.as_ssz_bytes() == other.as_ssz_bytes()
    }
}

impl Hash for PublicKey {
    /// Note: this is distinct from consensus serialization, it will produce a different hash.
    ///
    /// This method uses the uncompressed bytes, which are much faster to obtain than the
    /// compressed bytes required for consensus serialization.
    ///
    /// Use `ssz::Encode` to obtain the bytes required for consensus hashing.
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.as_uncompressed_bytes().hash(state)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ssz::ssz_encode;
    use tree_hash::TreeHash;

    #[test]
    pub fn test_ssz_round_trip() {
        let sk = SecretKey::random();
        let original = PublicKey::from_secret_key(&sk);

        let bytes = ssz_encode(&original);
        let decoded = PublicKey::from_ssz_bytes(&bytes).unwrap();

        assert_eq!(original, decoded);
    }

    #[test]
    pub fn test_cached_tree_hash() {
        let sk = SecretKey::random();
        let original = PublicKey::from_secret_key(&sk);

        let mut cache = cached_tree_hash::TreeHashCache::new(&original).unwrap();

        assert_eq!(
            cache.tree_hash_root().unwrap().to_vec(),
            original.tree_hash_root()
        );

        let sk = SecretKey::random();
        let modified = PublicKey::from_secret_key(&sk);

        cache.update(&modified).unwrap();

        assert_eq!(
            cache.tree_hash_root().unwrap().to_vec(),
            modified.tree_hash_root()
        );
    }
}
<|endoftext|>


<commit_before>#![cfg(feature = "full")]

#[macro_use]
extern crate quote;
extern crate regex;
extern crate syn;
extern crate syntex_pos;
extern crate syntex_syntax;
extern crate time;
extern crate walkdir;

use syntex_pos::Span;
use syntex_syntax::ast;
use syntex_syntax::parse::{self, ParseSess, PResult};
use time::PreciseTime;

use std::fs::File;
use std::io::{self, Read, Write};

macro_rules! errorf {
    ($($tt:tt)*) => {
        write!(io::stderr(), $($tt)*).unwrap();
    };
}

#[test]
fn test_round_trip() {
    let mut failed = 0;

    for entry in walkdir::WalkDir::new("tests/cases").into_iter() {
        let entry = entry.unwrap();

        let path = entry.path();
        if path.extension().map(|e| e != "rs").unwrap_or(true) {
            continue;
        }
        errorf!("=== {}: ", path.display());

        let mut file = File::open(path).unwrap();
        let mut content = String::new();
        file.read_to_string(&mut content).unwrap();

        let start = PreciseTime::now();
        let (krate, elapsed) = match syn::parse_crate(&content) {
            Ok(krate) => (krate, start.to(PreciseTime::now())),
            Err(msg) => {
                errorf!("syn failed to parse\n{}\n", msg);
                failed += 1;
                continue;
            }
        };
        let back = quote!(#krate).to_string();

        let sess = ParseSess::new();
        let before = syntex_parse(content, &sess).unwrap();
        let after = match syntex_parse(back, &sess) {
            Ok(after) => after,
            Err(mut diagnostic) => {
                errorf!("syntex failed to parse");
                diagnostic.emit();
                failed += 1;
                continue;
            }
        };

        if before == after {
            errorf!("pass in {}ms\n", elapsed.num_milliseconds());
        } else {
            errorf!("FAIL\nbefore: {:?}\nafter: {:?}\n", before, after);
            failed += 1;
        }
    }

    if failed > 0 {
        panic!("{} failures", failed);
    }
}

fn syntex_parse<'a>(content: String, sess: &'a ParseSess) -> PResult<'a, ast::Crate> {
    let name = "test_round_trip".to_string();
    let cfg = Vec::new();
    parse::parse_crate_from_source_str(name, content, cfg, sess).map(respan_crate)
}

fn respan_crate(krate: ast::Crate) -> ast::Crate {
    use regex::Regex;
    use std::rc::Rc;
    use syntex_syntax::ast::{Attribute, Expr, ExprKind, Field, FnDecl, FunctionRetTy, ImplItem,
                             ImplItemKind, ItemKind, Lit, LitKind, Mac, MethodSig, TraitItem,
                             TraitItemKind, TyParam};
    use syntex_syntax::codemap::{self, Spanned};
    use syntex_syntax::fold::{self, Folder};
    use syntex_syntax::parse::token::{Lit as TokenLit, Token, intern as intern_n,
                                      intern_and_get_ident as intern_s};
    use syntex_syntax::ptr::P;
    use syntex_syntax::tokenstream::{Delimited, SequenceRepetition, TokenTree};
    use syntex_syntax::util::move_map::MoveMap;
    use syntex_syntax::util::small_vector::SmallVector;

    struct Respanner {
        multiline_regex: Regex,
    }

    impl Respanner {
        fn new() -> Self {
            Respanner { multiline_regex: Regex::new(r"(?m)\\\n *").unwrap() }
        }

        fn fold_spanned<T>(&mut self, spanned: Spanned<T>) -> Spanned<T> {
            codemap::respan(self.new_span(spanned.span), spanned.node)
        }

        fn fold_lit(&mut self, l: Lit) -> Lit {
            let node = match l.node {
                LitKind::Str(value, style) => {
                    LitKind::Str(intern_s(&self.multiline_regex.replace_all(&value, "")),
                                 style)
                }
                LitKind::Float(repr, ty) => {
                    LitKind::Float(intern_s(&repr.to_string().replace("_", "")), ty)
                }
                _ => l.node,
            };
            codemap::respan(self.new_span(l.span), node)
        }

        fn fold_token_lit(&mut self, l: TokenLit) -> TokenLit {
            match l {
                TokenLit::Integer(repr) => {
                    TokenLit::Integer(intern_n(&repr.to_string().replace("_", "")))
                }
                TokenLit::Str_(repr) => {
                    TokenLit::Str_(intern_n(&self.multiline_regex
                        .replace_all(&repr.to_string(), "")))
                }
                TokenLit::Float(repr) => {
                    TokenLit::Float(intern_n(&repr.to_string().replace("_", "")))
                }
                _ => l,
            }
        }
    }

    impl Folder for Respanner {
        fn new_span(&mut self, _: Span) -> Span {
            syntex_pos::DUMMY_SP
        }

        fn fold_item_kind(&mut self, i: ItemKind) -> ItemKind {
            match i {
                ItemKind::Fn(decl, unsafety, constness, abi, generics, body) => {
                    let generics = self.fold_generics(generics);
                    let decl = self.fold_fn_decl(decl);
                    let body = self.fold_block(body);
                    // default fold_item_kind does not fold this span
                    let constness = self.fold_spanned(constness);
                    ItemKind::Fn(decl, unsafety, constness, abi, generics, body)
                }
                _ => fold::noop_fold_item_kind(i, self),
            }
        }

        fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
            e.map(|e| {
                let folded = fold::noop_fold_expr(e, self);
                Expr {
                    node: match folded.node {
                        ExprKind::Lit(l) => {
                            // default fold_expr does not fold lits
                            ExprKind::Lit(l.map(|l| self.fold_lit(l)))
                        }
                        ExprKind::Binary(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::Binary(self.fold_spanned(op),
                                             self.fold_expr(lhs),
                                             self.fold_expr(rhs))
                        }
                        ExprKind::AssignOp(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::AssignOp(self.fold_spanned(op),
                                               self.fold_expr(lhs),
                                               self.fold_expr(rhs))
                        }
                        other => other,
                    },
                    ..folded
                }
            })
        }

        fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
            TyParam {
                // default fold_ty_param does not fold the span
                span: self.new_span(tp.span),
                ..fold::noop_fold_ty_param(tp, self)
            }
        }

        fn fold_fn_decl(&mut self, decl: P<FnDecl>) -> P<FnDecl> {
            decl.map(|FnDecl { inputs, output, variadic }| {
                FnDecl {
                    inputs: inputs.move_map(|x| self.fold_arg(x)),
                    output: match output {
                        FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(self.fold_ty(ty)),
                        // default fold_fn_decl does not fold this span
                        FunctionRetTy::Default(span) => FunctionRetTy::Default(self.new_span(span)),
                    },
                    variadic: variadic,
                }
            })
        }

        fn fold_field(&mut self, field: Field) -> Field {
            Field {
                ident: codemap::respan(// default fold_field does not fold this span
                                       self.new_span(field.ident.span),
                                       self.fold_ident(field.ident.node)),
                expr: self.fold_expr(field.expr),
                span: self.new_span(field.span),
            }
        }

        fn fold_trait_item(&mut self, i: TraitItem) -> SmallVector<TraitItem> {
            let noop = fold::noop_fold_trait_item(i, self).expect_one("");
            SmallVector::one(TraitItem {
                node: match noop.node {
                    TraitItemKind::Method(sig, body) => {
                        TraitItemKind::Method(MethodSig {
                                                  constness: self.fold_spanned(sig.constness),
                                                  ..sig
                                              },
                                              body)
                    }
                    node => node,
                },
                ..noop
            })
        }

        fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector<ImplItem> {
            let noop = fold::noop_fold_impl_item(i, self).expect_one("");
            SmallVector::one(ImplItem {
                node: match noop.node {
                    ImplItemKind::Method(sig, body) => {
                        ImplItemKind::Method(MethodSig {
                                                 constness: self.fold_spanned(sig.constness),
                                                 ..sig
                                             },
                                             body)
                    }
                    node => node,
                },
                ..noop
            })
        }

        fn fold_attribute(&mut self, mut at: Attribute) -> Option<Attribute> {
            at.node.id.0 = 0;
            fold::noop_fold_attribute(at, self)
        }

        fn fold_mac(&mut self, mac: Mac) -> Mac {
            fold::noop_fold_mac(mac, self)
        }

        fn fold_tt(&mut self, tt: &TokenTree) -> TokenTree {
            match *tt {
                TokenTree::Token(span, ref tok) => {
                    TokenTree::Token(self.new_span(span), self.fold_token(tok.clone()))
                }
                TokenTree::Delimited(span, ref delimed) => {
                    TokenTree::Delimited(self.new_span(span),
                                         Rc::new(Delimited {
                                             delim: delimed.delim,
                                             open_span: self.new_span(delimed.open_span),
                                             tts: self.fold_tts(&delimed.tts),
                                             close_span: self.new_span(delimed.close_span),
                                         }))
                }
                TokenTree::Sequence(span, ref seq) => {
                    TokenTree::Sequence(self.new_span(span),
                                        Rc::new(SequenceRepetition {
                                            tts: self.fold_tts(&seq.tts),
                                            separator: seq.separator
                                                .clone()
                                                .map(|tok| self.fold_token(tok)),
                                            ..**seq
                                        }))
                }
            }
        }

        fn fold_token(&mut self, t: Token) -> Token {
            match t {
                // default fold_token does not fold literals
                Token::Literal(lit, repr) => Token::Literal(self.fold_token_lit(lit), repr),
                Token::Ident(id) => Token::Ident(self.fold_ident(id)),
                Token::Lifetime(id) => Token::Lifetime(self.fold_ident(id)),
                Token::Interpolated(nt) => Token::Interpolated(self.fold_interpolated(nt)),
                Token::SubstNt(ident) => Token::SubstNt(self.fold_ident(ident)),
                Token::MatchNt(name, kind) => {
                    Token::MatchNt(self.fold_ident(name), self.fold_ident(kind))
                }
                _ => t,
            }
        }
    }

    Respanner::new().fold_crate(krate)
}
<commit_msg>No need to fold normalized lits<commit_after>#![cfg(feature = "full")]

#[macro_use]
extern crate quote;
extern crate regex;
extern crate syn;
extern crate syntex_pos;
extern crate syntex_syntax;
extern crate time;
extern crate walkdir;

use syntex_pos::Span;
use syntex_syntax::ast;
use syntex_syntax::parse::{self, ParseSess, PResult};
use time::PreciseTime;

use std::fs::File;
use std::io::{self, Read, Write};

macro_rules! errorf {
    ($($tt:tt)*) => {
        write!(io::stderr(), $($tt)*).unwrap();
    };
}

#[test]
fn test_round_trip() {
    let mut failed = 0;

    for entry in walkdir::WalkDir::new("tests/cases").into_iter() {
        let entry = entry.unwrap();

        let path = entry.path();
        if path.extension().map(|e| e != "rs").unwrap_or(true) {
            continue;
        }
        errorf!("=== {}: ", path.display());

        let mut file = File::open(path).unwrap();
        let mut content = String::new();
        file.read_to_string(&mut content).unwrap();

        let start = PreciseTime::now();
        let (krate, elapsed) = match syn::parse_crate(&content) {
            Ok(krate) => (krate, start.to(PreciseTime::now())),
            Err(msg) => {
                errorf!("syn failed to parse\n{}\n", msg);
                failed += 1;
                continue;
            }
        };
        let back = quote!(#krate).to_string();

        let sess = ParseSess::new();
        let before = syntex_parse(content, &sess).unwrap();
        let after = match syntex_parse(back, &sess) {
            Ok(after) => after,
            Err(mut diagnostic) => {
                errorf!("syntex failed to parse");
                diagnostic.emit();
                failed += 1;
                continue;
            }
        };

        if before == after {
            errorf!("pass in {}ms\n", elapsed.num_milliseconds());
        } else {
            errorf!("FAIL\nbefore: {:?}\nafter: {:?}\n", before, after);
            failed += 1;
        }
    }

    if failed > 0 {
        panic!("{} failures", failed);
    }
}

fn syntex_parse<'a>(content: String, sess: &'a ParseSess) -> PResult<'a, ast::Crate> {
    let name = "test_round_trip".to_string();
    let cfg = Vec::new();
    parse::parse_crate_from_source_str(name, content, cfg, sess).map(respan_crate)
}

fn respan_crate(krate: ast::Crate) -> ast::Crate {
    use regex::Regex;
    use std::rc::Rc;
    use syntex_syntax::ast::{Attribute, Expr, ExprKind, Field, FnDecl, FunctionRetTy, ImplItem,
                             ImplItemKind, ItemKind, Mac, MethodSig, TraitItem, TraitItemKind,
                             TyParam};
    use syntex_syntax::codemap::{self, Spanned};
    use syntex_syntax::fold::{self, Folder};
    use syntex_syntax::parse::token::{Lit, Token, intern};
    use syntex_syntax::ptr::P;
    use syntex_syntax::tokenstream::{Delimited, SequenceRepetition, TokenTree};
    use syntex_syntax::util::move_map::MoveMap;
    use syntex_syntax::util::small_vector::SmallVector;

    struct Respanner {
        multiline_regex: Regex,
    }

    impl Respanner {
        fn new() -> Self {
            Respanner { multiline_regex: Regex::new(r"(?m)\\\n *").unwrap() }
        }

        fn fold_spanned<T>(&mut self, spanned: Spanned<T>) -> Spanned<T> {
            codemap::respan(self.new_span(spanned.span), spanned.node)
        }

        fn fold_lit(&mut self, l: Lit) -> Lit {
            match l {
                Lit::Integer(repr) => {
                    Lit::Integer(intern(&repr.to_string().replace("_", "")))
                }
                Lit::Str_(repr) => {
                    Lit::Str_(intern(&self.multiline_regex
                        .replace_all(&repr.to_string(), "")))
                }
                Lit::Float(repr) => {
                    Lit::Float(intern(&repr.to_string().replace("_", "")))
                }
                _ => l,
            }
        }
    }

    impl Folder for Respanner {
        fn new_span(&mut self, _: Span) -> Span {
            syntex_pos::DUMMY_SP
        }

        fn fold_item_kind(&mut self, i: ItemKind) -> ItemKind {
            match i {
                ItemKind::Fn(decl, unsafety, constness, abi, generics, body) => {
                    let generics = self.fold_generics(generics);
                    let decl = self.fold_fn_decl(decl);
                    let body = self.fold_block(body);
                    // default fold_item_kind does not fold this span
                    let constness = self.fold_spanned(constness);
                    ItemKind::Fn(decl, unsafety, constness, abi, generics, body)
                }
                _ => fold::noop_fold_item_kind(i, self),
            }
        }

        fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
            e.map(|e| {
                let folded = fold::noop_fold_expr(e, self);
                Expr {
                    node: match folded.node {
                        ExprKind::Lit(l) => {
                            // default fold_expr does not fold lits
                            ExprKind::Lit(l.map(|l| self.fold_spanned(l)))
                        }
                        ExprKind::Binary(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::Binary(self.fold_spanned(op),
                                             self.fold_expr(lhs),
                                             self.fold_expr(rhs))
                        }
                        ExprKind::AssignOp(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::AssignOp(self.fold_spanned(op),
                                               self.fold_expr(lhs),
                                               self.fold_expr(rhs))
                        }
                        other => other,
                    },
                    ..folded
                }
            })
        }

        fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
            TyParam {
                // default fold_ty_param does not fold the span
                span: self.new_span(tp.span),
                ..fold::noop_fold_ty_param(tp, self)
            }
        }

        fn fold_fn_decl(&mut self, decl: P<FnDecl>) -> P<FnDecl> {
            decl.map(|FnDecl { inputs, output, variadic }| {
                FnDecl {
                    inputs: inputs.move_map(|x| self.fold_arg(x)),
                    output: match output {
                        FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(self.fold_ty(ty)),
                        // default fold_fn_decl does not fold this span
                        FunctionRetTy::Default(span) => FunctionRetTy::Default(self.new_span(span)),
                    },
                    variadic: variadic,
                }
            })
        }

        fn fold_field(&mut self, field: Field) -> Field {
            Field {
                ident: codemap::respan(// default fold_field does not fold this span
                                       self.new_span(field.ident.span),
                                       self.fold_ident(field.ident.node)),
                expr: self.fold_expr(field.expr),
                span: self.new_span(field.span),
            }
        }

        fn fold_trait_item(&mut self, i: TraitItem) -> SmallVector<TraitItem> {
            let noop = fold::noop_fold_trait_item(i, self).expect_one("");
            SmallVector::one(TraitItem {
                node: match noop.node {
                    TraitItemKind::Method(sig, body) => {
                        TraitItemKind::Method(MethodSig {
                                                  constness: self.fold_spanned(sig.constness),
                                                  ..sig
                                              },
                                              body)
                    }
                    node => node,
                },
                ..noop
            })
        }

        fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector<ImplItem> {
            let noop = fold::noop_fold_impl_item(i, self).expect_one("");
            SmallVector::one(ImplItem {
                node: match noop.node {
                    ImplItemKind::Method(sig, body) => {
                        ImplItemKind::Method(MethodSig {
                                                 constness: self.fold_spanned(sig.constness),
                                                 ..sig
                                             },
                                             body)
                    }
                    node => node,
                },
                ..noop
            })
        }

        fn fold_attribute(&mut self, mut at: Attribute) -> Option<Attribute> {
            at.node.id.0 = 0;
            fold::noop_fold_attribute(at, self)
        }

        fn fold_mac(&mut self, mac: Mac) -> Mac {
            fold::noop_fold_mac(mac, self)
        }

        fn fold_tt(&mut self, tt: &TokenTree) -> TokenTree {
            match *tt {
                TokenTree::Token(span, ref tok) => {
                    TokenTree::Token(self.new_span(span), self.fold_token(tok.clone()))
                }
                TokenTree::Delimited(span, ref delimed) => {
                    TokenTree::Delimited(self.new_span(span),
                                         Rc::new(Delimited {
                                             delim: delimed.delim,
                                             open_span: self.new_span(delimed.open_span),
                                             tts: self.fold_tts(&delimed.tts),
                                             close_span: self.new_span(delimed.close_span),
                                         }))
                }
                TokenTree::Sequence(span, ref seq) => {
                    TokenTree::Sequence(self.new_span(span),
                                        Rc::new(SequenceRepetition {
                                            tts: self.fold_tts(&seq.tts),
                                            separator: seq.separator
                                                .clone()
                                                .map(|tok| self.fold_token(tok)),
                                            ..**seq
                                        }))
                }
            }
        }

        fn fold_token(&mut self, t: Token) -> Token {
            match t {
                // default fold_token does not fold literals
                Token::Literal(lit, repr) => Token::Literal(self.fold_lit(lit), repr),
                Token::Ident(id) => Token::Ident(self.fold_ident(id)),
                Token::Lifetime(id) => Token::Lifetime(self.fold_ident(id)),
                Token::Interpolated(nt) => Token::Interpolated(self.fold_interpolated(nt)),
                Token::SubstNt(ident) => Token::SubstNt(self.fold_ident(ident)),
                Token::MatchNt(name, kind) => {
                    Token::MatchNt(self.fold_ident(name), self.fold_ident(kind))
                }
                _ => t,
            }
        }
    }

    Respanner::new().fold_crate(krate)
}
<|endoftext|>