<commit_before>//! Roundtrip (write-read) tests for supported LAS versions and attributes.

extern crate chrono;
extern crate las;

use las::{Header, Point, Reader, Writer};
use std::io::Cursor;

pub fn roundtrip(header: Header, point: Point) {
    let mut cursor = Cursor::new(Vec::new());
    {
        let mut writer = Writer::new(&mut cursor, header.clone()).unwrap();
        writer.write(point.clone()).unwrap();
    }
    cursor.set_position(0);
    let mut reader = Reader::new(cursor).unwrap();
    let other = reader.read().unwrap().unwrap();
    assert_eq!(point, other);
    assert_eq!(None, reader.read().unwrap());
    if reader.header.evlrs().len() == 0 {
        assert!(reader.read().expect("Error when reading EOF").is_none());
    }

    let other = reader.header;
    assert_eq!(header.guid, other.guid);
    assert_eq!(header.version, other.version);
    assert_eq!(header.transforms, other.transforms);
    assert_eq!(header.point_format, other.point_format);
    assert_eq!(1, other.number_of_points);
    assert_eq!(point.x, other.bounds.min.x);
    assert_eq!(point.x, other.bounds.max.x);
    assert_eq!(point.y, other.bounds.min.y);
    assert_eq!(point.y, other.bounds.max.y);
    assert_eq!(point.z, other.bounds.min.z);
    assert_eq!(point.z, other.bounds.max.z);
    if point.return_number > 0 {
        assert_eq!(1, other.number_of_points_by_return[&point.return_number]);
    }

    assert_eq!(header.vlrs, other.vlrs);
}

fn new_writer_fail(header: Header) {
    assert!(Writer::new(Cursor::new(Vec::new()), header).is_err());
}

macro_rules! roundtrip {
    ($name:ident, $major:expr, $minor:expr) => {
        mod $name {
            use chrono::{Utc, Duration};

            use las::{GpsTimeType, Color, Header, Point, Transform, Vector};
            use las::point::{ScanDirection, Classification};

            const VERSION: (u8, u8) = ($major, $minor);

            fn roundtrip(point: Point) {
                let header = Header { version: VERSION.into(), ..Default::default() };
                super::roundtrip(header, point);
            }

            fn roundtrip_with_format(point: Point, point_format: u8) {
                use las::point::Format;
                let header = Header {
                    version: VERSION.into(),
                    point_format: Format::new(point_format).unwrap(),
                    ..Default::default()
                };
                super::roundtrip(header, point);
            }

            #[test]
            fn xyz() {
                let point = Point {
                    x: 1.,
                    y: 2.,
                    z: 3.,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn intensity() {
                let point = Point {
                    intensity: 11,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn return_number() {
                let point = Point {
                    return_number: 1,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn number_of_returns() {
                let point = Point {
                    number_of_returns: 1,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn scan_direction_flag() {
                let point = Point {
                    scan_direction: ScanDirection::LeftToRight,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn is_edge_of_flight_line() {
                let point = Point {
                    is_edge_of_flight_line: true,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn classification() {
                let point = Point {
                    classification: Classification::Ground,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn scan_angle_rank() {
                let point = Point {
                    scan_angle: 2.,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn user_data() {
                let point = Point {
                    user_data: 1,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn point_source_id() {
                let point = Point {
                    point_source_id: 1,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn gps_time() {
                let point = Point {
                    gps_time: Some(1.),
                    ..Default::default()
                };
                roundtrip_with_format(point, 1);
            }

            #[test]
            fn transforms() {
                let point = Point {
                    x: 10.,
                    y: 20.,
                    z: 30.,
                    ..Default::default()
                };
                let transform = Transform { scale: 0.1, offset: -1. };
                let transforms = Vector {
                    x: transform,
                    y: transform,
                    z: transform,
                };
                let header = Header { version: VERSION.into(), transforms: transforms, ..Default::default() };
                super::roundtrip(header, point);
            }

            #[test]
            fn guid() {
                let header = Header { version: VERSION.into(), guid: [1; 16], ..Default::default() };
                super::roundtrip(header, Default::default());
            }

            #[test]
            fn system_identifier() {
                let header = Header { version: VERSION.into(), system_identifier: "Beer!".to_string(), ..Default::default() };
                super::roundtrip(header, Default::default());
            }

            #[test]
            fn generating_software() {
                let header = Header { version: VERSION.into(), generating_software: "Beer!".to_string(), ..Default::default() };
                super::roundtrip(header, Default::default());
            }

            #[test]
            fn date() {
                let header = Header { version: VERSION.into(), date: Some(Utc::today() - Duration::days(1)), ..Default::default() };
                super::roundtrip(header, Default::default());
            }

            #[test]
            fn padding() {
                let header = Header { version: VERSION.into(), padding: vec![1], ..Default::default() };
                super::roundtrip(header, Default::default());
            }

            #[test]
            fn vlr_padding() {
                let header = Header { version: VERSION.into(), vlr_padding: vec![0], ..Default::default() };
                super::roundtrip(header, Default::default());
            }

            #[test]
            fn vlrs() {
                let vlrs = vec![Default::default()];
                let header = Header { version: VERSION.into(), vlrs: vlrs, ..Default::default() };
                super::roundtrip(header, Default::default());
            }

            #[test]
            fn color() {
                use las::point::Format;
                let point = Point {
                    color: Some(Color { red: 1, green: 2, blue: 3}),
                    ..Default::default()
                };
                if VERSION == (1, 0) || VERSION == (1, 1) {
                    super::new_writer_fail(Header { version: VERSION.into(), point_format: Format::new(2).unwrap(), ..Default::default() });
                } else {
                    roundtrip_with_format(point, 2.into());
                }
            }

            #[test]
            fn file_source_id() {
                let header = Header { version: VERSION.into(), file_source_id: 1, ..Default::default() };
                if VERSION == (1, 0) {
                    super::new_writer_fail(header);
                } else {
                    super::roundtrip(header, Default::default());
                }
            }

            #[test]
            fn gps_time_type() {
                let header = Header { version: VERSION.into(), gps_time_type: GpsTimeType::Standard, ..Default::default() };
                if VERSION == (1, 0) || VERSION == (1, 1) {
                    super::new_writer_fail(header);
                } else {
                    super::roundtrip(header, Default::default());
                }
            }

            #[test]
            fn evlr() {
                use las::Vlr;
                use std::u16;
                let vlrs = vec![Vlr { is_extended: true, data: vec![42; u16::MAX as usize + 1], ..Default::default() }];
                let header = Header { version: VERSION.into(), vlrs: vlrs, ..Default::default() };
                if VERSION == (1, 4) {
                    super::roundtrip(header, Default::default());
                } else {
                    super::new_writer_fail(header);
                }
            }

            #[test]
            fn extra_bytes() {
                use las::point::Format;
                let format = Format { extra_bytes: 1, ..Default::default() };
                let header = Header { version: VERSION.into(), point_format: format, ..Default::default() };
                let point = Point { extra_bytes: vec![42], ..Default::default() };
                super::roundtrip(header, point);
            }
        }
    }
}

roundtrip!(las_1_0, 1, 0);
roundtrip!(las_1_1, 1, 1);
roundtrip!(las_1_2, 1, 2);
roundtrip!(las_1_3, 1, 3);
roundtrip!(las_1_4, 1, 4);
<commit_msg>Remove duplicate eof check<commit_after>//! Roundtrip (write-read) tests for supported LAS versions and attributes.

extern crate chrono;
extern crate las;

use las::{Header, Point, Reader, Writer};
use std::io::Cursor;

pub fn roundtrip(header: Header, point: Point) {
    let mut cursor = Cursor::new(Vec::new());
    {
        let mut writer = Writer::new(&mut cursor, header.clone()).unwrap();
        writer.write(point.clone()).unwrap();
    }
    cursor.set_position(0);
    let mut reader = Reader::new(cursor).unwrap();
    let other = reader.read().unwrap().unwrap();
    assert_eq!(point, other);
    assert_eq!(None, reader.read().unwrap());

    let other = reader.header;
    assert_eq!(header.guid, other.guid);
    assert_eq!(header.version, other.version);
    assert_eq!(header.transforms, other.transforms);
    assert_eq!(header.point_format, other.point_format);
    assert_eq!(1, other.number_of_points);
    assert_eq!(point.x, other.bounds.min.x);
    assert_eq!(point.x, other.bounds.max.x);
    assert_eq!(point.y, other.bounds.min.y);
    assert_eq!(point.y, other.bounds.max.y);
    assert_eq!(point.z, other.bounds.min.z);
    assert_eq!(point.z, other.bounds.max.z);
    if point.return_number > 0 {
        assert_eq!(1, other.number_of_points_by_return[&point.return_number]);
    }

    assert_eq!(header.vlrs, other.vlrs);
}

fn new_writer_fail(header: Header) {
    assert!(Writer::new(Cursor::new(Vec::new()), header).is_err());
}

macro_rules! roundtrip {
    ($name:ident, $major:expr, $minor:expr) => {
        mod $name {
            use chrono::{Utc, Duration};

            use las::{GpsTimeType, Color, Header, Point, Transform, Vector};
            use las::point::{ScanDirection, Classification};

            const VERSION: (u8, u8) = ($major, $minor);

            fn roundtrip(point: Point) {
                let header = Header { version: VERSION.into(), ..Default::default() };
                super::roundtrip(header, point);
            }

            fn roundtrip_with_format(point: Point, point_format: u8) {
                use las::point::Format;
                let header = Header {
                    version: VERSION.into(),
                    point_format: Format::new(point_format).unwrap(),
                    ..Default::default()
                };
                super::roundtrip(header, point);
            }

            #[test]
            fn xyz() {
                let point = Point {
                    x: 1.,
                    y: 2.,
                    z: 3.,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn intensity() {
                let point = Point {
                    intensity: 11,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn return_number() {
                let point = Point {
                    return_number: 1,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn number_of_returns() {
                let point = Point {
                    number_of_returns: 1,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn scan_direction_flag() {
                let point = Point {
                    scan_direction: ScanDirection::LeftToRight,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn is_edge_of_flight_line() {
                let point = Point {
                    is_edge_of_flight_line: true,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn classification() {
                let point = Point {
                    classification: Classification::Ground,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn scan_angle_rank() {
                let point = Point {
                    scan_angle: 2.,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn user_data() {
                let point = Point {
                    user_data: 1,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn point_source_id() {
                let point = Point {
                    point_source_id: 1,
                    ..Default::default()
                };
                roundtrip(point);
            }

            #[test]
            fn gps_time() {
                let point = Point {
                    gps_time: Some(1.),
                    ..Default::default()
                };
                roundtrip_with_format(point, 1);
            }

            #[test]
            fn transforms() {
                let point = Point {
                    x: 10.,
                    y: 20.,
                    z: 30.,
                    ..Default::default()
                };
                let transform = Transform { scale: 0.1, offset: -1. };
                let transforms = Vector {
                    x: transform,
                    y: transform,
                    z: transform,
                };
                let header = Header { version: VERSION.into(), transforms: transforms, ..Default::default() };
                super::roundtrip(header, point);
            }

            #[test]
            fn guid() {
                let header = Header { version: VERSION.into(), guid: [1; 16], ..Default::default() };
                super::roundtrip(header, Default::default());
            }

            #[test]
            fn system_identifier() {
                let header = Header { version: VERSION.into(), system_identifier: "Beer!".to_string(), ..Default::default() };
                super::roundtrip(header, Default::default());
            }

            #[test]
            fn generating_software() {
                let header = Header { version: VERSION.into(), generating_software: "Beer!".to_string(), ..Default::default() };
                super::roundtrip(header, Default::default());
            }

            #[test]
            fn date() {
                let header = Header { version: VERSION.into(), date: Some(Utc::today() - Duration::days(1)), ..Default::default() };
                super::roundtrip(header, Default::default());
            }

            #[test]
            fn padding() {
                let header = Header { version: VERSION.into(), padding: vec![1], ..Default::default() };
                super::roundtrip(header, Default::default());
            }

            #[test]
            fn vlr_padding() {
                let header = Header { version: VERSION.into(), vlr_padding: vec![0], ..Default::default() };
                super::roundtrip(header, Default::default());
            }

            #[test]
            fn vlrs() {
                let vlrs = vec![Default::default()];
                let header = Header { version: VERSION.into(), vlrs: vlrs, ..Default::default() };
                super::roundtrip(header, Default::default());
            }

            #[test]
            fn color() {
                use las::point::Format;
                let point = Point {
                    color: Some(Color { red: 1, green: 2, blue: 3}),
                    ..Default::default()
                };
                if VERSION == (1, 0) || VERSION == (1, 1) {
                    super::new_writer_fail(Header { version: VERSION.into(), point_format: Format::new(2).unwrap(), ..Default::default() });
                } else {
                    roundtrip_with_format(point, 2.into());
                }
            }

            #[test]
            fn file_source_id() {
                let header = Header { version: VERSION.into(), file_source_id: 1, ..Default::default() };
                if VERSION == (1, 0) {
                    super::new_writer_fail(header);
                } else {
                    super::roundtrip(header, Default::default());
                }
            }

            #[test]
            fn gps_time_type() {
                let header = Header { version: VERSION.into(), gps_time_type: GpsTimeType::Standard, ..Default::default() };
                if VERSION == (1, 0) || VERSION == (1, 1) {
                    super::new_writer_fail(header);
                } else {
                    super::roundtrip(header, Default::default());
                }
            }

            #[test]
            fn evlr() {
                use las::Vlr;
                use std::u16;
                let vlrs = vec![Vlr { is_extended: true, data: vec![42; u16::MAX as usize + 1], ..Default::default() }];
                let header = Header { version: VERSION.into(), vlrs: vlrs, ..Default::default() };
                if VERSION == (1, 4) {
                    super::roundtrip(header, Default::default());
                } else {
                    super::new_writer_fail(header);
                }
            }

            #[test]
            fn extra_bytes() {
                use las::point::Format;
                let format = Format { extra_bytes: 1, ..Default::default() };
                let header = Header { version: VERSION.into(), point_format: format, ..Default::default() };
                let point = Point { extra_bytes: vec![42], ..Default::default() };
                super::roundtrip(header, point);
            }
        }
    }
}

roundtrip!(las_1_0, 1, 0);
roundtrip!(las_1_1, 1, 1);
roundtrip!(las_1_2, 1, 2);
roundtrip!(las_1_3, 1, 3);
roundtrip!(las_1_4, 1, 4);
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate futures;
extern crate tokio_core as tokio;
extern crate tokio_service as service;
extern crate tokio_proto as proto;
extern crate tokio_timer;
extern crate env_logger;
extern crate vastatrix;

use std::net::SocketAddr;
use std::time::Duration;

use tokio::reactor::Core;
use futures::Future;
use vastatrix::LogPos;

use vastatrix::hosting::*;

#[test]
fn smoketest_single_node() {
    env_logger::init().unwrap_or(());

    let mut core = Core::new().unwrap();
    let timer = tokio_timer::wheel().tick_duration(Duration::from_millis(1)).build();
    let timeout = Duration::from_millis(1000);

    let local_anon_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();

    let server = build_server(
                                        &core.handle(),
                                        local_anon_addr.clone(),
                                        local_anon_addr.clone())
                     .expect("start server");
    println!("running: {:?}", server);

    info!("Head at: {:?}, tail at: {:?}",
          server.head,
          server.tail);
    let client = vastatrix::ThickClient::new(core.handle(),
                                             &server.head,
                                             &server.tail);

    let f = client.log_item(b"hello".to_vec())
                  .and_then(|pos0| {
                      client.log_item(b"world".to_vec()).map(move |pos1| (pos0, pos1))
                  });
    let (wpos0, wpos1) = core.run(timer.timeout(f, timeout)).expect("run write");

    info!("Wrote to offset:{:?}", (wpos0, wpos1));

    let item_f = client.fetch_next(LogPos::zero())
                       .and_then(|(pos0, val0)| {
                           client.fetch_next(pos0).map(move |second| vec![(pos0, val0), second])
                       });

    let read = core.run(timer.timeout(item_f, timeout)).expect("run read");
    info!("Got: {:?}", read);

    assert_eq!(read,
               vec![(wpos0, b"hello".to_vec()), (wpos1, b"world".to_vec())]);
}

#[test]
fn smoketest_two_member_chain() {
    env_logger::init().unwrap_or(());
    let timer = tokio_timer::wheel().tick_duration(Duration::from_millis(1)).build();
    let timeout = Duration::from_millis(1000);
    let mut core = Core::new().unwrap();

    let local_anon_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
    let mut head_addr = local_anon_addr.clone();
    let mut tail_addr = local_anon_addr.clone();

    head_addr.set_port(11000);
    tail_addr.set_port(11001);
    let server0 = build_server(
                      &core.handle(),
                      head_addr.clone(),
                      tail_addr.clone())
        .expect("start server");
    println!("running: {:?}", server0);

    head_addr.set_port(11010);
    tail_addr.set_port(11011);
    let server1 = build_server(
                      &core.handle(),
                      head_addr.clone(),
                      tail_addr.clone())
        .expect("start server");

    println!("running: {:?}", server1);

    let client = vastatrix::ThickClient::new(core.handle(), &server0.head, &server1.tail);

    let f = client.add_peer(server0.clone())
        .and_then(|_| client.add_peer(server1.clone()))
        .and_then(|_| client.log_item(b"hello".to_vec()))
        .and_then(|pos0| client.log_item(b"world".to_vec()).map(move |pos1| (pos0, pos1)));
    let (wpos0, wpos1) = core.run(timer.timeout(f, timeout)).expect("run write");

    info!("Wrote to offset:{:?}", (wpos0, wpos1));

    let item_f = client.fetch_next(LogPos::zero())
        .and_then(|(pos0, val0)| {
            client.fetch_next(pos0).map(move |second| vec![(pos0, val0), second])
        });

    let read = core.run(timer.timeout(item_f, timeout)).expect("run read");
    info!("Got: {:?}", read);

    assert_eq!(read,
               vec![(wpos0, b"hello".to_vec()), (wpos1, b"world".to_vec())]);
}

#[test]
#[ignore]
fn smoketest_three_member_chain() {
    env_logger::init().unwrap_or(());
    let timer = tokio_timer::wheel().tick_duration(Duration::from_millis(1)).build();
    let timeout = Duration::from_millis(1000);
    let mut core = Core::new().unwrap();

    let local_anon_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
    let mut head_addr = local_anon_addr.clone();
    let mut tail_addr = local_anon_addr.clone();

    head_addr.set_port(11000);
    tail_addr.set_port(11001);
    let server0 = build_server(
                      &core.handle(),
                      head_addr.clone(),
                      tail_addr.clone())
        .expect("start server");
    println!("running: {:?}", server0);

    head_addr.set_port(11010);
    tail_addr.set_port(11011);
    let server1 = build_server(
                      &core.handle(),
                      head_addr.clone(),
                      tail_addr.clone())
        .expect("start server");

    println!("running: {:?}", server1);

    head_addr.set_port(11020);
    tail_addr.set_port(11021);
    let server2 = build_server(
                      &core.handle(),
                      head_addr.clone(),
                      tail_addr.clone())
        .expect("start server");
    println!("running: {:?}", server2);

    let client = vastatrix::ThickClient::new(core.handle(), &server0.head, &server2.tail);

    let f = client.add_peer(server0.clone())
        .and_then(|_| client.add_peer(server1.clone()))
        .and_then(|_| client.log_item(b"hello".to_vec()))
        .and_then(|_| client.add_peer(server2.clone()))
        .and_then(|pos0| client.log_item(b"world".to_vec()).map(move |pos1| (pos0, pos1)));
    let (wpos0, wpos1) = core.run(timer.timeout(f, timeout)).expect("run write");

    info!("Wrote to offset:{:?}", (wpos0, wpos1));

    let item_f = client.fetch_next(LogPos::zero())
        .and_then(|(pos0, val0)| {
            client.fetch_next(pos0).map(move |second| vec![(pos0, val0), second])
        });

    let res = core.run(timer.timeout(item_f, timeout));
    let read = res.expect("run read");
    info!("Got: {:?}", read);

    assert_eq!(read,
               vec![(wpos0, b"hello".to_vec()), (wpos1, b"world".to_vec())]);
}
<commit_msg>Three member chains now work.<commit_after>#[macro_use]
extern crate log;
extern crate futures;
extern crate tokio_core as tokio;
extern crate tokio_service as service;
extern crate tokio_proto as proto;
extern crate tokio_timer;
extern crate env_logger;
extern crate vastatrix;

use std::net::SocketAddr;
use std::time::Duration;

use tokio::reactor::Core;
use futures::Future;
use vastatrix::LogPos;

use vastatrix::hosting::*;

#[test]
fn smoketest_single_node() {
    env_logger::init().unwrap_or(());

    let mut core = Core::new().unwrap();
    let timer = tokio_timer::wheel().tick_duration(Duration::from_millis(1)).build();
    let timeout = Duration::from_millis(1000);

    let local_anon_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();

    let server = build_server(
                                        &core.handle(),
                                        local_anon_addr.clone(),
                                        local_anon_addr.clone())
                     .expect("start server");
    println!("running: {:?}", server);

    info!("Head at: {:?}, tail at: {:?}",
          server.head,
          server.tail);
    let client = vastatrix::ThickClient::new(core.handle(),
                                             &server.head,
                                             &server.tail);

    let f = client.log_item(b"hello".to_vec())
                  .and_then(|pos0| {
                      client.log_item(b"world".to_vec()).map(move |pos1| (pos0, pos1))
                  });
    let (wpos0, wpos1) = core.run(timer.timeout(f, timeout)).expect("run write");

    info!("Wrote to offset:{:?}", (wpos0, wpos1));

    let item_f = client.fetch_next(LogPos::zero())
                       .and_then(|(pos0, val0)| {
                           client.fetch_next(pos0).map(move |second| vec![(pos0, val0), second])
                       });

    let read = core.run(timer.timeout(item_f, timeout)).expect("run read");
    info!("Got: {:?}", read);

    assert_eq!(read,
               vec![(wpos0, b"hello".to_vec()), (wpos1, b"world".to_vec())]);
}

#[test]
fn smoketest_two_member_chain() {
    env_logger::init().unwrap_or(());
    let timer = tokio_timer::wheel().tick_duration(Duration::from_millis(1)).build();
    let timeout = Duration::from_millis(1000);
    let mut core = Core::new().unwrap();

    let local_anon_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
    let mut head_addr = local_anon_addr.clone();
    let mut tail_addr = local_anon_addr.clone();

    head_addr.set_port(11000);
    tail_addr.set_port(11001);
    let server0 = build_server(
                      &core.handle(),
                      head_addr.clone(),
                      tail_addr.clone())
        .expect("start server");
    println!("running: {:?}", server0);

    head_addr.set_port(11010);
    tail_addr.set_port(11011);
    let server1 = build_server(
                      &core.handle(),
                      head_addr.clone(),
                      tail_addr.clone())
        .expect("start server");

    println!("running: {:?}", server1);

    let client = vastatrix::ThickClient::new(core.handle(), &server0.head, &server1.tail);

    let f = client.add_peer(server0.clone())
        .and_then(|_| client.add_peer(server1.clone()))
        .and_then(|_| client.log_item(b"hello".to_vec()))
        .and_then(|pos0| client.log_item(b"world".to_vec()).map(move |pos1| (pos0, pos1)));
    let (wpos0, wpos1) = core.run(timer.timeout(f, timeout)).expect("run write");

    info!("Wrote to offset:{:?}", (wpos0, wpos1));

    let item_f = client.fetch_next(LogPos::zero())
        .and_then(|(pos0, val0)| {
            client.fetch_next(pos0).map(move |second| vec![(pos0, val0), second])
        });

    let read = core.run(timer.timeout(item_f, timeout)).expect("run read");
    info!("Got: {:?}", read);

    assert_eq!(read,
               vec![(wpos0, b"hello".to_vec()), (wpos1, b"world".to_vec())]);
}

#[test]
fn smoketest_three_member_chain() {
    env_logger::init().unwrap_or(());
    let timer = tokio_timer::wheel().tick_duration(Duration::from_millis(1)).build();
    let timeout = Duration::from_millis(1000);
    let mut core = Core::new().unwrap();

    let local_anon_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
    let mut head_addr = local_anon_addr.clone();
    let mut tail_addr = local_anon_addr.clone();

    head_addr.set_port(11300);
    tail_addr.set_port(11301);
    let server0 = build_server(
                      &core.handle(),
                      head_addr.clone(),
                      tail_addr.clone())
        .expect("start server");
    println!("running: {:?}", server0);

    head_addr.set_port(11310);
    tail_addr.set_port(11311);
    let server1 = build_server(
                      &core.handle(),
                      head_addr.clone(),
                      tail_addr.clone())
        .expect("start server");

    println!("running: {:?}", server1);

    head_addr.set_port(11320);
    tail_addr.set_port(11321);
    let server2 = build_server(
                      &core.handle(),
                      head_addr.clone(),
                      tail_addr.clone())
        .expect("start server");
    println!("running: {:?}", server2);

    let client = vastatrix::ThickClient::new(core.handle(), &server0.head, &server2.tail);

    let f = client.add_peer(server0.clone())
        .and_then(|_| client.add_peer(server1.clone()))
        .and_then(|_| client.log_item(b"hello".to_vec()))
        .and_then(|pos0| client.add_peer(server2.clone()).map(move |_| pos0))
        .and_then(|pos0| client.log_item(b"world".to_vec()).map(move |pos1| (pos0, pos1)));
    let (wpos0, wpos1) = core.run(timer.timeout(f, timeout)).expect("run write");

    info!("Wrote to offset:{:?}", (wpos0, wpos1));

    let (pos0, val0) = core.run(timer.timeout(client.fetch_next(LogPos::zero()), timeout)).expect("fetch first");
    info!("Got: {:?}", (&pos0, &val0));
    let (pos1, val1) = core.run(timer.timeout(client.fetch_next(pos0), timeout)).expect("fetch second");
    info!("Got: {:?}", (&pos1, &val1));

    assert_eq!(vec![(pos0, &*String::from_utf8_lossy(&val0)), (wpos1, &*String::from_utf8_lossy(&val1))],
               vec![(wpos0, "hello"), (wpos1, "world")]);
}
<|endoftext|>


<commit_before>export prime, init, grow, get_at, iterable_prime, loopable_prime, factors, iterable_factors;

type prime = {
    mutable vec: [u64]
};

impl loopable_prime for prime {
    fn iterate(blk: fn(&&u64) -> bool) {
        let i = 0u;
        while blk(get_at_vec(self.vec, i)) {
            i += 1u;
        }
    }
}

fn init() -> prime {
    { mutable vec: [] }
}

fn grow(ps: prime, n: uint) {
    grow_vec(ps.vec, n);
}

fn get_at(&ps: prime, n: u64) -> u64 {
    ret get_at_vec(ps.vec, n);
}

fn grow_vec(&v: [u64], n: uint) {
    if n == 0u {
        ret;
    }
    let num = alt vec::last_opt(v) {
      none       { v = [2u64];  grow_vec(v, n - 1u); ret }
      some(2u64) { v += [3u64]; grow_vec(v, n - 1u); ret }
      some(x)    { x + 2u64 }
    };

    let i = 0u;
    while i < n {
        for p in v {
            if p * p > num {
                v += [num];
                i += 1u;
                break;
            }
            if num % p == 0u64 {
                break;
            }
        }
        num += 2u;
    }
}

fn get_at_vec(&v: [u64], n: u64) -> u64 {
    if vec::len(v) <= n {
        grow_vec(v, n - vec::len(v) + 1u);
    }
    ret v[n];
}

fn div_multi(&num: u64, f: u64) -> u64 {
    let exp = 0u64;
    while (num % f == 0u64) {
        exp += 1u64;
        num /= f;
    }
    ret exp;
}

fn factors(num: u64, &primes: prime, blk: fn((u64, i64))) {
    let itr = num;
    primes.iterate { |p|
        let exp = div_multi(itr, p);
        if exp > 0u64 {
            blk((p, exp as i64));
        }
        ret itr != 1u;
    };
}<commit_msg>Remove extra `export'<commit_after>export prime, init, grow, get_at, loopable_prime, factors;

type prime = {
    mutable vec: [u64]
};

impl loopable_prime for prime {
    fn iterate(blk: fn(&&u64) -> bool) {
        let i = 0u;
        while blk(get_at_vec(self.vec, i)) {
            i += 1u;
        }
    }
}

fn init() -> prime {
    { mutable vec: [] }
}

fn grow(ps: prime, n: uint) {
    grow_vec(ps.vec, n);
}

fn get_at(&ps: prime, n: u64) -> u64 {
    ret get_at_vec(ps.vec, n);
}

fn grow_vec(&v: [u64], n: uint) {
    if n == 0u {
        ret;
    }
    let num = alt vec::last_opt(v) {
      none       { v = [2u64];  grow_vec(v, n - 1u); ret }
      some(2u64) { v += [3u64]; grow_vec(v, n - 1u); ret }
      some(x)    { x + 2u64 }
    };

    let i = 0u;
    while i < n {
        for p in v {
            if p * p > num {
                v += [num];
                i += 1u;
                break;
            }
            if num % p == 0u64 {
                break;
            }
        }
        num += 2u;
    }
}

fn get_at_vec(&v: [u64], n: u64) -> u64 {
    if vec::len(v) <= n {
        grow_vec(v, n - vec::len(v) + 1u);
    }
    ret v[n];
}

fn div_multi(&num: u64, f: u64) -> u64 {
    let exp = 0u64;
    while (num % f == 0u64) {
        exp += 1u64;
        num /= f;
    }
    ret exp;
}

fn factors(num: u64, &primes: prime, blk: fn((u64, i64))) {
    let itr = num;
    primes.iterate { |p|
        let exp = div_multi(itr, p);
        if exp > 0u64 {
            blk((p, exp as i64));
        }
        ret itr != 1u;
    };
}<|endoftext|>


<commit_before>use crate::{
    ast, error::Result, DiagnosticError, ForeignEnumInfo, ForeignInterface, ForeignerClassInfo,
    ForeignerMethod, LanguageGenerator, MethodVariant, PythonConfig, RustType, SelfTypeVariant,
    TypeMap,
};
use heck::SnakeCase;
use proc_macro2::TokenStream;
use quote::quote;
use syn::parse_quote;
use syn::spanned::Spanned;
use syn::{Ident, Type};

fn method_name(method: &ForeignerMethod) -> Result<&syn::Ident> {
    Ok(&method
        .rust_id
        .segments
        .last()
        .ok_or_else(|| DiagnosticError::new(method.span(), "Method has no name"))?
        .value()
        .ident)
}

impl LanguageGenerator for PythonConfig {
    fn register_class(&self, _conv_map: &mut TypeMap, _class: &ForeignerClassInfo) -> Result<()> {
        Ok(())
    }

    fn generate(
        &self,
        conv_map: &mut TypeMap,
        _: usize,
        class: &ForeignerClassInfo,
    ) -> Result<Vec<TokenStream>> {
        let class_name = &class.name;
        let wrapper_mod_name =
            syn::parse_str::<Ident>(&py_wrapper_mod_name(&class_name.to_string()))?;
        self.module_initialization_code.borrow_mut().push(quote! {
            {
                m.add_class::<#wrapper_mod_name::#class_name>(py)?;
            }
        });
        let (rust_instance_field, rust_instance_getter) =
            generate_rust_instance_field_and_getter(class)?;
        let methods_code = class
            .methods
            .iter()
            .map(|m| generate_method_code(class, m, conv_map))
            .collect::<Result<Vec<_>>>()?;
        let class_code = quote! {
            mod #wrapper_mod_name {
                py_class!(pub class #class_name |py| {
                    #rust_instance_field

                    #( #methods_code )*
                });

                #rust_instance_getter
            }
        };
        Ok(vec![class_code])
    }

    fn generate_enum(
        &self,
        conv_map: &mut TypeMap,
        _pointer_target_width: usize,
        enum_info: &ForeignEnumInfo,
    ) -> Result<Vec<TokenStream>> {
        let enum_name = &enum_info.name;
        let wrapper_mod_name =
            syn::parse_str::<Ident>(&py_wrapper_mod_name(&enum_name.to_string()))?;
        self.module_initialization_code.borrow_mut().push(quote! {
            {
                m.add_class::<#wrapper_mod_name::#enum_name>(py)?;
            }

        });
        let foreign_variants = enum_info.items.iter().map(|item| &item.name);
        let rust_variants = enum_info.items.iter().map(|item| &item.rust_name);
        let class_code = quote! {
            mod #wrapper_mod_name {
                py_class!(pub class #enum_name |py| {
                    #( static #foreign_variants = super::#rust_variants as u32; )*
                });
            }
        };
        conv_map.register_exported_enum(enum_info);
        Ok(vec![class_code])
    }

    fn generate_interface(
        &self,
        _conv_map: &mut TypeMap,
        _pointer_target_width: usize,
        _interface: &ForeignInterface,
    ) -> Result<Vec<TokenStream>> {
        Ok(vec![])
    }

    fn finish_glue_rs(&self, _conv_map: &mut TypeMap) -> Result<Vec<TokenStream>> {
        let module_initialization_code_cell = self.module_initialization_code.borrow();
        let module_initialization_code = &*module_initialization_code_cell;
        let registration_code = vec![quote! {
            py_module_initializer!(librust_swig_test_python, initlibrust_swig_test_python, PyInit_rust_swig_test_python, |py, m| {
                m.add(py, "__doc__", "This is test module for rust_swig.")?;
                #(#module_initialization_code)*
                Ok(())
            });
        }];
        Ok(registration_code)
    }
}

fn generate_rust_instance_field_and_getter(
    class: &ForeignerClassInfo,
) -> Result<(TokenStream, TokenStream)> {
    if let Some(ref rust_self_type) = class.self_type {
        let self_type = &rust_self_type.ty;
        let class_name = &class.name;
        Ok((
            quote! {
                data rust_instance: std::sync::RwLock<super::#self_type>;
            },
            // For some reason, rust-cpython generates private `rust_instance` getter method.
            // As a workaround, we add public function in the same module, that gets `rust_instance`.
            quote! {
                pub fn rust_instance<'a>(class: &'a #class_name, py: cpython::Python<'a>) -> &'a std::sync::RwLock<super::#self_type> {
                    class.rust_instance(py)
                }
            },
        ))
    } else if !has_any_methods(class) {
        Ok((TokenStream::new(), TokenStream::new()))
    } else {
        Err(DiagnosticError::new(
            class.span(),
            format!(
                "Class {} has non-static methods, but no self_type",
                class.name
            ),
        ))
    }
}

fn generate_method_code(
    class: &ForeignerClassInfo,
    method: &ForeignerMethod,
    conv_map: &TypeMap,
) -> Result<TokenStream> {
    match method.variant {
        MethodVariant::Constructor => generate_constructor_code(class, conv_map),
        MethodVariant::Method(self_variant) => {
            generate_standard_method_code(class, method, self_variant, conv_map)
        }
        MethodVariant::StaticMethod => generate_static_method_code(method, conv_map),
    }
}

fn generate_constructor_code(
    class: &ForeignerClassInfo,
    conv_map: &TypeMap,
) -> Result<TokenStream> {
    if let Some(constructor) = class
        .methods
        .iter()
        .find(|m| m.variant == MethodVariant::Constructor)
    {
        let class_name = &class.name;
        let constructor_rust_path = &constructor.rust_id;
        Ok(quote! {
             def __new__(_cls) -> cpython::PyResult<#class_name> {
                let rust_instance = super::#constructor_rust_path();
                #class_name::create_instance(py, std::sync::RwLock::new(rust_instance))
            }
        })
    } else if !has_any_methods(class) {
        Ok(TokenStream::new())
    } else {
        Err(DiagnosticError::new(
            class.span(),
            format!(
                "Class {} has non-static methods, but no constructor",
                class.name
            ),
        ))
    }
}

fn generate_standard_method_code(
    class: &ForeignerClassInfo,
    method: &ForeignerMethod,
    self_variant: SelfTypeVariant,
    conv_map: &TypeMap,
) -> Result<TokenStream> {
    let method_name = method_name(method)?;
    let method_rust_path = &method.rust_id;
    let self_type = &class
        .self_type
        .as_ref()
        .ok_or_else(|| {
            DiagnosticError::new(
                class.span(),
                "Class have non-static methods, but no self_type",
            )
        })?
        .ty;
    let self_type_ref = match self_variant {
        SelfTypeVariant::Rptr => parse_type! {&#self_type},
        SelfTypeVariant::RptrMut => parse_type! {&mut #self_type},
        _ => unimplemented!("Passing self by value not implemented yet"),
    };
    let (_, self_convertion) =
        generate_conversion_for_argument(&self_type_ref.into(), conv_map, "self")?;
    let (args_types, mut args_convertions): (Vec<_>, Vec<_>) = method
        .fn_decl
        .inputs
        .iter()
        .skip(1) // Skip `self`, which is handled above.
        .enumerate()
        .map(|(i, a)| {
            let arg_name = format!("a_{}", i);
            generate_conversion_for_argument(
                &ast::fn_arg_type(a).clone().into(),
                conv_map,
                &arg_name,
            )
        })
        .collect::<Result<Vec<_>>>()?
        .into_iter()
        .unzip();
    args_convertions.insert(0, self_convertion);
    let args_names = (0..method.fn_decl.inputs.len() - 1)
        .map(|i| syn::parse_str(&format!("a_{}", i)))
        .collect::<std::result::Result<Vec<TokenStream>, _>>()?;
    let (return_type, return_conversion) = generate_conversion_for_return(
        &extract_return_type(&method.fn_decl.output),
        conv_map,
        "_ret",
    )?;
    Ok(quote! {
        def #method_name(
            &self
            #( ,#args_names: #args_types )*
        ) -> cpython::PyResult<#return_type> {
            let _ret = super::#method_rust_path(
                #( #args_convertions ),*
            );
            Ok(#return_conversion)
        }
    })
}

fn generate_static_method_code(
    method: &ForeignerMethod,
    conv_map: &TypeMap,
) -> Result<TokenStream> {
    let static_method_name = method_name(method)?;
    let static_method_rust_path = &method.rust_id;
    let (args_types, args_convertions): (Vec<_>, Vec<_>) = method
        .fn_decl
        .inputs
        .iter()
        .enumerate()
        .map(|(i, a)| {
            let arg_name = format!("a_{}", i);
            generate_conversion_for_argument(
                &ast::fn_arg_type(a).clone().into(),
                conv_map,
                &arg_name,
            )
        })
        .collect::<Result<Vec<_>>>()?
        .into_iter()
        .unzip();
    let args_names = (0..method.fn_decl.inputs.len())
        .map(|i| syn::parse_str(&format!("a_{}", i)))
        .collect::<std::result::Result<Vec<TokenStream>, _>>()?;
    let (return_type, return_conversion) = generate_conversion_for_return(
        &extract_return_type(&method.fn_decl.output),
        conv_map,
        "_ret",
    )?;
    Ok(quote! {
        @staticmethod def #static_method_name(
            #( #args_names: #args_types ),*
        ) -> cpython::PyResult<#return_type> {
            let _ret = super::#static_method_rust_path(
                #( #args_convertions ),*
            );
            Ok(#return_conversion)
        }
    })
}

fn has_any_methods(class: &ForeignerClassInfo) -> bool {
    class.methods.iter().any(|m| {
        if let MethodVariant::Method(_) = m.variant {
            true
        } else {
            false
        }
    })
}

fn generate_conversion_for_argument(
    rust_type: &RustType,
    conv_map: &TypeMap,
    arg_name: &str,
) -> Result<(Type, TokenStream)> {
    let arg_name_ident: TokenStream = syn::parse_str(arg_name)?;
    if is_cpython_supported_type(rust_type) {
        Ok((rust_type.ty.clone(), arg_name_ident))
    } else if let Some(foreign_class) =
        conv_map.find_foreigner_class_with_such_self_type(&rust_type.ty, true)
    {
        let class_name = foreign_class.name.to_string();
        let py_mod: Ident = syn::parse_str(&py_wrapper_mod_name(&class_name))?;
        let py_type: Type = syn::parse_str(&format!(
            "&super::{}::{}",
            py_wrapper_mod_name(&class_name),
            &class_name
        ))?;
        let self_conversion_code = if let Type::Reference(ref reference) = rust_type.ty {
            if reference.mutability.is_some() {
                quote! {
                    &mut *super::#py_mod::rust_instance(#arg_name_ident, py).write().unwrap()
                }
            } else {
                quote! {
                    &*super::#py_mod::rust_instance(#arg_name_ident, py).read().unwrap()
                }
            }
        } else {
            unimplemented!("Passing object by value not implemented yet")
        };
        Ok((py_type, self_conversion_code))
    } else {
        unimplemented!("other arg");
    }
}

fn generate_conversion_for_return(
    rust_type: &RustType,
    conv_map: &TypeMap,
    ret_name: &str,
) -> Result<(Type, TokenStream)> {
    if rust_type.normalized_name == "( )" {
        Ok((parse_type!(cpython::PyObject), quote!(py.None())))
    } else if is_cpython_supported_type(rust_type) {
        Ok((rust_type.ty.clone(), syn::parse_str(ret_name)?))
    } else if let Some(foreign_class) =
        conv_map.find_foreigner_class_with_such_this_type(&rust_type.ty)
    {
        unimplemented!();
    } else {
        unimplemented!();
    }
}

fn is_cpython_supported_type(rust_type: &RustType) -> bool {
    let primitive_types = [
        "bool", "i8", "i16", "i32", "i64", "isize", "u8", "u16", "u32", "u64", "usize", "f32",
        "f64", "String", "& str",
    ];
    primitive_types.contains(&rust_type.normalized_name.as_str())
}

fn extract_return_type(syn_return_type: &syn::ReturnType) -> RustType {
    match syn_return_type {
        syn::ReturnType::Default => {
            let mut ty: Type = parse_type! { () };
            ast::change_span(&mut ty, syn_return_type.span());
            ty.into()
        }
        syn::ReturnType::Type(_, ref ty) => {
            let ty: Type = *ty.clone();
            ty.into()
        }
    }
}

fn py_wrapper_mod_name(type_name: &str) -> String {
    format!("py_{}", type_name.to_snake_case())
}
<commit_msg>Uniform method generation<commit_after>use crate::{
    ast, error::Result, DiagnosticError, ForeignEnumInfo, ForeignInterface, ForeignerClassInfo,
    ForeignerMethod, LanguageGenerator, MethodVariant, PythonConfig, RustType, SelfTypeVariant,
    TypeMap,
};
use heck::SnakeCase;
use proc_macro2::{Span, TokenStream};
use quote::quote;
use quote::ToTokens;
use syn::parse_quote;
use syn::spanned::Spanned;

use syn::{Ident, Type};

impl LanguageGenerator for PythonConfig {
    fn register_class(&self, _conv_map: &mut TypeMap, _class: &ForeignerClassInfo) -> Result<()> {
        Ok(())
    }

    fn generate(
        &self,
        conv_map: &mut TypeMap,
        _: usize,
        class: &ForeignerClassInfo,
    ) -> Result<Vec<TokenStream>> {
        let class_name = &class.name;
        let wrapper_mod_name =
            syn::parse_str::<Ident>(&py_wrapper_mod_name(&class_name.to_string()))?;
        self.module_initialization_code.borrow_mut().push(quote! {
            {
                m.add_class::<#wrapper_mod_name::#class_name>(py)?;
            }
        });
        let (rust_instance_field, rust_instance_getter) =
            generate_rust_instance_field_and_methods(class)?;
        let methods_code = class
            .methods
            .iter()
            .map(|m| generate_method_code(class, m, conv_map))
            .collect::<Result<Vec<_>>>()?;
        let class_code = quote! {
            mod #wrapper_mod_name {
                py_class!(pub class #class_name |py| {
                    #rust_instance_field

                    #( #methods_code )*
                });

                #rust_instance_getter
            }
        };
        Ok(vec![class_code])
    }

    fn generate_enum(
        &self,
        conv_map: &mut TypeMap,
        _pointer_target_width: usize,
        enum_info: &ForeignEnumInfo,
    ) -> Result<Vec<TokenStream>> {
        let enum_name = &enum_info.name;
        let wrapper_mod_name =
            syn::parse_str::<Ident>(&py_wrapper_mod_name(&enum_name.to_string()))?;
        self.module_initialization_code.borrow_mut().push(quote! {
            {
                m.add_class::<#wrapper_mod_name::#enum_name>(py)?;
            }

        });
        let foreign_variants = enum_info.items.iter().map(|item| &item.name);
        let rust_variants = enum_info.items.iter().map(|item| &item.rust_name);
        let class_code = quote! {
            mod #wrapper_mod_name {
                py_class!(pub class #enum_name |py| {
                    #( static #foreign_variants = super::#rust_variants as u32; )*
                });
            }
        };
        conv_map.register_exported_enum(enum_info);
        Ok(vec![class_code])
    }

    fn generate_interface(
        &self,
        _conv_map: &mut TypeMap,
        _pointer_target_width: usize,
        _interface: &ForeignInterface,
    ) -> Result<Vec<TokenStream>> {
        Ok(vec![])
    }

    fn finish_glue_rs(&self, _conv_map: &mut TypeMap) -> Result<Vec<TokenStream>> {
        let module_initialization_code_cell = self.module_initialization_code.borrow();
        let module_initialization_code = &*module_initialization_code_cell;
        let registration_code = vec![quote! {
            py_module_initializer!(librust_swig_test_python, initlibrust_swig_test_python, PyInit_rust_swig_test_python, |py, m| {
                m.add(py, "__doc__", "This is test module for rust_swig.")?;
                #(#module_initialization_code)*
                Ok(())
            });
        }];
        Ok(registration_code)
    }
}

fn generate_rust_instance_field_and_methods(
    class: &ForeignerClassInfo,
) -> Result<(TokenStream, TokenStream)> {
    if let Some(ref rust_self_type) = class.self_type {
        let self_type = &rust_self_type.ty;
        let class_name = &class.name;
        Ok((
            quote! {
                data rust_instance: std::sync::RwLock<super::#self_type>;
            },
            // For some reason, rust-cpython generates private `rust_instance` getter method.
            // As a workaround, we add public function in the same module, that gets `rust_instance`.
            // The same goes for `create_instance
            quote! {
                pub fn rust_instance<'a>(class: &'a #class_name, py: cpython::Python<'a>) -> &'a std::sync::RwLock<super::#self_type> {
                    class.rust_instance(py)
                }

                pub fn create_instance(py: cpython::Python, instance: std::sync::RwLock<super::#self_type>) -> cpython::PyResult<#class_name> {
                    #class_name::create_instance(py, instance)
                }
            },
        ))
    } else if !has_any_methods(class) {
        Ok((TokenStream::new(), TokenStream::new()))
    } else {
        Err(DiagnosticError::new(
            class.span(),
            format!(
                "Class {} has non-static methods, but no self_type",
                class.name
            ),
        ))
    }
}

fn generate_method_code(
    class: &ForeignerClassInfo,
    method: &ForeignerMethod,
    conv_map: &TypeMap,
) -> Result<TokenStream> {
    if method.is_dummy_constructor() {
        return Ok(TokenStream::new());
    }
    let method_name = method_name(method)?;
    let method_rust_path = &method.rust_id;
    let skip_args_count = if let MethodVariant::Method(_) = method.variant {
        1
    } else {
        0
    };
    let (args_types, mut args_convertions): (Vec<_>, Vec<_>) = method
        .fn_decl
        .inputs
        .iter()
        .skip(skip_args_count)
        .enumerate()
        .map(|(i, a)| {
            let arg_name = format!("a_{}", i);
            generate_conversion_for_argument(
                &ast::fn_arg_type(a).clone().into(),
                conv_map,
                &arg_name,
            )
        })
        .collect::<Result<Vec<_>>>()?
        .into_iter()
        .unzip();
    if let Some(self_convertion) = self_type_conversion(class, method, conv_map)? {
        args_convertions.insert(0, self_convertion);
    }
    let mut args_list = args_types
        .into_iter()
        .enumerate()
        .map(|(i, t)| syn::parse_str(&format!("a_{}: {}", i, t.into_token_stream().to_string())))
        .collect::<std::result::Result<Vec<TokenStream>, _>>()?;
    if let MethodVariant::Method(_) = method.variant {
        args_list.insert(0, syn::parse_str("&self")?);
    } else if method.variant == MethodVariant::Constructor {
        args_list.insert(0, syn::parse_str("_cls")?);
    }
    let attribute = if method.variant == MethodVariant::StaticMethod {
        syn::parse_str("@staticmethod")?
    } else {
        TokenStream::new()
    };
    let (return_type, return_conversion) = generate_conversion_for_return(
        &extract_return_type(&method.fn_decl.output),
        method.span(),
        conv_map,
        "_ret",
    )?;
    Ok(quote! {
        #attribute def #method_name(
            #( #args_list ),*
        ) -> cpython::PyResult<#return_type> {
            let _ret = super::#method_rust_path(
                #( #args_convertions ),*
            );
            Ok(#return_conversion)
        }
    })
}

fn standard_method_name(method: &ForeignerMethod) -> Result<syn::Ident> {
    Ok(method
        .name_alias
        .as_ref()
        .or_else(|| method.rust_id.segments.last().map(|p| &p.value().ident))
        .ok_or_else(|| DiagnosticError::new(method.span(), "Method has no name"))?
        .clone())
}

fn method_name(method: &ForeignerMethod) -> Result<syn::Ident> {
    if method.variant == MethodVariant::Constructor {
        Ok(syn::parse_str("__new__")?)
    } else {
        standard_method_name(method)
    }
}

fn self_type_conversion(
    class: &ForeignerClassInfo,
    method: &ForeignerMethod,
    conv_map: &TypeMap,
) -> Result<Option<TokenStream>> {
    if let MethodVariant::Method(self_variant) = method.variant {
        let self_type = &class
            .self_type
            .as_ref()
            .ok_or_else(|| {
                DiagnosticError::new(
                    class.span(),
                    "Class have non-static methods, but no self_type",
                )
            })?
            .ty;
        let self_type_ref = match self_variant {
            SelfTypeVariant::Rptr => parse_type! {&#self_type},
            SelfTypeVariant::RptrMut => parse_type! {&mut #self_type},
            _ => unimplemented!("Passing self by value not implemented"),
        };
        Ok(Some(
            generate_conversion_for_argument(&self_type_ref.into(), conv_map, "self")?.1,
        ))
    } else {
        Ok(None)
    }
}

fn has_any_methods(class: &ForeignerClassInfo) -> bool {
    class.methods.iter().any(|m| {
        if let MethodVariant::Method(_) = m.variant {
            true
        } else {
            false
        }
    })
}

fn generate_conversion_for_argument(
    rust_type: &RustType,
    conv_map: &TypeMap,
    arg_name: &str,
) -> Result<(Type, TokenStream)> {
    let arg_name_ident: TokenStream = syn::parse_str(arg_name)?;
    if is_cpython_supported_type(rust_type) {
        Ok((rust_type.ty.clone(), arg_name_ident))
    } else if let Some(foreign_class) =
        conv_map.find_foreigner_class_with_such_self_type(&rust_type.ty, true)
    {
        let class_name = foreign_class.name.to_string();
        let py_mod_str = py_wrapper_mod_name(&class_name);
        let py_mod: Ident = syn::parse_str(&py_mod_str)?;
        let py_type: Type = syn::parse_str(&format!("&super::{}::{}", &py_mod_str, &class_name))?;
        let self_conversion_code = if let Type::Reference(ref reference) = rust_type.ty {
            if reference.mutability.is_some() {
                quote! {
                    &mut *super::#py_mod::rust_instance(#arg_name_ident, py).write().unwrap()
                }
            } else {
                quote! {
                    &*super::#py_mod::rust_instance(#arg_name_ident, py).read().unwrap()
                }
            }
        } else {
            unimplemented!("Passing object by value not implemented yet")
        };
        Ok((py_type, self_conversion_code))
    } else {
        unimplemented!("other arg");
    }
}

fn generate_conversion_for_return(
    rust_type: &RustType,
    method_span: Span,
    conv_map: &TypeMap,
    ret_name: &str,
) -> Result<(Type, TokenStream)> {
    let ret_name_ident: TokenStream = syn::parse_str(ret_name)?;
    if rust_type.normalized_name == "( )" {
        Ok((parse_type!(cpython::PyObject), quote!(py.None())))
    } else if is_cpython_supported_type(rust_type) {
        Ok((rust_type.ty.clone(), ret_name_ident))
    } else if let Some(class) = conv_map.find_foreigner_class_with_such_this_type(&rust_type.ty) {
        if let Type::Reference(_) = rust_type.ty {
            return Err(DiagnosticError::new(
                method_span,
                "Returning rust object into python by reference is not safe and not supported.",
            ));
        };
        let class_name = &class.name;
        let py_mod: Ident = syn::parse_str(&py_wrapper_mod_name(&class_name.to_string()))?;
        Ok((
            parse_type!(super::#py_mod::#class_name),
            quote! {
                super::#py_mod::#class_name::create_instance(py, std::sync::RwLock::new(#ret_name_ident))?
            },
        ))
    } else {
        unimplemented!();
    }
}

fn is_cpython_supported_type(rust_type: &RustType) -> bool {
    let primitive_types = [
        "bool", "i8", "i16", "i32", "i64", "isize", "u8", "u16", "u32", "u64", "usize", "f32",
        "f64", "String", "& str",
    ];
    primitive_types.contains(&rust_type.normalized_name.as_str())
}

fn extract_return_type(syn_return_type: &syn::ReturnType) -> RustType {
    match syn_return_type {
        syn::ReturnType::Default => {
            let mut ty: Type = parse_type! { () };
            ast::change_span(&mut ty, syn_return_type.span());
            ty.into()
        }
        syn::ReturnType::Type(_, ref ty) => {
            let ty: Type = *ty.clone();
            ty.into()
        }
    }
}

fn py_wrapper_mod_name(type_name: &str) -> String {
    format!("py_{}", type_name.to_snake_case())
}
<|endoftext|>


<commit_before>extern crate translator;

extern crate piston_window;
#[macro_use]
extern crate conrod;
extern crate find_folder;

use translator::Translator;

use piston_window::{PistonWindow, WindowSettings, EventLoop, Glyphs, UpdateEvent, G2d};
use conrod::{Theme, Canvas, TextBox, Widget, Sizeable, Positionable, Graphics};
use conrod::color::{self, Colorable};

type Backend = (<G2d<'static> as Graphics>::Texture, Glyphs);
type Ui = conrod::Ui<Backend>;

fn main() {
    let window: PistonWindow = WindowSettings::new("Hello Conrod", [800, 600])
                                   .exit_on_esc(true)
                                   .vsync(true)
                                   .build()
                                   .unwrap();

    let mut ui: Ui = {
        let assets_path = find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap();
        let font_path = assets_path.join("NotoSans-Regular.ttf");
        let theme = Theme::default();
        let glyph_cache = Glyphs::new(&font_path, window.factory.clone());
        Ui::new(glyph_cache.unwrap(), theme)
    };

    let mut original_text = "".to_owned();
    let mut translated_text = "".to_owned();

    let translator = Translator::new();

    window.set_ups(60);
    while let Some(event) = window.next() {
        ui.handle_event(&event);

        event.update(|_| {
            ui.set_widgets(|ui| {
                let background_color = color::rgb(0.2, 0.35, 0.45);

                // TODO: Use frame width for text boxes.
                Canvas::new()
                    .pad(30.)
                    .color(background_color)
                    .scroll_kids()
                    .set(CANVAS, &mut ui);

                TextBox::new(&mut original_text)
                    .font_size(20)
                    .w_h(420.0, 40.0)
                    .mid_left_of(CANVAS)
                    .color(background_color.invert())
                    .react(|_string: &mut String| {})
                    .set(INPUT_TEXT, &mut ui);

                TextBox::new(&mut translated_text)
                    .font_size(20)
                    .w_h(420.0, 40.0)
                    .down_from(INPUT_TEXT, 45.0)
                    .color(background_color.invert())
                    .react(|_string: &mut String| {})
                    .set(OUTPUT_TEXT, &mut ui);
            })
        });

        window.draw_2d(&event,
                       |context, graphic| ui.draw_if_changed(context, graphic));

        translated_text = translator.translate(&original_text);
    }
}

widget_ids! {
    CANVAS,
    INPUT_TEXT,
    OUTPUT_TEXT,
}
<commit_msg>Build fix<commit_after>extern crate translator;

extern crate piston_window;
#[macro_use]
extern crate conrod;
extern crate find_folder;

use translator::Translator;

use piston_window::{PistonWindow, WindowSettings, EventLoop, Glyphs, UpdateEvent, G2d};
use conrod::{Theme, Canvas, TextBox, Widget, Sizeable, Positionable, Graphics};
use conrod::color::{self, Colorable};

type Backend = (<G2d<'static> as Graphics>::Texture, Glyphs);
type Ui = conrod::Ui<Backend>;

fn main() {
    let mut window: PistonWindow = WindowSettings::new("Hello Conrod", [800, 600])
                                   .exit_on_esc(true)
                                   .vsync(true)
                                   .build()
                                   .unwrap();

    let mut ui = {
        let assets_path = find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap();
        let font_path = assets_path.join("NotoSans-Regular.ttf");
        let theme = Theme::default();
        let glyph_cache = Glyphs::new(&font_path, window.factory.clone());
        Ui::new(glyph_cache.unwrap(), theme)
    };

    let mut original_text = "".to_owned();
    let mut translated_text = "".to_owned();

    let translator = Translator::new();

    window.set_ups(60);
    while let Some(event) = window.next() {
        ui.handle_event(&event);

        event.update(|_| {
            ui.set_widgets(|mut ui| {
                let background_color = color::rgb(0.2, 0.35, 0.45);

                // TODO: Use frame width for text boxes.
                Canvas::new()
                    .pad(30.)
                    .color(background_color)
                    .scroll_kids()
                    .set(CANVAS, &mut ui);

                TextBox::new(&mut original_text)
                    .font_size(20)
                    .w_h(420.0, 40.0)
                    .mid_left_of(CANVAS)
                    .color(background_color.invert())
                    .react(|_string: &mut String| {})
                    .set(INPUT_TEXT, &mut ui);

                TextBox::new(&mut translated_text)
                    .font_size(20)
                    .w_h(420.0, 40.0)
                    .down_from(INPUT_TEXT, 45.0)
                    .color(background_color.invert())
                    .react(|_string: &mut String| {})
                    .set(OUTPUT_TEXT, &mut ui);
            })
        });

        window.draw_2d(&event,
                       |context, graphic| ui.draw_if_changed(context, graphic));

        translated_text = translator.translate(&original_text);
    }
}

widget_ids! {
    CANVAS,
    INPUT_TEXT,
    OUTPUT_TEXT,
}
<|endoftext|>


<commit_before>use std::mem;

use buffering::copy::{StreamReadBuffer,StreamWriteBuffer};
use libc;

use Nl;
use consts::{Af,Arphrd,AddrFamily,IfaF,Iff,Ntf,Nud,RtaType,RtmF,Rtn,Rtprot,RtScope,RtTable};
use err::{SerError,DeError};

/// Struct representing interface information messages
pub struct Ifinfomsg {
    /// Interface address family
    pub ifi_family: AddrFamily,
    /// Interface type
    pub ifi_type: Arphrd,
    /// Interface index
    pub ifi_index: libc::c_int,
    /// Interface flags
    pub ifi_flags: Vec<Iff>,
    ifi_change: libc::c_uint,
}

impl Ifinfomsg {
    /// Create a fully initialized interface info struct
    pub fn new(ifi_family: AddrFamily, ifi_type: Arphrd, ifi_index: libc::c_int, ifi_flags: Vec<Iff>) -> Self {
        Ifinfomsg { ifi_family, ifi_type, ifi_index, ifi_flags, ifi_change: 0xffffffff }
    }
}

impl Nl for Ifinfomsg {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.ifi_family.serialize(buf)?;
        self.ifi_type.serialize(buf)?;
        self.ifi_index.serialize(buf)?;
        self.ifi_flags.iter().fold(0, |acc: libc::c_uint, next| {
            let next_uint: libc::c_uint = next.into();
            acc | next_uint
        }).serialize(buf)?;
        self.ifi_change.serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(Ifinfomsg {
            ifi_family: AddrFamily::deserialize(buf)?,
            ifi_type: Arphrd::deserialize(buf)?,
            ifi_index: libc::c_int::deserialize(buf)?,
            ifi_flags: {
                let flags = libc::c_uint::deserialize(buf)?;
                let mut nl_flags = Vec::new();
                for i in 0..mem::size_of::<libc::c_int>() * 8 {
                    let bit = 1 << i;
                    if bit & flags == bit {
                        nl_flags.push(bit.into());
                    }
                }
                nl_flags
            },
            ifi_change: 0xffffffff,
        })
    }

    fn size(&self) -> usize {
        self.ifi_family.size() + self.ifi_type.size() + self.ifi_index.size() + mem::size_of::<libc::c_uint>()
    }
}

/// Struct representing interface address messages
pub struct Ifaddrmsg {
    /// Interface address family
    pub ifa_family: Af,
    /// Interface address prefix length
    pub ifa_prefixlen: libc::c_uchar,
    /// Interface address flags
    pub ifa_flags: Vec<IfaF>,
    /// Interface address scope
    pub ifa_scope: libc::c_uchar,
    /// Interface address index
    pub ifa_index: libc::c_int,
}

impl Nl for Ifaddrmsg {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.ifa_family.serialize(buf)?;
        self.ifa_prefixlen.serialize(buf)?;
        self.ifa_flags.iter().fold(0, |acc: libc::c_uchar, next| {
            let next_uint: u32 = next.into();
            acc | next_uint as libc::c_uchar
        }).serialize(buf)?;
        self.ifa_scope.serialize(buf)?;
        self.ifa_index.serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(Ifaddrmsg {
            ifa_family: Af::deserialize(buf)?,
            ifa_prefixlen: libc::c_uchar::deserialize(buf)?,
            ifa_flags: {
                let flags = libc::c_uchar::deserialize(buf)?;
                let mut nl_flags = Vec::new();
                for i in 0..mem::size_of::<libc::c_uchar>() * 8 {
                    let bit = 1 << i;
                    if bit & flags == bit {
                        nl_flags.push((bit as u32).into());
                    }
                }
                nl_flags
            },
            ifa_scope: libc::c_uchar::deserialize(buf)?,
            ifa_index: libc::c_int::deserialize(buf)?,
        })
    }

    fn size(&self) -> usize {
        self.ifa_family.size() + self.ifa_prefixlen.size() + mem::size_of::<libc::c_uchar>()
            + self.ifa_scope.size() + self.ifa_index.size()
    }
}

/// Route message
pub struct Rtmsg {
    /// Address family of route
    pub rtm_family: libc::c_uchar,
    /// Length of destination
    pub rtm_dst_len: libc::c_uchar,
    /// Length of source
    pub rtm_src_len: libc::c_uchar,
    /// TOS filter
    pub rtm_tos: libc::c_uchar,
    /// Routing table ID
    pub rtm_table: RtTable,
    /// Routing protocol
    pub rtm_protocol: Rtprot,
    /// Routing scope
    pub rtm_scope: RtScope,
    /// Routing type
    pub rtm_type: Rtn,
    /// Routing flags
    pub rtm_flags: Vec<RtmF>,
}

impl Nl for Rtmsg {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.rtm_family.serialize(buf)?;
        self.rtm_dst_len.serialize(buf)?;
        self.rtm_src_len.serialize(buf)?;
        self.rtm_tos.serialize(buf)?;
        self.rtm_table.serialize(buf)?;
        self.rtm_protocol.serialize(buf)?;
        self.rtm_scope.serialize(buf)?;
        self.rtm_type.serialize(buf)?;
        self.rtm_flags.iter().fold(0, |acc: libc::c_uint, next| {
            let next_uint: libc::c_uint = next.into();
            acc | next_uint
        }).serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(Rtmsg {
            rtm_family: libc::c_uchar::deserialize(buf)?,
            rtm_dst_len: libc::c_uchar::deserialize(buf)?,
            rtm_src_len: libc::c_uchar::deserialize(buf)?,
            rtm_tos: libc::c_uchar::deserialize(buf)?,
            rtm_table: RtTable::deserialize(buf)?,
            rtm_protocol: Rtprot::deserialize(buf)?,
            rtm_scope: RtScope::deserialize(buf)?,
            rtm_type: Rtn::deserialize(buf)?,
            rtm_flags: {
                let flags = libc::c_int::deserialize(buf)?;
                let mut rtm_flags = Vec::new();
                for i in 0..mem::size_of::<libc::c_uint>() * 8 {
                    let bit = 1 << i;
                    if bit & flags == bit {
                        rtm_flags.push((bit as libc::c_uint).into());
                    }
                }
                rtm_flags
            },
        })
    }

    fn size(&self) -> usize {
        self.rtm_family.size() + self.rtm_dst_len.size() + self.rtm_src_len.size()
            + self.rtm_tos.size() + self.rtm_table.size() + self.rtm_protocol.size()
            + self.rtm_scope.size() + self.rtm_type.size() + mem::size_of::<libc::c_uint>()
    }
}

/// Represents an ARP (neighbor table) entry
pub struct Ndmsg {
    /// Address family of entry
    pub ndm_family: Af,
    /// Index of entry
    pub ndm_index: libc::c_int,
    /// State of entry
    pub ndm_state: Vec<Nud>,
    /// Flags for entry
    pub ndm_flags: Vec<Ntf>,
    /// Type of entry
    pub ndm_type: Rtn,
}

/// Struct representing route netlink attributes
pub struct RtAttr<T> {
    /// Length of the attribute
    pub rta_len: libc::c_ushort,
    /// Type of the attribute
    pub rta_type: T,
}

impl<T> Nl for RtAttr<T> where T: RtaType {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.rta_len.serialize(buf)?;
        self.rta_type.serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(RtAttr {
            rta_len: libc::c_ushort::deserialize(buf)?,
            rta_type: T::deserialize(buf)?,
        })
    }

    fn size(&self) -> usize {
        self.rta_len.size() + self.rta_type.size()
    }
}
<commit_msg>New NdaCacheinfo struct<commit_after>use std::mem;

use buffering::copy::{StreamReadBuffer,StreamWriteBuffer};
use libc;

use Nl;
use consts::{Af,Arphrd,AddrFamily,IfaF,Iff,Ntf,Nud,RtaType,RtmF,Rtn,Rtprot,RtScope,RtTable};
use err::{SerError,DeError};

/// Struct representing interface information messages
pub struct Ifinfomsg {
    /// Interface address family
    pub ifi_family: AddrFamily,
    /// Interface type
    pub ifi_type: Arphrd,
    /// Interface index
    pub ifi_index: libc::c_int,
    /// Interface flags
    pub ifi_flags: Vec<Iff>,
    ifi_change: libc::c_uint,
}

impl Ifinfomsg {
    /// Create a fully initialized interface info struct
    pub fn new(ifi_family: AddrFamily, ifi_type: Arphrd, ifi_index: libc::c_int, ifi_flags: Vec<Iff>) -> Self {
        Ifinfomsg { ifi_family, ifi_type, ifi_index, ifi_flags, ifi_change: 0xffffffff }
    }
}

impl Nl for Ifinfomsg {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.ifi_family.serialize(buf)?;
        self.ifi_type.serialize(buf)?;
        self.ifi_index.serialize(buf)?;
        self.ifi_flags.iter().fold(0, |acc: libc::c_uint, next| {
            let next_uint: libc::c_uint = next.into();
            acc | next_uint
        }).serialize(buf)?;
        self.ifi_change.serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(Ifinfomsg {
            ifi_family: AddrFamily::deserialize(buf)?,
            ifi_type: Arphrd::deserialize(buf)?,
            ifi_index: libc::c_int::deserialize(buf)?,
            ifi_flags: {
                let flags = libc::c_uint::deserialize(buf)?;
                let mut nl_flags = Vec::new();
                for i in 0..mem::size_of::<libc::c_int>() * 8 {
                    let bit = 1 << i;
                    if bit & flags == bit {
                        nl_flags.push(bit.into());
                    }
                }
                nl_flags
            },
            ifi_change: 0xffffffff,
        })
    }

    fn size(&self) -> usize {
        self.ifi_family.size() + self.ifi_type.size() + self.ifi_index.size() + mem::size_of::<libc::c_uint>()
    }
}

/// Struct representing interface address messages
pub struct Ifaddrmsg {
    /// Interface address family
    pub ifa_family: Af,
    /// Interface address prefix length
    pub ifa_prefixlen: libc::c_uchar,
    /// Interface address flags
    pub ifa_flags: Vec<IfaF>,
    /// Interface address scope
    pub ifa_scope: libc::c_uchar,
    /// Interface address index
    pub ifa_index: libc::c_int,
}

impl Nl for Ifaddrmsg {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.ifa_family.serialize(buf)?;
        self.ifa_prefixlen.serialize(buf)?;
        self.ifa_flags.iter().fold(0, |acc: libc::c_uchar, next| {
            let next_uint: u32 = next.into();
            acc | next_uint as libc::c_uchar
        }).serialize(buf)?;
        self.ifa_scope.serialize(buf)?;
        self.ifa_index.serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(Ifaddrmsg {
            ifa_family: Af::deserialize(buf)?,
            ifa_prefixlen: libc::c_uchar::deserialize(buf)?,
            ifa_flags: {
                let flags = libc::c_uchar::deserialize(buf)?;
                let mut nl_flags = Vec::new();
                for i in 0..mem::size_of::<libc::c_uchar>() * 8 {
                    let bit = 1 << i;
                    if bit & flags == bit {
                        nl_flags.push((bit as u32).into());
                    }
                }
                nl_flags
            },
            ifa_scope: libc::c_uchar::deserialize(buf)?,
            ifa_index: libc::c_int::deserialize(buf)?,
        })
    }

    fn size(&self) -> usize {
        self.ifa_family.size() + self.ifa_prefixlen.size() + mem::size_of::<libc::c_uchar>()
            + self.ifa_scope.size() + self.ifa_index.size()
    }
}

/// Route message
pub struct Rtmsg {
    /// Address family of route
    pub rtm_family: libc::c_uchar,
    /// Length of destination
    pub rtm_dst_len: libc::c_uchar,
    /// Length of source
    pub rtm_src_len: libc::c_uchar,
    /// TOS filter
    pub rtm_tos: libc::c_uchar,
    /// Routing table ID
    pub rtm_table: RtTable,
    /// Routing protocol
    pub rtm_protocol: Rtprot,
    /// Routing scope
    pub rtm_scope: RtScope,
    /// Routing type
    pub rtm_type: Rtn,
    /// Routing flags
    pub rtm_flags: Vec<RtmF>,
}

impl Nl for Rtmsg {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.rtm_family.serialize(buf)?;
        self.rtm_dst_len.serialize(buf)?;
        self.rtm_src_len.serialize(buf)?;
        self.rtm_tos.serialize(buf)?;
        self.rtm_table.serialize(buf)?;
        self.rtm_protocol.serialize(buf)?;
        self.rtm_scope.serialize(buf)?;
        self.rtm_type.serialize(buf)?;
        self.rtm_flags.iter().fold(0, |acc: libc::c_uint, next| {
            let next_uint: libc::c_uint = next.into();
            acc | next_uint
        }).serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(Rtmsg {
            rtm_family: libc::c_uchar::deserialize(buf)?,
            rtm_dst_len: libc::c_uchar::deserialize(buf)?,
            rtm_src_len: libc::c_uchar::deserialize(buf)?,
            rtm_tos: libc::c_uchar::deserialize(buf)?,
            rtm_table: RtTable::deserialize(buf)?,
            rtm_protocol: Rtprot::deserialize(buf)?,
            rtm_scope: RtScope::deserialize(buf)?,
            rtm_type: Rtn::deserialize(buf)?,
            rtm_flags: {
                let flags = libc::c_int::deserialize(buf)?;
                let mut rtm_flags = Vec::new();
                for i in 0..mem::size_of::<libc::c_uint>() * 8 {
                    let bit = 1 << i;
                    if bit & flags == bit {
                        rtm_flags.push((bit as libc::c_uint).into());
                    }
                }
                rtm_flags
            },
        })
    }

    fn size(&self) -> usize {
        self.rtm_family.size() + self.rtm_dst_len.size() + self.rtm_src_len.size()
            + self.rtm_tos.size() + self.rtm_table.size() + self.rtm_protocol.size()
            + self.rtm_scope.size() + self.rtm_type.size() + mem::size_of::<libc::c_uint>()
    }
}

/// Represents an ARP (neighbor table) entry
pub struct Ndmsg {
    /// Address family of entry
    pub ndm_family: Af,
    /// Index of entry
    pub ndm_index: libc::c_int,
    /// State of entry
    pub ndm_state: Vec<Nud>,
    /// Flags for entry
    pub ndm_flags: Vec<Ntf>,
    /// Type of entry
    pub ndm_type: Rtn,
}

/// Struct representing ARP cache info
pub struct NdaCacheinfo {
    /// Confirmed
    pub ndm_confirmed: u32,
    /// Used
    pub ndm_used: u32,
    /// Updated
    pub ndm_updated: u32,
    /// Reference count
    pub ndm_refcnt: u32,
}

/// Struct representing route netlink attributes
pub struct RtAttr<T> {
    /// Length of the attribute
    pub rta_len: libc::c_ushort,
    /// Type of the attribute
    pub rta_type: T,
}

impl<T> Nl for RtAttr<T> where T: RtaType {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.rta_len.serialize(buf)?;
        self.rta_type.serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(RtAttr {
            rta_len: libc::c_ushort::deserialize(buf)?,
            rta_type: T::deserialize(buf)?,
        })
    }

    fn size(&self) -> usize {
        self.rta_len.size() + self.rta_type.size()
    }
}
<|endoftext|>


<commit_before>#![feature(rustc_private)]

extern crate aster;
extern crate syntax;

use syntax::ast;
use syntax::codemap::{DUMMY_SP, respan};
use syntax::print::pprust;
use syntax::ptr::P;

use aster::AstBuilder;

#[test]
fn test_let() {
    let builder = AstBuilder::new();

    assert_eq!(
        builder.stmt()
            .let_().id("x").build(),
        P(respan(
            DUMMY_SP,
            ast::StmtDecl(
                P(respan(
                    DUMMY_SP,
                    ast::DeclLocal(P(ast::Local {
                        pat: builder.pat().id("x"),
                        ty: None,
                        init: None,
                        id: ast::DUMMY_NODE_ID,
                        span: DUMMY_SP,
                        source: ast::LocalLet,
                    })),
                )),
                ast::DUMMY_NODE_ID,
            ),
        ))
    );

    assert_eq!(
        builder.stmt()
            .let_().id("x").ty().i8().build(),
        P(respan(
            DUMMY_SP,
            ast::StmtDecl(
                P(respan(
                    DUMMY_SP,
                    ast::DeclLocal(P(ast::Local {
                        pat: builder.pat().id("x"),
                        ty: Some(builder.ty().i8()),
                        init: None,
                        id: ast::DUMMY_NODE_ID,
                        span: DUMMY_SP,
                        source: ast::LocalLet,
                    })),
                )),
                ast::DUMMY_NODE_ID,
            ),
        ))
    );

    assert_eq!(
        builder.stmt()
            .let_().id("x").expr().i8(5),
        P(respan(
            DUMMY_SP,
            ast::StmtDecl(
                P(respan(
                    DUMMY_SP,
                    ast::DeclLocal(P(ast::Local {
                        pat: builder.pat().id("x"),
                        ty: None,
                        init: Some(builder.expr().i8(5)),
                        id: ast::DUMMY_NODE_ID,
                        span: DUMMY_SP,
                        source: ast::LocalLet,
                    })),
                )),
                ast::DUMMY_NODE_ID,
            ),
        ))
    );

    assert_eq!(
        builder.stmt()
            .let_().id("x").ty().i8().expr().i8(5),
        P(respan(
            DUMMY_SP,
            ast::StmtDecl(
                P(respan(
                    DUMMY_SP,
                    ast::DeclLocal(P(ast::Local {
                        pat: builder.pat().id("x"),
                        ty: Some(builder.ty().i8()),
                        init: Some(builder.expr().i8(5)),
                        id: ast::DUMMY_NODE_ID,
                        span: DUMMY_SP,
                        source: ast::LocalLet,
                    })),
                )),
                ast::DUMMY_NODE_ID,
            ),
        ))
    );

    assert_eq!(
        builder.stmt().let_()
            .tuple()
                .pat().id("x")
                .pat().id("y")
                .build()
            .expr().tuple()
                .expr().u8(0)
                .expr().u16(1)
                .build(),
        P(respan(
            DUMMY_SP,
            ast::StmtDecl(
                P(respan(
                    DUMMY_SP,
                    ast::DeclLocal(P(ast::Local {
                        pat: builder.pat().tuple()
                            .pat().id("x")
                            .pat().id("y")
                            .build(),
                        ty: None,
                        init: Some(
                            builder.expr().tuple()
                                .expr().u8(0)
                                .expr().u16(1)
                                .build()
                        ),
                        id: ast::DUMMY_NODE_ID,
                        span: DUMMY_SP,
                        source: ast::LocalLet,
                    })),
                )),
                ast::DUMMY_NODE_ID,
            ),
        ))
    );
}
<commit_msg>Fix a warning<commit_after>#![feature(rustc_private)]

extern crate aster;
extern crate syntax;

use syntax::ast;
use syntax::codemap::{DUMMY_SP, respan};
use syntax::ptr::P;

use aster::AstBuilder;

#[test]
fn test_let() {
    let builder = AstBuilder::new();

    assert_eq!(
        builder.stmt()
            .let_().id("x").build(),
        P(respan(
            DUMMY_SP,
            ast::StmtDecl(
                P(respan(
                    DUMMY_SP,
                    ast::DeclLocal(P(ast::Local {
                        pat: builder.pat().id("x"),
                        ty: None,
                        init: None,
                        id: ast::DUMMY_NODE_ID,
                        span: DUMMY_SP,
                        source: ast::LocalLet,
                    })),
                )),
                ast::DUMMY_NODE_ID,
            ),
        ))
    );

    assert_eq!(
        builder.stmt()
            .let_().id("x").ty().i8().build(),
        P(respan(
            DUMMY_SP,
            ast::StmtDecl(
                P(respan(
                    DUMMY_SP,
                    ast::DeclLocal(P(ast::Local {
                        pat: builder.pat().id("x"),
                        ty: Some(builder.ty().i8()),
                        init: None,
                        id: ast::DUMMY_NODE_ID,
                        span: DUMMY_SP,
                        source: ast::LocalLet,
                    })),
                )),
                ast::DUMMY_NODE_ID,
            ),
        ))
    );

    assert_eq!(
        builder.stmt()
            .let_().id("x").expr().i8(5),
        P(respan(
            DUMMY_SP,
            ast::StmtDecl(
                P(respan(
                    DUMMY_SP,
                    ast::DeclLocal(P(ast::Local {
                        pat: builder.pat().id("x"),
                        ty: None,
                        init: Some(builder.expr().i8(5)),
                        id: ast::DUMMY_NODE_ID,
                        span: DUMMY_SP,
                        source: ast::LocalLet,
                    })),
                )),
                ast::DUMMY_NODE_ID,
            ),
        ))
    );

    assert_eq!(
        builder.stmt()
            .let_().id("x").ty().i8().expr().i8(5),
        P(respan(
            DUMMY_SP,
            ast::StmtDecl(
                P(respan(
                    DUMMY_SP,
                    ast::DeclLocal(P(ast::Local {
                        pat: builder.pat().id("x"),
                        ty: Some(builder.ty().i8()),
                        init: Some(builder.expr().i8(5)),
                        id: ast::DUMMY_NODE_ID,
                        span: DUMMY_SP,
                        source: ast::LocalLet,
                    })),
                )),
                ast::DUMMY_NODE_ID,
            ),
        ))
    );

    assert_eq!(
        builder.stmt().let_()
            .tuple()
                .pat().id("x")
                .pat().id("y")
                .build()
            .expr().tuple()
                .expr().u8(0)
                .expr().u16(1)
                .build(),
        P(respan(
            DUMMY_SP,
            ast::StmtDecl(
                P(respan(
                    DUMMY_SP,
                    ast::DeclLocal(P(ast::Local {
                        pat: builder.pat().tuple()
                            .pat().id("x")
                            .pat().id("y")
                            .build(),
                        ty: None,
                        init: Some(
                            builder.expr().tuple()
                                .expr().u8(0)
                                .expr().u16(1)
                                .build()
                        ),
                        id: ast::DUMMY_NODE_ID,
                        span: DUMMY_SP,
                        source: ast::LocalLet,
                    })),
                )),
                ast::DUMMY_NODE_ID,
            ),
        ))
    );
}
<|endoftext|>


<commit_before>extern mod linenoise;

mod rush {
    extern mod linenoise;
    extern mod core;
    use core::task::spawn;
    use core::run;

    pub fn exec_command(stdin_fd: libc::c_int, command: &~str) -> libc::c_int {
        let pipe_out = os::pipe();
        let pipe_err = os::pipe();
        let com = copy *command;
        do spawn{
            let command_split = str::split_char(com, ' ');
            let prog = command_split.head();
            let args = command_split.tail();
            let pid = run::spawn_process(
                    *prog, args, &None, &None,
                    stdin_fd, pipe_out.out, pipe_err.out);
            os::close(pipe_out.out);
            os::close(pipe_err.out);
            let status = run::waitpid(pid);
        }
        pipe_out.in
    }

    pub fn handle_input(line: &str) {
        linenoise::history_add(line);
        linenoise::history_save("history.txt");
        let commands = vec::map(str::split_char(line, '|'), |command| str::trim(*command));
        let pipe_in = os::pipe();
        let std_out = vec::foldl(pipe_in.in, commands, exec_command);
        os::close(pipe_in.out);
        let (stdout_po, stdout_ch) = comm::stream();
        do task::spawn_sched(task::SingleThreaded) || {
            stdout_ch.send(core::run::readclose(std_out));
        }
        let stdout = stdout_po.recv();
        io::print(stdout);
    }

}

fn main() {
    linenoise::set_multiline(true);
    loop {
        let line = linenoise::init("rush: ");
        rush::handle_input(line);
    }
}
<commit_msg>Updated for rust 0.6<commit_after>extern mod linenoise;

mod rush {
    extern mod linenoise;
    extern mod core;
    use core::run;

    pub fn exec_command(stdin_fd: libc::c_int, command: &str) -> libc::c_int {
        let pipe_out = os::pipe();
        let pipe_err = os::pipe();
        let mut args: ~[~str] = ~[];
        let mut prog = ~"";
        let mut first = true;
        str::each_split_char(command, ' ', |item| {
            if (first) {
                prog = copy item.to_owned();
                first = false;
            } else {
                args.push(item.to_owned());
            }
            true
        });
        let pid = run::spawn_process(
                prog, args, &None, &None,
                stdin_fd, pipe_out.out, pipe_err.out);
        os::close(pipe_out.out);
        os::close(pipe_err.out);
        do task::spawn_sched(task::SingleThreaded) || {
            run::waitpid(pid);
        }
        pipe_out.in
    }

    pub fn handle_input(line: &str) {
        linenoise::history_add(line);
        linenoise::history_save("history.txt");
        let mut commands: ~[&str] = ~[];
        str::each_split_char_no_trailing(line, '|', |command| { commands.push(str::trim(command)); true });
        let pipe_in = os::pipe();
        let std_out = vec::foldl(pipe_in.in, commands, |stdin, command| {
            exec_command(stdin, *command)
        });
        os::close(pipe_in.out);
        do task::spawn_sched(task::SingleThreaded) || {
            io::print(core::run::readclose(std_out));
        }
    }

}

fn main() {
    linenoise::set_multiline(true);
    loop {
        let line = linenoise::init("rush: ");
        rush::handle_input(line);
    }
}
<|endoftext|>


<commit_before>s_no_extra_traits! {
    #[allow(missing_debug_implementations)]
    #[repr(align(16))]
    pub struct max_align_t {
        priv_: [f32; 8]
    }
}

s!{
    pub struct ucontext_t {
        pub uc_flags: ::c_ulong,
        pub uc_link: *mut ucontext_t,
        pub uc_stack: ::stack_t,
        pub uc_sigmask: ::sigset_t,
        pub uc_mcontext: mcontext_t,
    }

    #[repr(align(16))]
    pub struct mcontext_t {
        // What we want here is a single [u64; 36 + 512], but splitting things
        // up allows Debug to be auto-derived.
        __regs1: [[u64; 18]; 2], // 36
        __regs2: [[u64; 32]; 16], // 512
    }
}
<commit_msg>Populate mcontext_t on aarch64-linux-musl<commit_after>s_no_extra_traits! {
    #[allow(missing_debug_implementations)]
    #[repr(align(16))]
    pub struct max_align_t {
        priv_: [f32; 8]
    }
}

s! {
    pub struct ucontext_t {
        pub uc_flags: ::c_ulong,
        pub uc_link: *mut ucontext_t,
        pub uc_stack: ::stack_t,
        pub uc_sigmask: ::sigset_t,
        pub uc_mcontext: mcontext_t,
    }

    #[repr(align(16))]
    pub struct mcontext_t {
        pub fault_address: ::c_ulong,
        pub regs: [::c_ulong; 31],
        pub sp: ::c_ulong,
        pub pc: ::c_ulong,
        pub pstate: ::c_ulong,
        __reserved: [[u64; 32]; 16],
    }
}
<|endoftext|>