<commit_before>//extern crate core;
use core::prelude::*;
use core::mem;

use std::sync::{Once, ONCE_INIT, spsc_queue};

use collections::vec::Vec;
use collections::SmallIntMap;
use collections::MutableMap;
use collections::MutableSeq;
use collections::Mutable;
use collections::Map;

use log::logi;
use motionevent::append_motion_event;
use android::input::AInputEvent;

use opengles::gl2::*;

use pointshader::{PointShader};
use glcommon::check_gl_error;
use gltexture::Texture;
use point;
use point::{ShaderPaintPoint, Coordinate, PointEntry, PointConsumer, PointProducer};
use rollingaverage::RollingAverage;
use dropfree::DropFree;
use matrix::Matrix;
use luascript::LuaScript;

/// lifetime storage for a pointer's past state
struct PointStorage {
    info: Option<ShaderPaintPoint>,
    sizeavg: RollingAverage<f32>,
    speedavg: RollingAverage<f32>,
}

pub struct RustStatics {
    consumer: PointConsumer,
    producer: PointProducer,
    currentPoints: SmallIntMap<PointStorage>,
    drawvec: Vec<ShaderPaintPoint>,
    pointCounter: i32,
}

static mut dataRef: DropFree<RustStatics> = DropFree(0 as *mut RustStatics);
static mut pathinit: Once = ONCE_INIT;

fn do_path_init() -> () {
    unsafe {
        pathinit.doit(|| {
            let (consumer, producer) = spsc_queue::queue::<PointEntry>(0);
            dataRef = DropFree::new(RustStatics {
                consumer: consumer,
                producer: producer,
                currentPoints: SmallIntMap::new(),
                drawvec: Vec::new(),
                pointCounter: 0,
            });
            logi("created statics");
        });
    }
}

fn get_statics<'a>() -> &'a mut RustStatics {
    do_path_init();
    unsafe { dataRef.get_mut() }
}

#[no_mangle]
//FIXME: needs meaningful name
pub extern fn jni_append_motion_event(evt: *const AInputEvent) {
    let s = get_statics();
    append_motion_event(evt, &mut s.producer);
}

fn manhattan_distance(a: Coordinate, b: Coordinate) -> f32 {
    let x = if a.x > b.x { a.x - b.x } else { b.x - a.x };
    let y = if a.y > b.y { a.y - b.y } else { b.y - a.y };
    return if x > y { x } else { y };
}

#[allow(dead_code)]
fn append_points(a: ShaderPaintPoint, b: ShaderPaintPoint, c: &mut Vec<ShaderPaintPoint>, count: uint) -> () {
    // transform seconds from [0..timescale] to [0..1]
    // this is done here to avoid rollover resulting in negative steptime
    // it might be better to leave it alone and do fract() in the vertex shader?
    let timescale = 10f32;
    let stepx = (b.pos.x - a.pos.x) / count as f32;
    let stepy = (b.pos.y - a.pos.y) / count as f32;
    let steptime = (b.time - a.time) / (count as f32 * timescale);
    let stepsize = (b.size - a.size) / count as f32;
    let stepspeed = (b.speed - a.speed) / count as f32;
    let stepdistance = (b.distance - a.distance) / count as f32;
    let mut addPoint = a;
    addPoint.time = (addPoint.time / timescale) % 1f32;
    for _ in range(0, count) {
        c.push(addPoint);
        addPoint.pos.x += stepx;
        addPoint.pos.y += stepy;
        addPoint.time += steptime;
        addPoint.time = if addPoint.time > 1f32 { addPoint.time - 1f32 } else { addPoint.time };
        addPoint.size += stepsize;
        addPoint.speed += stepspeed;
        addPoint.distance += stepdistance;
    }
}

pub fn draw_path(framebuffer: GLuint, shader: &PointShader, interpolator: &LuaScript, matrix: *mut f32, color: [f32, ..3], brush: &Texture, backBuffer: &Texture) -> bool {
    let s = get_statics();
    s.drawvec.clear();

    interpolator.prep();
    run_lua_shader(backBuffer.dimensions, s);

    let ref mut pointvec = s.drawvec;
    if pointvec.len() > 0 {
        bind_framebuffer(FRAMEBUFFER, framebuffer);
        let safe_matrix: &Matrix = unsafe { mem::transmute(matrix) };
        shader.prep(safe_matrix.as_slice(), pointvec.as_slice(), color, brush, backBuffer);
        draw_arrays(POINTS, 0, pointvec.len() as i32);
        check_gl_error("draw_arrays");
    }
    s.currentPoints.iter().all(|x: (uint, &PointStorage)| {
        let (_, point) = x;
        logi!("getting point info");
        let isnone = point.info.is_none();
        logi!("got point info: {}", isnone);
        isnone
    })
}

#[no_mangle]
pub extern "C" fn next_point_from_lua(s: &mut RustStatics, points: &mut (ShaderPaintPoint, ShaderPaintPoint)) -> bool {
    let ref mut queue = s.consumer;
    let ref mut currentPoints = s.currentPoints;
    loop {
        match queue.pop() {
            Some(point) => {
                let idx = point.index;
                let newpoint = point.entry;
                if !currentPoints.contains_key(&(idx as uint)) {
                    currentPoints.insert(idx as uint, PointStorage {
                        info: None,
                        sizeavg: RollingAverage::new(16),
                        speedavg: RollingAverage::new(16),
                    });
                }
                let oldpoint = currentPoints.find_mut(&(idx as uint)).unwrap();
                match (oldpoint.info, newpoint) {
                    (Some(op), point::Point(np)) => {
                        let dist = manhattan_distance(op.pos, np.pos);
                        let avgsize = oldpoint.sizeavg.push(np.size);
                        let avgspeed = oldpoint.speedavg.push(dist);
                        let npdata = ShaderPaintPoint {
                            pos: np.pos,
                            time: np.time,
                            size: avgsize,
                            speed: avgspeed,
                            distance: op.distance + dist,
                            counter: op.counter,
                        };
                        oldpoint.info = Some(npdata);
                        *points = (op, npdata);
                        return true;
                    },
                    (_, point::Stop) => {
                        oldpoint.info = None;
                        oldpoint.sizeavg.clear();
                        oldpoint.speedavg.clear();
                    },
                    (_, point::Point(p)) => {
                        let oldCounter = s.pointCounter;
                        s.pointCounter += 1;
                        oldpoint.info = Some(ShaderPaintPoint {
                            pos: p.pos,
                            time: p.time,
                            size: p.size,
                            distance: 0f32,
                            speed: 0f32,
                            counter: oldCounter as f32,
                        });

                    },
                }
            },
            None => {
                return false;
            }
        }
    }
}

fn run_lua_shader(dimensions: (i32, i32), statics: &mut RustStatics) {
    let (x,y) = dimensions;
    unsafe {
        doInterpolateLua(x, y, statics);
    }
}

#[allow(non_snake_case_functions)]
extern "C" {
    pub fn doInterpolateLua(x: i32, y: i32, statics: *mut RustStatics);
}

#[no_mangle]
pub unsafe extern "C" fn pushrustvec(statics: &mut RustStatics, point: *const ShaderPaintPoint) {
    statics.drawvec.push(*point);
}

<commit_msg>manual point counting<commit_after>//extern crate core;
use core::prelude::*;
use core::mem;

use std::sync::{Once, ONCE_INIT, spsc_queue};

use collections::vec::Vec;
use collections::SmallIntMap;
use collections::MutableMap;
use collections::MutableSeq;
use collections::Mutable;
use collections::Map;

use log::logi;
use motionevent::append_motion_event;
use android::input::AInputEvent;

use opengles::gl2::*;

use pointshader::{PointShader};
use glcommon::check_gl_error;
use gltexture::Texture;
use point;
use point::{ShaderPaintPoint, Coordinate, PointEntry, PointConsumer, PointProducer};
use rollingaverage::RollingAverage;
use dropfree::DropFree;
use matrix::Matrix;
use luascript::LuaScript;

/// lifetime storage for a pointer's past state
struct PointStorage {
    info: Option<ShaderPaintPoint>,
    sizeavg: RollingAverage<f32>,
    speedavg: RollingAverage<f32>,
}

pub struct RustStatics {
    consumer: PointConsumer,
    producer: PointProducer,
    currentPoints: SmallIntMap<PointStorage>,
    drawvec: Vec<ShaderPaintPoint>,
    pointCounter: i32,
    point_count: i32,
}

static mut dataRef: DropFree<RustStatics> = DropFree(0 as *mut RustStatics);
static mut pathinit: Once = ONCE_INIT;

fn do_path_init() -> () {
    unsafe {
        pathinit.doit(|| {
            let (consumer, producer) = spsc_queue::queue::<PointEntry>(0);
            dataRef = DropFree::new(RustStatics {
                consumer: consumer,
                producer: producer,
                currentPoints: SmallIntMap::new(),
                drawvec: Vec::new(),
                pointCounter: 0,
                point_count: 0,
            });
            logi("created statics");
        });
    }
}

fn get_statics<'a>() -> &'a mut RustStatics {
    do_path_init();
    unsafe { dataRef.get_mut() }
}

#[no_mangle]
//FIXME: needs meaningful name
pub extern fn jni_append_motion_event(evt: *const AInputEvent) {
    let s = get_statics();
    append_motion_event(evt, &mut s.producer);
}

fn manhattan_distance(a: Coordinate, b: Coordinate) -> f32 {
    let x = if a.x > b.x { a.x - b.x } else { b.x - a.x };
    let y = if a.y > b.y { a.y - b.y } else { b.y - a.y };
    return if x > y { x } else { y };
}

#[allow(dead_code)]
fn append_points(a: ShaderPaintPoint, b: ShaderPaintPoint, c: &mut Vec<ShaderPaintPoint>, count: uint) -> () {
    // transform seconds from [0..timescale] to [0..1]
    // this is done here to avoid rollover resulting in negative steptime
    // it might be better to leave it alone and do fract() in the vertex shader?
    let timescale = 10f32;
    let stepx = (b.pos.x - a.pos.x) / count as f32;
    let stepy = (b.pos.y - a.pos.y) / count as f32;
    let steptime = (b.time - a.time) / (count as f32 * timescale);
    let stepsize = (b.size - a.size) / count as f32;
    let stepspeed = (b.speed - a.speed) / count as f32;
    let stepdistance = (b.distance - a.distance) / count as f32;
    let mut addPoint = a;
    addPoint.time = (addPoint.time / timescale) % 1f32;
    for _ in range(0, count) {
        c.push(addPoint);
        addPoint.pos.x += stepx;
        addPoint.pos.y += stepy;
        addPoint.time += steptime;
        addPoint.time = if addPoint.time > 1f32 { addPoint.time - 1f32 } else { addPoint.time };
        addPoint.size += stepsize;
        addPoint.speed += stepspeed;
        addPoint.distance += stepdistance;
    }
}

pub fn draw_path(framebuffer: GLuint, shader: &PointShader, interpolator: &LuaScript, matrix: *mut f32, color: [f32, ..3], brush: &Texture, backBuffer: &Texture) -> bool {
    let s = get_statics();
    s.drawvec.clear();

    interpolator.prep();
    run_lua_shader(backBuffer.dimensions, s);

    let ref mut pointvec = s.drawvec;
    if pointvec.len() > 0 {
        bind_framebuffer(FRAMEBUFFER, framebuffer);
        let safe_matrix: &Matrix = unsafe { mem::transmute(matrix) };
        shader.prep(safe_matrix.as_slice(), pointvec.as_slice(), color, brush, backBuffer);
        draw_arrays(POINTS, 0, pointvec.len() as i32);
        check_gl_error("draw_arrays");
    }
    s.point_count == 0
}

#[no_mangle]
pub extern "C" fn next_point_from_lua(s: &mut RustStatics, points: &mut (ShaderPaintPoint, ShaderPaintPoint)) -> bool {
    let ref mut queue = s.consumer;
    let ref mut currentPoints = s.currentPoints;
    loop {
        match queue.pop() {
            Some(point) => {
                let idx = point.index;
                let newpoint = point.entry;
                if !currentPoints.contains_key(&(idx as uint)) {
                    currentPoints.insert(idx as uint, PointStorage {
                        info: None,
                        sizeavg: RollingAverage::new(16),
                        speedavg: RollingAverage::new(16),
                    });
                }
                let oldpoint = currentPoints.find_mut(&(idx as uint)).unwrap();
                match (oldpoint.info, newpoint) {
                    (Some(op), point::Point(np)) => {
                        let dist = manhattan_distance(op.pos, np.pos);
                        let avgsize = oldpoint.sizeavg.push(np.size);
                        let avgspeed = oldpoint.speedavg.push(dist);
                        let npdata = ShaderPaintPoint {
                            pos: np.pos,
                            time: np.time,
                            size: avgsize,
                            speed: avgspeed,
                            distance: op.distance + dist,
                            counter: op.counter,
                        };
                        oldpoint.info = Some(npdata);
                        *points = (op, npdata);
                        return true;
                    },
                    (_, point::Stop) => {
                        oldpoint.info = None;
                        oldpoint.sizeavg.clear();
                        oldpoint.speedavg.clear();
                        s.point_count -= 1;
                    },
                    (_, point::Point(p)) => {
                        let oldCounter = s.pointCounter;
                        s.pointCounter += 1;
                        s.point_count += 1;
                        oldpoint.info = Some(ShaderPaintPoint {
                            pos: p.pos,
                            time: p.time,
                            size: p.size,
                            distance: 0f32,
                            speed: 0f32,
                            counter: oldCounter as f32,
                        });

                    },
                }
            },
            None => {
                return false;
            }
        }
    }
}

fn run_lua_shader(dimensions: (i32, i32), statics: &mut RustStatics) {
    let (x,y) = dimensions;
    unsafe {
        doInterpolateLua(x, y, statics);
    }
}

#[allow(non_snake_case_functions)]
extern "C" {
    pub fn doInterpolateLua(x: i32, y: i32, statics: *mut RustStatics);
}

#[no_mangle]
pub unsafe extern "C" fn pushrustvec(statics: &mut RustStatics, point: *const ShaderPaintPoint) {
    statics.drawvec.push(*point);
}

<|endoftext|>


<commit_before>//
// zhttpto.rs
//
// Starting code for PS1
// Running on Rust 0.9
//
// Note that this code has serious security risks!  You should not run it
// on any system with access to sensitive files.
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu and David Evans
// Version 0.3

#[feature(globs)];
use std::io::*;
use std::io::net::ip::{SocketAddr};
use std::{str};

static IP: &'static str = "127.0.0.1";
static PORT:        int = 4414;

fn main() {
    let addr = from_str::<SocketAddr>(format!("{:s}:{:d}", IP, PORT)).unwrap();
    let mut acceptor = net::tcp::TcpListener::bind(addr).listen();

    println(format!("Listening on [{:s}] ...", addr.to_str()));

    for stream in acceptor.incoming() {
        // Spawn a task to handle the connection
        do spawn {
            let mut stream = stream;

            match stream {
                Some(ref mut s) => {
                             match s.peer_name() {
                                Some(pn) => {println(format!("Received connection from: [{:s}]", pn.to_str()));},
                                None => ()
                             }
                           },
                None => ()
            }

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);
            println(format!("Received request :\n{:s}", request_str));

            let response: ~str =
                ~"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                 <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

                 \r\n";
            stream.write(response.as_bytes());
            println!("Connection terminates.");
        }
    }
}
<commit_msg>final<commit_after>//
// zhttpto.rs
//
// Starting code for PS1
// Running on Rust 0.9
//
// Note that this code has serious security risks!  You should not run it
// on any system with access to sensitive files.
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu and David Evans
// Version 0.3

#[feature(globs)];
use std::io::*;
use std::io::net::ip::{SocketAddr};
use std::{str,os};
use std::str;
use std::io::File;

static IP: &'static str = "127.0.0.1";
static PORT:        int = 4414;
static mut COUNT: int =0;

fn main() {
    let addr = from_str::<SocketAddr>(format!("{:s}:{:d}", IP, PORT)).unwrap();
    let mut acceptor = net::tcp::TcpListener::bind(addr).listen();

    println(format!("Listening on [{:s}] ...", addr.to_str()));

    for stream in acceptor.incoming() {
        // Spawn a task to handle the connection
        do spawn {
            let mut stream = stream;

            match stream {
                Some(ref mut s) => {
                             match s.peer_name() {
                                Some(pn) => {println(format!("Received connection from: [{:s}]", pn.to_str()));},
                                None => ()
                             }
                           },
                None => ()
            }

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf).to_owned();
	    if(request_str.contains("GET")){
		let tempstr: ~[&str]= request_str.split(' ').collect();
		if(tempstr[1].len() >2){
			let file = Path::new(tempstr[1].slice_from(1));
			println!("{}",tempstr[1].slice_from(1));
			if tempstr[1].ends_with(".html") {
                    match result(|| File::open(&file)) {
                        Ok(mut f) => {
			    println!("FILE OK");
                            let response: ~[u8] = f.read_to_end();
                            stream.write(response);
                        } ,
                        Err(e) => {
                            if e.kind == PermissionDenied {
                                stream.write("404".as_bytes());
                            }
			    else if e.kind == FileNotFound {
                                stream.write("404".as_bytes());
                            }
			    else {
                                stream.write("io error".as_bytes());
                            }
                        }
                    }
                }
		}
	    }
            println(format!("Received request :\n{:s}", request_str));
	    unsafe{
	       COUNT +=1;

            let response: ~str =
                ~"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                 <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

 Visitors:" + COUNT.to_str() + "
\r\n";
            stream.write(response.as_bytes());
            println!("Connection terminates.");
            }
        }
    }
}

//fn loadFile(path: &str)-> &str{

//}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;

extern crate bincode;
extern crate serde;
extern crate byteorder;

use std::fmt::Debug;
use std::collections::HashMap;
use std::borrow::Cow;

use bincode::{Infinite, Bounded};
use bincode::{serialized_size, ErrorKind, Result};
use bincode::endian_choice::{serialize, deserialize};

use bincode::serialize as serialize_little;
use bincode::deserialize as deserialize_little;
use bincode::deserialize_from as deserialize_from_little;

fn the_same<V>(element: V)
    where V: serde::Serialize+serde::Deserialize+PartialEq+Debug+'static
{
    let size = serialized_size(&element);
    {
        let encoded = serialize_little(&element, Infinite);
        let encoded = encoded.unwrap();
        let decoded = deserialize_little(&encoded[..]);
        let decoded = decoded.unwrap();

        assert_eq!(element, decoded);
        assert_eq!(size, encoded.len() as u64);
    }

    {
        let encoded = serialize::<_, _, byteorder::BigEndian>(&element, Infinite);
        let encoded = encoded.unwrap();
        let decoded = deserialize::<_, byteorder::BigEndian>(&encoded[..]);
        let decoded = decoded.unwrap();

        assert_eq!(element, decoded);
        assert_eq!(size, encoded.len() as u64);
    }
}

#[test]
fn test_numbers() {
    // unsigned positive
    the_same(5u8);
    the_same(5u16);
    the_same(5u32);
    the_same(5u64);
    the_same(5usize);
    // signed positive
    the_same(5i8);
    the_same(5i16);
    the_same(5i32);
    the_same(5i64);
    the_same(5isize);
    // signed negative
    the_same(-5i8);
    the_same(-5i16);
    the_same(-5i32);
    the_same(-5i64);
    the_same(-5isize);
    // floating
    the_same(-100f32);
    the_same(0f32);
    the_same(5f32);
    the_same(-100f64);
    the_same(5f64);
}

#[test]
fn test_string() {
    the_same("".to_string());
    the_same("a".to_string());
}

#[test]
fn test_tuple() {
    the_same((1isize,));
    the_same((1isize,2isize,3isize));
    the_same((1isize,"foo".to_string(),()));
}

#[test]
fn test_basic_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Easy {
        x: isize,
        s: String,
        y: usize
    }
    the_same(Easy{x: -4, s: "foo".to_string(), y: 10});
}

#[test]
fn test_nested_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Easy {
        x: isize,
        s: String,
        y: usize
    }
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Nest {
        f: Easy,
        b: usize,
        s: Easy
    }

    the_same(Nest {
        f: Easy {x: -1, s: "foo".to_string(), y: 20},
        b: 100,
        s: Easy {x: -100, s: "bar".to_string(), y: 20}
    });
}

#[test]
fn test_struct_newtype() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct NewtypeStr(usize);

    the_same(NewtypeStr(5));
}

#[test]
fn test_struct_tuple() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct TubStr(usize, String, f32);

    the_same(TubStr(5, "hello".to_string(), 3.2));
}

#[test]
fn test_option() {
    the_same(Some(5usize));
    the_same(Some("foo bar".to_string()));
    the_same(None::<usize>);
}

#[test]
fn test_enum() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum TestEnum {
        NoArg,
        OneArg(usize),
        Args(usize, usize),
        AnotherNoArg,
        StructLike{x: usize, y: f32}
    }
    the_same(TestEnum::NoArg);
    the_same(TestEnum::OneArg(4));
    //the_same(TestEnum::Args(4, 5));
    the_same(TestEnum::AnotherNoArg);
    the_same(TestEnum::StructLike{x: 4, y: 3.14159});
    the_same(vec![TestEnum::NoArg, TestEnum::OneArg(5), TestEnum::AnotherNoArg,
                  TestEnum::StructLike{x: 4, y:1.4}]);
}

#[test]
fn test_vec() {
    let v: Vec<u8> = vec![];
    the_same(v);
    the_same(vec![1u64]);
    the_same(vec![1u64,2,3,4,5,6]);
}

#[test]
fn test_map() {
    let mut m = HashMap::new();
    m.insert(4u64, "foo".to_string());
    m.insert(0u64, "bar".to_string());
    the_same(m);
}

#[test]
fn test_bool() {
    the_same(true);
    the_same(false);
}

#[test]
fn test_unicode() {
    the_same("å".to_string());
    the_same("aåååååååa".to_string());
}

#[test]
fn test_fixed_size_array() {
    the_same([24u32; 32]);
    the_same([1u64, 2, 3, 4, 5, 6, 7, 8]);
    the_same([0u8; 19]);
}

#[test]
fn deserializing_errors() {
    fn isize_invalid_deserialize<T: Debug>(res: Result<T>) {
        match res.map_err(|e| *e) {
            Err(ErrorKind::InvalidEncoding{..}) => {},
            Err(ErrorKind::Custom(ref s)) if s.contains("invalid encoding") => {},
            Err(ErrorKind::Custom(ref s)) if s.contains("invalid value") => {},
            other => panic!("Expecting InvalidEncoding, got {:?}", other),
        }
    }

    isize_invalid_deserialize(deserialize_little::<bool>(&vec![0xA][..]));
    isize_invalid_deserialize(deserialize_little::<String>(&vec![1, 0, 0, 0, 0, 0, 0, 0, 0xFF][..]));
    // Out-of-bounds variant
    #[derive(Serialize, Deserialize, Debug)]
    enum Test {
        One,
        Two,
    };
    isize_invalid_deserialize(deserialize_little::<Test>(&vec![0, 0, 0, 5][..]));
    isize_invalid_deserialize(deserialize_little::<Option<u8>>(&vec![5, 0][..]));
}

#[test]
fn too_big_deserialize() {
    let serialized = vec![0,0,0,3];
    let deserialized: Result<u32> = deserialize_from_little::<_, _, _>(&mut &serialized[..], Bounded(3));
    assert!(deserialized.is_err());

    let serialized = vec![0,0,0,3];
    let deserialized: Result<u32> = deserialize_from_little::<_, _, _>(&mut &serialized[..], Bounded(4));
    assert!(deserialized.is_ok());
}

#[test]
fn char_serialization() {
    let chars = "Aa\0☺♪";
    for c in chars.chars() {
        let encoded = serialize_little(&c, Bounded(4)).expect("serializing char failed");
        let decoded: char = deserialize_little(&encoded).expect("deserializing failed");
        assert_eq!(decoded, c);
    }
}

#[test]
fn too_big_char_deserialize() {
    let serialized = vec![0x41];
    let deserialized: Result<char> = deserialize_from_little::<_, _, _>(&mut &serialized[..], Bounded(1));
    assert!(deserialized.is_ok());
    assert_eq!(deserialized.unwrap(), 'A');
}

#[test]
fn too_big_serialize() {
    assert!(serialize_little(&0u32, Bounded(3)).is_err());
    assert!(serialize_little(&0u32, Bounded(4)).is_ok());

    assert!(serialize_little(&"abcde", Bounded(8 + 4)).is_err());
    assert!(serialize_little(&"abcde", Bounded(8 + 5)).is_ok());
}

#[test]
fn test_proxy_encoded_size() {
    assert!(serialized_size(&0u8) == 1);
    assert!(serialized_size(&0u16) == 2);
    assert!(serialized_size(&0u32) == 4);
    assert!(serialized_size(&0u64) == 8);

    // length isize stored as u64
    assert!(serialized_size(&"") == 8);
    assert!(serialized_size(&"a") == 8 + 1);

    assert!(serialized_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4))

}

#[test]
fn test_serialized_size() {
    assert!(serialized_size(&0u8) == 1);
    assert!(serialized_size(&0u16) == 2);
    assert!(serialized_size(&0u32) == 4);
    assert!(serialized_size(&0u64) == 8);

    // length isize stored as u64
    assert!(serialized_size(&"") == 8);
    assert!(serialized_size(&"a") == 8 + 1);

    assert!(serialized_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4))
}

#[test]
fn encode_box() {
    the_same(Box::new(5));
}

#[test]
fn test_cow_serialize() {
    let large_object = vec![1u32,2,3,4,5,6];
    let mut large_map = HashMap::new();
    large_map.insert(1, 2);

    #[derive(Serialize, Deserialize, Debug)]
    enum Message<'a> {
        M1(Cow<'a, Vec<u32>>),
        M2(Cow<'a, HashMap<u32, u32>>)
    }

    // Test 1
    {
        let serialized = serialize_little(&Message::M1(Cow::Borrowed(&large_object)), Infinite).unwrap();
        let deserialized: Message<'static> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap();

        match deserialized {
            Message::M1(b) => assert!(&b.into_owned() == &large_object),
            _ => assert!(false)
        }
    }

    // Test 2
    {
        let serialized = serialize_little(&Message::M2(Cow::Borrowed(&large_map)), Infinite).unwrap();
        let deserialized: Message<'static> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap();

        match deserialized {
            Message::M2(b) => assert!(&b.into_owned() == &large_map),
            _ => assert!(false)
        }
    }
}

#[test]
fn test_strbox_serialize() {
    let strx: &'static str = "hello world";
    let serialized = serialize_little(&Cow::Borrowed(strx), Infinite).unwrap();
    let deserialized: Cow<'static, String> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap();
    let stringx: String = deserialized.into_owned();
    assert!(strx == &stringx[..]);
}

#[test]
fn test_slicebox_serialize() {
    let slice = [1u32, 2, 3 ,4, 5];
    let serialized = serialize_little(&Cow::Borrowed(&slice[..]), Infinite).unwrap();
    println!("{:?}", serialized);
    let deserialized: Cow<'static, Vec<u32>> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap();
    {
        let sb: &[u32] = &deserialized;
        assert!(slice == sb);
    }
    let vecx: Vec<u32> = deserialized.into_owned();
    assert!(slice == &vecx[..]);
}

#[test]
fn test_multi_strings_serialize() {
    assert!(serialize_little(&("foo", "bar", "baz"), Infinite).is_ok());
}

/*
#[test]
fn test_oom_protection() {
    use std::io::Cursor;
    struct FakeVec {
        len: u64,
        byte: u8
    }
    let x = bincode::rustc_serialize::encode(&FakeVec { len: 0xffffffffffffffffu64, byte: 1 }, bincode::SizeLimit::Bounded(10)).unwrap();
    let y : Result<Vec<u8>, _> = bincode::rustc_serialize::decode_from(&mut Cursor::new(&x[..]), bincode::SizeLimit::Bounded(10));
    assert!(y.is_err());
}*/

#[test]
fn path_buf() {
    use std::path::{Path, PathBuf};
    let path = Path::new("foo").to_path_buf();
    let serde_encoded = serialize_little(&path, Infinite).unwrap();
    let decoded: PathBuf = deserialize_little(&serde_encoded).unwrap();
    assert!(path.to_str() == decoded.to_str());
}

#[test]
fn bytes() {
    use serde::bytes::Bytes;

    let data = b"abc\0123";
    let s = serialize_little(&data, Infinite).unwrap();
    let s2 = serialize_little(&Bytes::new(data), Infinite).unwrap();
    assert_eq!(s[..], s2[8..]);
}

#[test]
fn endian_difference() {
    let x = 10u64;
    let little = serialize_little(&x, Infinite).unwrap();
    let big = serialize::<_, _, byteorder::BigEndian>(&x, Infinite).unwrap();
    assert_ne!(little, big);
}
<commit_msg>add more tests<commit_after>#[macro_use]
extern crate serde_derive;

extern crate bincode;
extern crate serde;
extern crate byteorder;

use std::fmt::Debug;
use std::collections::HashMap;
use std::borrow::Cow;

use bincode::{Infinite, Bounded};
use bincode::{serialized_size, ErrorKind, Result};
use bincode::endian_choice::{serialize, deserialize};

use bincode::serialize as serialize_little;
use bincode::deserialize as deserialize_little;
use bincode::deserialize_from as deserialize_from_little;

fn the_same<V>(element: V)
    where V: serde::Serialize+serde::Deserialize+PartialEq+Debug+'static
{
    let size = serialized_size(&element);
    {
        let encoded = serialize_little(&element, Infinite);
        let encoded = encoded.unwrap();
        let decoded = deserialize_little(&encoded[..]);
        let decoded = decoded.unwrap();

        assert_eq!(element, decoded);
        assert_eq!(size, encoded.len() as u64);
    }

    {
        let encoded = serialize::<_, _, byteorder::BigEndian>(&element, Infinite);
        let encoded = encoded.unwrap();
        let decoded = deserialize::<_, byteorder::BigEndian>(&encoded[..]);
        let decoded = decoded.unwrap();

        assert_eq!(element, decoded);
        assert_eq!(size, encoded.len() as u64);
    }
}

#[test]
fn test_numbers() {
    // unsigned positive
    the_same(5u8);
    the_same(5u16);
    the_same(5u32);
    the_same(5u64);
    the_same(5usize);
    // signed positive
    the_same(5i8);
    the_same(5i16);
    the_same(5i32);
    the_same(5i64);
    the_same(5isize);
    // signed negative
    the_same(-5i8);
    the_same(-5i16);
    the_same(-5i32);
    the_same(-5i64);
    the_same(-5isize);
    // floating
    the_same(-100f32);
    the_same(0f32);
    the_same(5f32);
    the_same(-100f64);
    the_same(5f64);
}

#[test]
fn test_string() {
    the_same("".to_string());
    the_same("a".to_string());
}

#[test]
fn test_tuple() {
    the_same((1isize,));
    the_same((1isize,2isize,3isize));
    the_same((1isize,"foo".to_string(),()));
}

#[test]
fn test_basic_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Easy {
        x: isize,
        s: String,
        y: usize
    }
    the_same(Easy{x: -4, s: "foo".to_string(), y: 10});
}

#[test]
fn test_nested_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Easy {
        x: isize,
        s: String,
        y: usize
    }
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Nest {
        f: Easy,
        b: usize,
        s: Easy
    }

    the_same(Nest {
        f: Easy {x: -1, s: "foo".to_string(), y: 20},
        b: 100,
        s: Easy {x: -100, s: "bar".to_string(), y: 20}
    });
}

#[test]
fn test_struct_newtype() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct NewtypeStr(usize);

    the_same(NewtypeStr(5));
}

#[test]
fn test_struct_tuple() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct TubStr(usize, String, f32);

    the_same(TubStr(5, "hello".to_string(), 3.2));
}

#[test]
fn test_option() {
    the_same(Some(5usize));
    the_same(Some("foo bar".to_string()));
    the_same(None::<usize>);
}

#[test]
fn test_enum() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum TestEnum {
        NoArg,
        OneArg(usize),
        Args(usize, usize),
        AnotherNoArg,
        StructLike{x: usize, y: f32}
    }
    the_same(TestEnum::NoArg);
    the_same(TestEnum::OneArg(4));
    //the_same(TestEnum::Args(4, 5));
    the_same(TestEnum::AnotherNoArg);
    the_same(TestEnum::StructLike{x: 4, y: 3.14159});
    the_same(vec![TestEnum::NoArg, TestEnum::OneArg(5), TestEnum::AnotherNoArg,
                  TestEnum::StructLike{x: 4, y:1.4}]);
}

#[test]
fn test_vec() {
    let v: Vec<u8> = vec![];
    the_same(v);
    the_same(vec![1u64]);
    the_same(vec![1u64,2,3,4,5,6]);
}

#[test]
fn test_map() {
    let mut m = HashMap::new();
    m.insert(4u64, "foo".to_string());
    m.insert(0u64, "bar".to_string());
    the_same(m);
}

#[test]
fn test_bool() {
    the_same(true);
    the_same(false);
}

#[test]
fn test_unicode() {
    the_same("å".to_string());
    the_same("aåååååååa".to_string());
}

#[test]
fn test_fixed_size_array() {
    the_same([24u32; 32]);
    the_same([1u64, 2, 3, 4, 5, 6, 7, 8]);
    the_same([0u8; 19]);
}

#[test]
fn deserializing_errors() {
    fn isize_invalid_deserialize<T: Debug>(res: Result<T>) {
        match res.map_err(|e| *e) {
            Err(ErrorKind::InvalidEncoding{..}) => {},
            Err(ErrorKind::Custom(ref s)) if s.contains("invalid encoding") => {},
            Err(ErrorKind::Custom(ref s)) if s.contains("invalid value") => {},
            other => panic!("Expecting InvalidEncoding, got {:?}", other),
        }
    }

    isize_invalid_deserialize(deserialize_little::<bool>(&vec![0xA][..]));
    isize_invalid_deserialize(deserialize_little::<String>(&vec![1, 0, 0, 0, 0, 0, 0, 0, 0xFF][..]));
    // Out-of-bounds variant
    #[derive(Serialize, Deserialize, Debug)]
    enum Test {
        One,
        Two,
    };
    isize_invalid_deserialize(deserialize_little::<Test>(&vec![0, 0, 0, 5][..]));
    isize_invalid_deserialize(deserialize_little::<Option<u8>>(&vec![5, 0][..]));
}

#[test]
fn too_big_deserialize() {
    let serialized = vec![0,0,0,3];
    let deserialized: Result<u32> = deserialize_from_little::<_, _, _>(&mut &serialized[..], Bounded(3));
    assert!(deserialized.is_err());

    let serialized = vec![0,0,0,3];
    let deserialized: Result<u32> = deserialize_from_little::<_, _, _>(&mut &serialized[..], Bounded(4));
    assert!(deserialized.is_ok());
}

#[test]
fn char_serialization() {
    let chars = "Aa\0☺♪";
    for c in chars.chars() {
        let encoded = serialize_little(&c, Bounded(4)).expect("serializing char failed");
        let decoded: char = deserialize_little(&encoded).expect("deserializing failed");
        assert_eq!(decoded, c);
    }
}

#[test]
fn too_big_char_deserialize() {
    let serialized = vec![0x41];
    let deserialized: Result<char> = deserialize_from_little::<_, _, _>(&mut &serialized[..], Bounded(1));
    assert!(deserialized.is_ok());
    assert_eq!(deserialized.unwrap(), 'A');
}

#[test]
fn too_big_serialize() {
    assert!(serialize_little(&0u32, Bounded(3)).is_err());
    assert!(serialize_little(&0u32, Bounded(4)).is_ok());

    assert!(serialize_little(&"abcde", Bounded(8 + 4)).is_err());
    assert!(serialize_little(&"abcde", Bounded(8 + 5)).is_ok());
}

#[test]
fn test_proxy_encoded_size() {
    assert!(serialized_size(&0u8) == 1);
    assert!(serialized_size(&0u16) == 2);
    assert!(serialized_size(&0u32) == 4);
    assert!(serialized_size(&0u64) == 8);

    // length isize stored as u64
    assert!(serialized_size(&"") == 8);
    assert!(serialized_size(&"a") == 8 + 1);

    assert!(serialized_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4))

}

#[test]
fn test_serialized_size() {
    assert!(serialized_size(&0u8) == 1);
    assert!(serialized_size(&0u16) == 2);
    assert!(serialized_size(&0u32) == 4);
    assert!(serialized_size(&0u64) == 8);

    // length isize stored as u64
    assert!(serialized_size(&"") == 8);
    assert!(serialized_size(&"a") == 8 + 1);

    assert!(serialized_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4))
}

#[test]
fn encode_box() {
    the_same(Box::new(5));
}

#[test]
fn test_cow_serialize() {
    let large_object = vec![1u32,2,3,4,5,6];
    let mut large_map = HashMap::new();
    large_map.insert(1, 2);

    #[derive(Serialize, Deserialize, Debug)]
    enum Message<'a> {
        M1(Cow<'a, Vec<u32>>),
        M2(Cow<'a, HashMap<u32, u32>>)
    }

    // Test 1
    {
        let serialized = serialize_little(&Message::M1(Cow::Borrowed(&large_object)), Infinite).unwrap();
        let deserialized: Message<'static> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap();

        match deserialized {
            Message::M1(b) => assert!(&b.into_owned() == &large_object),
            _ => assert!(false)
        }
    }

    // Test 2
    {
        let serialized = serialize_little(&Message::M2(Cow::Borrowed(&large_map)), Infinite).unwrap();
        let deserialized: Message<'static> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap();

        match deserialized {
            Message::M2(b) => assert!(&b.into_owned() == &large_map),
            _ => assert!(false)
        }
    }
}

#[test]
fn test_strbox_serialize() {
    let strx: &'static str = "hello world";
    let serialized = serialize_little(&Cow::Borrowed(strx), Infinite).unwrap();
    let deserialized: Cow<'static, String> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap();
    let stringx: String = deserialized.into_owned();
    assert!(strx == &stringx[..]);
}

#[test]
fn test_slicebox_serialize() {
    let slice = [1u32, 2, 3 ,4, 5];
    let serialized = serialize_little(&Cow::Borrowed(&slice[..]), Infinite).unwrap();
    println!("{:?}", serialized);
    let deserialized: Cow<'static, Vec<u32>> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap();
    {
        let sb: &[u32] = &deserialized;
        assert!(slice == sb);
    }
    let vecx: Vec<u32> = deserialized.into_owned();
    assert!(slice == &vecx[..]);
}

#[test]
fn test_multi_strings_serialize() {
    assert!(serialize_little(&("foo", "bar", "baz"), Infinite).is_ok());
}

#[test]
fn test_oom_protection() {
    use std::io::Cursor;
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct FakeVec {
        len: u64,
        byte: u8
    }
    let x = serialize_little(&FakeVec { len: 0xffffffffffffffffu64, byte: 1 }, Bounded(10)).unwrap();
    let y: Result<Vec<u8>> = deserialize_from_little(&mut Cursor::new(&x[..]), Bounded(10));
    assert!(y.is_err());
}

#[test]
fn path_buf() {
    use std::path::{Path, PathBuf};
    let path = Path::new("foo").to_path_buf();
    let serde_encoded = serialize_little(&path, Infinite).unwrap();
    let decoded: PathBuf = deserialize_little(&serde_encoded).unwrap();
    assert!(path.to_str() == decoded.to_str());
}

#[test]
fn bytes() {
    use serde::bytes::Bytes;

    let data = b"abc\0123";
    let s = serialize_little(&data[..], Infinite).unwrap();
    let s2 = serialize_little(&Bytes::new(data), Infinite).unwrap();
    assert_eq!(s[..], s2[..]);
}

#[test]
fn serde_bytes() {
    use serde::bytes::ByteBuf;
    the_same(ByteBuf::from(vec![1,2,3,4,5]));
}

#[test]
fn endian_difference() {
    let x = 10u64;
    let little = serialize_little(&x, Infinite).unwrap();
    let big = serialize::<_, _, byteorder::BigEndian>(&x, Infinite).unwrap();
    assert_ne!(little, big);
}
<|endoftext|>


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

//! Implements the traits found in [ecma402_traits::pluralrules].

use ecma402_traits;
use rust_icu_common as common;
use rust_icu_upluralrules as uplr;
use std::fmt;

/// Implements [ecma402_traits::pluralrules::PluralRules] using ICU as the underlying
/// implementing library.
pub struct PluralRules {
    // The internal representation of rules.
    rep: uplr::UPluralRules,
}

pub(crate) mod internal {
    use ecma402_traits::pluralrules::options;
    use rust_icu_sys as usys;

    // Converts the trait style option type to an equivalente ICU type.
    pub fn to_icu_type(style: &options::Type) -> usys::UPluralType {
        match style {
            options::Type::Ordinal => usys::UPluralType::UPLURAL_TYPE_ORDINAL,
            options::Type::Cardinal => usys::UPluralType::UPLURAL_TYPE_CARDINAL,
        }
    }
}

impl ecma402_traits::pluralrules::PluralRules for PluralRules {
    type Error = common::Error;

    /// Creates a new [PluralRules].
    ///
    /// Creation may fail, for example, if the locale-specific data is not loaded, or if
    /// the supplied options are inconsistent.
    ///
    /// > Note: not yet implemented: the formatting constraints (min integer digits and such).
    fn try_new<L>(l: L, opts: ecma402_traits::pluralrules::Options) -> Result<Self, Self::Error>
    where
        L: ecma402_traits::Locale,
        Self: Sized,
    {
        let locale = format!("{}", l);
        let style_type = internal::to_icu_type(&opts.in_type);
        let rep = uplr::UPluralRules::try_new_styled(&locale, style_type)?;
        Ok(PluralRules { rep })
    }

    /// Formats the plural class of `number` into the supplied `writer`.
    ///
    /// The function implements [`Intl.PluralRules`][plr] from [ECMA 402][ecma].
    ///
    ///    [plr]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules
    ///    [ecma]: https://www.ecma-international.org/publications/standards/Ecma-402.htm
    fn select<W>(&self, number: f64, writer: &mut W) -> fmt::Result
    where
        W: fmt::Write,
    {
        let result = self.rep.select(number).map_err(|e| e.into())?;
        write!(writer, "{}", result)
    }
}

#[cfg(test)]
mod testing {
    use super::*;
    use ecma402_traits::pluralrules;
    use ecma402_traits::pluralrules::PluralRules;
    use rust_icu_uloc as uloc;
    use std::convert::TryFrom;

    #[test]
    fn plurals_per_locale() -> Result<(), common::Error> {
        #[derive(Debug, Clone)]
        struct TestCase {
            locale: &'static str,
            opts: pluralrules::Options,
            numbers: Vec<f64>,
            expected: Vec<&'static str>,
        };
        let tests = vec![
            TestCase {
                locale: "ar_EG",
                opts: Default::default(),
                numbers: vec![0 as f64, 1 as f64, 2 as f64, 6 as f64, 18 as f64],
                expected: vec!["zero", "one", "two", "few", "many"],
            },
            TestCase {
                locale: "ar_EG",
                opts: pluralrules::Options {
                    in_type: pluralrules::options::Type::Ordinal,
                    .. Default::default()
                },
                numbers: vec![0 as f64, 1 as f64, 2 as f64, 6 as f64, 18 as f64],
                expected: vec!["other", "other", "other", "other", "other"],
            },
            TestCase {
                locale: "sr_RS",
                opts: Default::default(),
                numbers: vec![0 as f64, 1 as f64, 2 as f64, 4 as f64, 6 as f64, 18 as f64],
                expected: vec!["other", "one", "few", "few", "other", "other"],
            },
            TestCase {
                locale: "sr_RS",
                opts: pluralrules::Options {
                    in_type: pluralrules::options::Type::Ordinal,
                    .. Default::default()
                },
                numbers: vec![0 as f64, 1 as f64, 2 as f64, 4 as f64, 6 as f64, 18 as f64],
                expected: vec!["other", "other", "other", "other", "other", "other"],
            },
        ];
        for test in tests {
            let locale = uloc::ULoc::try_from(test.locale).expect("locale exists");
            let plr = super::PluralRules::try_new(locale, test.clone().opts)?;
            let actual = test
                .numbers
                .iter()
                .map(|n| {
                    let mut result = String::new();
                    plr.select(*n, &mut result).unwrap();
                    result
                })
                .collect::<Vec<String>>();
            assert_eq!(test.expected, actual, "for test case: {:?}", &test);
        }
        Ok(())
    }
}
<commit_msg>Correct a typo in the doc comments.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Implements the traits found in [ecma402_traits::pluralrules].

use ecma402_traits;
use rust_icu_common as common;
use rust_icu_upluralrules as uplr;
use std::fmt;

/// Implements [ecma402_traits::pluralrules::PluralRules] using ICU as the underlying
/// implementing library.
pub struct PluralRules {
    // The internal representation of rules.
    rep: uplr::UPluralRules,
}

pub(crate) mod internal {
    use ecma402_traits::pluralrules::options;
    use rust_icu_sys as usys;

    // Converts the trait style option type to an equivalent ICU type.
    pub fn to_icu_type(style: &options::Type) -> usys::UPluralType {
        match style {
            options::Type::Ordinal => usys::UPluralType::UPLURAL_TYPE_ORDINAL,
            options::Type::Cardinal => usys::UPluralType::UPLURAL_TYPE_CARDINAL,
        }
    }
}

impl ecma402_traits::pluralrules::PluralRules for PluralRules {
    type Error = common::Error;

    /// Creates a new [PluralRules].
    ///
    /// Creation may fail, for example, if the locale-specific data is not loaded, or if
    /// the supplied options are inconsistent.
    ///
    /// > Note: not yet implemented: the formatting constraints (min integer digits and such).
    fn try_new<L>(l: L, opts: ecma402_traits::pluralrules::Options) -> Result<Self, Self::Error>
    where
        L: ecma402_traits::Locale,
        Self: Sized,
    {
        let locale = format!("{}", l);
        let style_type = internal::to_icu_type(&opts.in_type);
        let rep = uplr::UPluralRules::try_new_styled(&locale, style_type)?;
        Ok(PluralRules { rep })
    }

    /// Formats the plural class of `number` into the supplied `writer`.
    ///
    /// The function implements [`Intl.PluralRules`][plr] from [ECMA 402][ecma].
    ///
    ///    [plr]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules
    ///    [ecma]: https://www.ecma-international.org/publications/standards/Ecma-402.htm
    fn select<W>(&self, number: f64, writer: &mut W) -> fmt::Result
    where
        W: fmt::Write,
    {
        let result = self.rep.select(number).map_err(|e| e.into())?;
        write!(writer, "{}", result)
    }
}

#[cfg(test)]
mod testing {
    use super::*;
    use ecma402_traits::pluralrules;
    use ecma402_traits::pluralrules::PluralRules;
    use rust_icu_uloc as uloc;
    use std::convert::TryFrom;

    #[test]
    fn plurals_per_locale() -> Result<(), common::Error> {
        #[derive(Debug, Clone)]
        struct TestCase {
            locale: &'static str,
            opts: pluralrules::Options,
            numbers: Vec<f64>,
            expected: Vec<&'static str>,
        };
        let tests = vec![
            TestCase {
                locale: "ar_EG",
                opts: Default::default(),
                numbers: vec![0 as f64, 1 as f64, 2 as f64, 6 as f64, 18 as f64],
                expected: vec!["zero", "one", "two", "few", "many"],
            },
            TestCase {
                locale: "ar_EG",
                opts: pluralrules::Options {
                    in_type: pluralrules::options::Type::Ordinal,
                    .. Default::default()
                },
                numbers: vec![0 as f64, 1 as f64, 2 as f64, 6 as f64, 18 as f64],
                expected: vec!["other", "other", "other", "other", "other"],
            },
            TestCase {
                locale: "sr_RS",
                opts: Default::default(),
                numbers: vec![0 as f64, 1 as f64, 2 as f64, 4 as f64, 6 as f64, 18 as f64],
                expected: vec!["other", "one", "few", "few", "other", "other"],
            },
            TestCase {
                locale: "sr_RS",
                opts: pluralrules::Options {
                    in_type: pluralrules::options::Type::Ordinal,
                    .. Default::default()
                },
                numbers: vec![0 as f64, 1 as f64, 2 as f64, 4 as f64, 6 as f64, 18 as f64],
                expected: vec!["other", "other", "other", "other", "other", "other"],
            },
        ];
        for test in tests {
            let locale = uloc::ULoc::try_from(test.locale).expect("locale exists");
            let plr = super::PluralRules::try_new(locale, test.clone().opts)?;
            let actual = test
                .numbers
                .iter()
                .map(|n| {
                    let mut result = String::new();
                    plr.select(*n, &mut result).unwrap();
                    result
                })
                .collect::<Vec<String>>();
            assert_eq!(test.expected, actual, "for test case: {:?}", &test);
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::ptr;
use libc::{c_int};
use glib::Error;
use glib::object::{Wrapper, Ref};
use glib::types::{StaticType, Type};
use glib::translate::*;
use glib::glib_container::GlibContainer;
use secret_service::SecretService;
use secret_item::SecretItem;
use SecretResult;
use ffi;

pub struct SecretCollection(Ref);

impl SecretCollection {

    /// Lookup which collection is assigned to this alias.
    /// Aliases help determine well known collections, such as 'default'.
    /// Returns the collection, or NULL if none assigned to the alias.
    pub fn for_alias(alias: &str) -> SecretResult<SecretCollection>{
        let mut err = ptr::null_mut();
        let ptr = unsafe{ffi::secret_collection_for_alias_sync(ptr::null_mut(), alias.to_glib_none().0, SECRET_COLLECTION_LOAD_ITEMS, ptr::null_mut(), &mut err)};
        if err.is_null(){
            Ok(unsafe { from_glib_full(ptr) })
        } else {
            Err(Error::wrap(err))
        }
    }

    /// Create a new collection in the secret service.
    /// If you specify an alias and a collection with that alias already exists, then a new collection will not be created. The previous one will be returned instead.
    /// Returns the created Collection.
    pub fn create(label: &str, alias: Option<&str>) -> SecretResult<SecretCollection> {
        let mut err = ptr::null_mut();
        let ptr = unsafe{ffi::secret_collection_create_sync(ptr::null_mut(), label.to_glib_none().0, alias.to_glib_none().0, 0 as c_int, ptr::null_mut(), &mut err)};
        if err.is_null(){
            Ok(unsafe { from_glib_full(ptr) })
        } else {
            Err(Error::wrap(err))
        }
    }

    /// Get the created date and time of the collection.
    /// The return value is the number of seconds since the unix epoch, January 1st 1970.
    pub fn get_created(&self) -> u64 {
        unsafe {ffi::secret_collection_get_created(self.to_glib_none().0)}
    }

    /// Get the modified date and time of the collection.
    /// The return value is the number of seconds since the unix epoch, January 1st 1970.
    pub fn get_modified(&self) -> u64 {
        unsafe {ffi::secret_collection_get_modified(self.to_glib_none().0)}
    }

    /// Get the Secret Service object that this collection was created with.
    pub fn get_service(&self) -> SecretService { //TODO find out if this can return null
        unsafe {
            let ptr = ffi::secret_collection_get_service(self.to_glib_none().0);
            from_glib_none(ptr)
        }
    }

    pub fn are_items_loaded(&self) -> bool {
        let flags = unsafe {ffi::secret_collection_get_flags(self.to_glib_none().0)};
        flags & SECRET_COLLECTION_LOAD_ITEMS != 0
    }

    /// Get the label of this collection.
    pub fn get_label(&self) -> String {
        unsafe{
            let ptr = ffi::secret_collection_get_label(self.to_glib_none().0);
            from_glib_full(ptr)
        }
    }

    /// Get whether the collection is locked or not.
    pub fn get_locked(&self) -> bool {
        let gbool = unsafe{ffi::secret_collection_get_locked(self.to_glib_none().0)};
        from_glib(gbool)
    }

    /// Returns None, if the items have not yet been loaded.
    pub fn get_items(&self) -> Vec<SecretItem> {
        unsafe {
            let glist = ffi::secret_collection_get_items(self.to_glib_none().0);
            Vec::from_glib_full(glist)
        }
    }

    /// Ensure that the SecretCollection proxy has loaded all the items present in the Secret Service.
    pub fn load_items(&self) -> SecretResult<()>{
        unsafe {
            let mut err = ptr::null_mut();
            ffi::secret_collection_load_items_sync(self.to_glib_none().0, ptr::null_mut(), &mut err);
            if err.is_null() {
                Ok(())
            } else {
                Err(Error::wrap(err))
            }
        }
    }

    //TODO set_alias from ss
}

impl StaticType for SecretCollection {
    fn static_type() -> Type{
        unsafe { from_glib(ffi::secret_collection_get_type()) }
    }
}

impl Wrapper for SecretCollection {
    type GlibType = ffi::SecretCollectionFFI;
    unsafe fn wrap(r: Ref) -> Self{
        SecretCollection(r)
    }

    fn as_ref(&self) -> &Ref{
        &self.0
    }

    fn unwrap(self) -> Ref{
        self.0
    }
}

#[allow(dead_code)]
const SECRET_COLLECTION_NONE: i32        = 0;
const SECRET_COLLECTION_LOAD_ITEMS: i32  = 1 << 1;
<commit_msg>Make SecretCollection a proper Object<commit_after>use std::ptr;
use libc::{c_int};
use glib::Error;
use glib::object::{Object, Upcast, Wrapper, Ref};
use glib::types::{StaticType, Type};
use glib::translate::*;
use glib::glib_container::GlibContainer;
use secret_service::SecretService;
use secret_item::SecretItem;
use SecretResult;
use ffi;

pub struct SecretCollection(Ref);

impl SecretCollection {

    /// Lookup which collection is assigned to this alias.
    /// Aliases help determine well known collections, such as 'default'.
    /// Returns the collection, or NULL if none assigned to the alias.
    pub fn for_alias(alias: &str) -> SecretResult<SecretCollection>{
        let mut err = ptr::null_mut();
        let ptr = unsafe{ffi::secret_collection_for_alias_sync(ptr::null_mut(), alias.to_glib_none().0, SECRET_COLLECTION_LOAD_ITEMS, ptr::null_mut(), &mut err)};
        if err.is_null(){
            Ok(unsafe { from_glib_full(ptr) })
        } else {
            Err(Error::wrap(err))
        }
    }

    /// Create a new collection in the secret service.
    /// If you specify an alias and a collection with that alias already exists, then a new collection will not be created. The previous one will be returned instead.
    /// Returns the created Collection.
    pub fn create(label: &str, alias: Option<&str>) -> SecretResult<SecretCollection> {
        let mut err = ptr::null_mut();
        let ptr = unsafe{ffi::secret_collection_create_sync(ptr::null_mut(), label.to_glib_none().0, alias.to_glib_none().0, 0 as c_int, ptr::null_mut(), &mut err)};
        if err.is_null(){
            Ok(unsafe { from_glib_full(ptr) })
        } else {
            Err(Error::wrap(err))
        }
    }

    /// Get the created date and time of the collection.
    /// The return value is the number of seconds since the unix epoch, January 1st 1970.
    pub fn get_created(&self) -> u64 {
        unsafe {ffi::secret_collection_get_created(self.to_glib_none().0)}
    }

    /// Get the modified date and time of the collection.
    /// The return value is the number of seconds since the unix epoch, January 1st 1970.
    pub fn get_modified(&self) -> u64 {
        unsafe {ffi::secret_collection_get_modified(self.to_glib_none().0)}
    }

    /// Get the Secret Service object that this collection was created with.
    pub fn get_service(&self) -> SecretService { //TODO find out if this can return null
        unsafe {
            let ptr = ffi::secret_collection_get_service(self.to_glib_none().0);
            from_glib_none(ptr)
        }
    }

    pub fn are_items_loaded(&self) -> bool {
        let flags = unsafe {ffi::secret_collection_get_flags(self.to_glib_none().0)};
        flags & SECRET_COLLECTION_LOAD_ITEMS != 0
    }

    /// Get the label of this collection.
    pub fn get_label(&self) -> String {
        unsafe{
            let ptr = ffi::secret_collection_get_label(self.to_glib_none().0);
            from_glib_full(ptr)
        }
    }

    /// Get whether the collection is locked or not.
    pub fn get_locked(&self) -> bool {
        let gbool = unsafe{ffi::secret_collection_get_locked(self.to_glib_none().0)};
        from_glib(gbool)
    }

    /// Returns None, if the items have not yet been loaded.
    pub fn get_items(&self) -> Vec<SecretItem> {
        unsafe {
            let glist = ffi::secret_collection_get_items(self.to_glib_none().0);
            Vec::from_glib_full(glist)
        }
    }

    /// Ensure that the SecretCollection proxy has loaded all the items present in the Secret Service.
    pub fn load_items(&self) -> SecretResult<()>{
        unsafe {
            let mut err = ptr::null_mut();
            ffi::secret_collection_load_items_sync(self.to_glib_none().0, ptr::null_mut(), &mut err);
            if err.is_null() {
                Ok(())
            } else {
                Err(Error::wrap(err))
            }
        }
    }

    //TODO set_alias from ss
}

impl StaticType for SecretCollection {
    fn static_type() -> Type{
        unsafe { from_glib(ffi::secret_collection_get_type()) }
    }
}

unsafe impl Upcast<Object> for SecretCollection { }

impl Wrapper for SecretCollection {
    type GlibType = ffi::SecretCollectionFFI;
    unsafe fn wrap(r: Ref) -> Self{
        SecretCollection(r)
    }

    fn as_ref(&self) -> &Ref{
        &self.0
    }

    fn unwrap(self) -> Ref{
        self.0
    }
}

#[allow(dead_code)]
const SECRET_COLLECTION_NONE: i32        = 0;
const SECRET_COLLECTION_LOAD_ITEMS: i32  = 1 << 1;
<|endoftext|>


<commit_before>//use serde::de::Deserialize;
use super::super::link::HalLink;
use super::super::resource::OneOrMany;
use serde_json::{from_str, to_string};
use serde::*;

#[derive(Serialize, Deserialize)]
struct Boh<T:Clone>
{
    oom: OneOrMany<T>
}

#[test]
fn ensure_one_object_gets_serialized_as_one() {
    let boh: Boh<String> = Boh { oom: OneOrMany::new().with(&"test".to_owned()) };
    assert_eq!(to_string(&boh).unwrap(), r#"{"oom":"test"}"#);
}

#[test]
fn ensure_two_objects_get_serialized_as_array() {

    let boh: Boh<String> = Boh { oom: OneOrMany::new().with(&"test".to_owned()).with(&"test2".to_owned()) };
    assert_eq!(to_string(&boh).unwrap(), r#"{"oom":["test","test2"]}"#);
}

#[test]
fn ensure_array_gets_deserialized() {
    let s = r#"{"oom":["test","test2"]}"#;
    let boh: Boh<String> = from_str(s).unwrap();
    assert_eq!(2, boh.oom.len());
    assert_eq!("test", boh.oom[0]);
    assert_eq!("test2", boh.oom[1]);

}<commit_msg>Fix the tests for OneOrMany.<commit_after>//use serde::de::Deserialize;
use super::super::link::HalLink;
use super::super::resource::OneOrMany;
use serde_json::{from_str, to_string};
use serde::*;

#[derive(Serialize, Deserialize)]
struct Boh
{
    oom: OneOrMany<String>
}

#[test]
fn ensure_one_object_gets_serialized_as_one() {
    let boh = Boh { oom: OneOrMany::new().with(&"test".to_owned()) };
    assert_eq!(to_string(&boh).unwrap(), r#"{"oom":"test"}"#);
}

#[test]
fn ensure_two_objects_get_serialized_as_array() {

    let boh = Boh { oom: OneOrMany::new().with(&"test".to_owned()).with(&"test2".to_owned()) };
    assert_eq!(to_string(&boh).unwrap(), r#"{"oom":["test","test2"]}"#);
}

#[test]
fn ensure_array_gets_deserialized() {
    let s = r#"{"oom":["test","test2"]}"#;
    let boh: Boh = from_str(s).unwrap();
    assert_eq!(2, boh.oom.len());
    assert_eq!("test", boh.oom.many()[0]);
    assert_eq!("test2", boh.oom.many()[1]);

}<|endoftext|>


<commit_before>//! Falcon: A Binary Analysis Framework in Rust.

extern crate base64;
#[macro_use]
extern crate bitflags;
extern crate capstone_rust;
extern crate core;
#[macro_use]
extern crate error_chain;
extern crate goblin;
#[macro_use]
extern crate log;
extern crate regex;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

pub mod analysis;
pub mod engine;
pub mod executor;
pub mod graph;
pub mod il;
pub mod loader;
pub mod platform;
mod tests;
pub mod translator;

pub mod error {
    error_chain! {
        types {
            Error, ErrorKind, ResultExt, Result;
        }

        foreign_links {
            Base64(::base64::DecodeError);
            Goblin(::goblin::error::Error);
            Io(::std::io::Error);
            Json(::serde_json::Error);
            ParseIntError(::core::num::ParseIntError);
            Regex(::regex::Error);
            Utf8(::std::string::FromUtf8Error);
        }

        errors {
            Sort {
                description("Sort error, invalid bitness between expressions")
                display("Sort error, invalid bitness between expressions")
            }
            Arithmetic(m: String) {
                description("Error in evaluation of arithmetic expression")
                display("Arithmetic expression evaluation error: {}", m)
            }
            AccessUnmappedMemory(address: u64) {
                description("Attempt to access unmapped memory")
                display("Attempt to access unmapped memory at address 0x{:x}", address)
            }
        }
    }
}

pub use error::*;<commit_msg>fix build<commit_after>//! Falcon: A Binary Analysis Framework in Rust.

extern crate base64;
#[macro_use]
extern crate bitflags;
extern crate capstone_rust;
extern crate core;
#[macro_use]
extern crate error_chain;
extern crate goblin;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate regex;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

pub mod analysis;
pub mod engine;
pub mod executor;
pub mod graph;
pub mod il;
pub mod loader;
pub mod platform;
mod tests;
pub mod translator;

pub mod error {
    error_chain! {
        types {
            Error, ErrorKind, ResultExt, Result;
        }

        foreign_links {
            Base64(::base64::DecodeError);
            Goblin(::goblin::error::Error);
            Io(::std::io::Error);
            Json(::serde_json::Error);
            ParseIntError(::core::num::ParseIntError);
            Regex(::regex::Error);
            Utf8(::std::string::FromUtf8Error);
        }

        errors {
            Sort {
                description("Sort error, invalid bitness between expressions")
                display("Sort error, invalid bitness between expressions")
            }
            Arithmetic(m: String) {
                description("Error in evaluation of arithmetic expression")
                display("Arithmetic expression evaluation error: {}", m)
            }
            AccessUnmappedMemory(address: u64) {
                description("Attempt to access unmapped memory")
                display("Attempt to access unmapped memory at address 0x{:x}", address)
            }
        }
    }
}

pub use error::*;<|endoftext|>


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

use indoc::indoc;
use lazy_static::lazy_static;
use proc_macro2::Span;
use std::collections::HashMap;
use std::fmt::Display;
use syn::{Ident, Type, TypePath};

/// Any time we store a type name, we should use this.
/// At the moment it's just a string, but one day it will need to become
/// sufficiently intelligent to handle namespaces.
/// This should store the canonical Rust-side name, e.g.
/// u32, or CxxString. Not uint32_t, nor std_string, etc.
#[derive(Debug, PartialEq, PartialOrd, Eq, Hash, Clone)]
pub struct TypeName(String);

impl TypeName {
    pub(crate) fn from_ident(id: &Ident) -> Self {
        TypeName::new(&id.to_string())
    }

    pub(crate) fn from_type_path(p: &TypePath) -> Self {
        // TODO better handle generics, multi-segment paths, etc.
        TypeName::from_ident(TypeName::parse_type_path(p))
    }

    pub(crate) fn from_type(ty: &Type) -> Self {
        match ty {
            Type::Path(typ) => TypeName::from_type_path(typ),
            _ => panic!("Stringifying unknown type, not yet supported"), // TODO
        }
    }

    pub(crate) fn new(id: &str) -> Self {
        let canonical_name = DEADNAME_MAP.get(id);
        if let Some(canonical_name) = canonical_name {
            // This is already a cxx replacement name, e.g. CxxString.
            TypeName(canonical_name.into())
        } else {
            TypeName(id.into())
        }
    }

    pub(crate) fn to_ident(&self) -> Ident {
        Ident::new(&self.0, Span::call_site())
    }

    pub(crate) fn to_cpp_name(&self) -> &str {
        match KNOWN_TYPES.get(&self) {
            None => &self.0,
            Some(replacement) => &replacement.cpp_name.as_str(),
        }
    }

    /// Whether the given function name is prefixed by this type name
    /// and an underscore.
    /// If so, returns the suffix after that point.
    pub(crate) fn prefixes<'a>(&self, func_name: &'a str) -> Option<&'a str> {
        if func_name.starts_with(&self.0) {
            Some(&func_name[self.0.len() + 1..])
        } else {
            None
        }
    }

    fn parse_type_path(p: &TypePath) -> &Ident {
        &p.path.segments.last().unwrap().ident
    }
}

impl Display for TypeName {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str(&self.0)
    }
}

#[derive(Debug)]
enum PreludePolicy {
    Exclude,
    IncludeNormal,
    IncludeTemplated,
}

#[derive(Debug)]
pub(crate) struct TypeDetails {
    /// The name used by cxx for this type.
    cxx_name: String,
    /// This type may be called this in bindgen-generated code.
    /// We want to expunge that Bad Old Name as quickly as possible.
    cpp_deadname: Option<String>,
    /// C++ equivalent name for a Rust type.
    pub(crate) cpp_name: String,
    /// Whether this can be safely represented by value.
    pub(crate) by_value_safe: bool,
    /// Whether and how to include this in the prelude given to bindgen.
    prelude_policy: PreludePolicy,
}

impl TypeDetails {
    fn new(
        cxx_name: String,
        cpp_deadname: Option<String>,
        cpp_name: String,
        by_value_safe: bool,
        prelude_policy: PreludePolicy,
    ) -> Self {
        TypeDetails {
            cxx_name,
            cpp_deadname,
            cpp_name,
            by_value_safe,
            prelude_policy,
        }
    }

    fn get_prelude_entry(&self) -> Option<String> {
        match self.prelude_policy {
            PreludePolicy::Exclude => None,
            PreludePolicy::IncludeNormal | PreludePolicy::IncludeTemplated => {
                let proper_cpp_name = &self.cpp_name;
                let cxx_name = &self.cxx_name;
                let (templating, payload) = match self.prelude_policy {
                    PreludePolicy::IncludeNormal => ("", "char* ptr"),
                    PreludePolicy::IncludeTemplated => ("template<typename T> ", "T* ptr"),
                    _ => unreachable!(),
                };
                Some(format!(
                    indoc! {"
                    /**
                    *

                    */
                    {}class {} {{
                        {};
                    }};

                    "},
                    proper_cpp_name, templating, cxx_name, payload
                ))
            }
        }
    }
}

lazy_static! {
    pub(crate) static ref KNOWN_TYPES: HashMap<TypeName, TypeDetails> = {
        let mut map = HashMap::new();
        map.insert(
            TypeName::new("UniquePtr"),
            TypeDetails::new(
                "UniquePtr".into(),
                Some("std_unique_ptr".into()),
                "std::unique_ptr".into(),
                true,
                PreludePolicy::IncludeTemplated,
            ),
        );
        map.insert(
            TypeName::new("CxxString"),
            TypeDetails::new(
                "CxxString".into(),
                Some("std_string".into()),
                "std::string".into(),
                false,
                PreludePolicy::IncludeNormal,
            ),
        );
        for (cpp_type, rust_type) in (3..7)
            .map(|x| 2i32.pow(x))
            .map(|x| {
                vec![
                    (format!("uint{}_t", x), format!("u{}", x)),
                    (format!("int{}_t", x), format!("i{}", x)),
                ]
            })
            .flatten()
        {
            map.insert(
                TypeName::new(&rust_type),
                TypeDetails::new(
                    rust_type.into(),
                    None,
                    cpp_type,
                    true,
                    PreludePolicy::Exclude,
                ),
            );
        }
        map
    };
}

lazy_static! {
    static ref DEADNAME_MAP: HashMap<String, String> = {
        let mut map = HashMap::new();
        map.insert("std_unique_ptr".into(), "UniquePtr".into());
        map.insert("std_string".into(), "CxxString".into());
        map
    };
}

/// Prelude of C++ for squirting into bindgen. This configures
/// bindgen to output simpler types to replace some STL types
/// that bindgen just can't cope with. Although we then replace
/// those types with cxx types (e.g. UniquePtr), this intermediate
/// step is still necessary because bindgen can't otherwise
/// give us the templated types (e.g. when faced with the STL
/// unique_ptr, bindgen would normally give us std_unique_ptr
/// as opposed to std_unique_ptr<T>.)
pub(crate) fn get_prelude() -> String {
    itertools::join(
        KNOWN_TYPES.values().filter_map(|t| t.get_prelude_entry()),
        "\n",
    )
}

pub(crate) fn to_cpp_name(typ: &Type) -> String {
    match typ {
        Type::Path(ref typ) => TypeName::from_type_path(typ).to_cpp_name().to_string(),
        Type::Reference(ref typr) => {
            let const_bit = match typr.mutability {
                None => "const ",
                Some(_) => "",
            };
            format!(
                "{}{}&",
                const_bit,
                TypeName::from_type(typr.elem.as_ref())
                    .to_cpp_name()
                    .to_string()
            )
        }
        _ => unimplemented!(),
    }
}

#[cfg(test)]
mod tests {
    use crate::TypeName;

    #[test]
    fn test_ints() {
        assert_eq!(TypeName::new("i8").to_cpp_name(), "int8_t");
        assert_eq!(TypeName::new("u64").to_cpp_name(), "uint64_t");
    }
}
<commit_msg>Remove unused field.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use indoc::indoc;
use lazy_static::lazy_static;
use proc_macro2::Span;
use std::collections::HashMap;
use std::fmt::Display;
use syn::{Ident, Type, TypePath};

/// Any time we store a type name, we should use this.
/// At the moment it's just a string, but one day it will need to become
/// sufficiently intelligent to handle namespaces.
/// This should store the canonical Rust-side name, e.g.
/// u32, or CxxString. Not uint32_t, nor std_string, etc.
#[derive(Debug, PartialEq, PartialOrd, Eq, Hash, Clone)]
pub struct TypeName(String);

impl TypeName {
    pub(crate) fn from_ident(id: &Ident) -> Self {
        TypeName::new(&id.to_string())
    }

    pub(crate) fn from_type_path(p: &TypePath) -> Self {
        // TODO better handle generics, multi-segment paths, etc.
        TypeName::from_ident(TypeName::parse_type_path(p))
    }

    pub(crate) fn from_type(ty: &Type) -> Self {
        match ty {
            Type::Path(typ) => TypeName::from_type_path(typ),
            _ => panic!("Stringifying unknown type, not yet supported"), // TODO
        }
    }

    pub(crate) fn new(id: &str) -> Self {
        let canonical_name = DEADNAME_MAP.get(id);
        if let Some(canonical_name) = canonical_name {
            // This is already a cxx replacement name, e.g. CxxString.
            TypeName(canonical_name.into())
        } else {
            TypeName(id.into())
        }
    }

    pub(crate) fn to_ident(&self) -> Ident {
        Ident::new(&self.0, Span::call_site())
    }

    pub(crate) fn to_cpp_name(&self) -> &str {
        match KNOWN_TYPES.get(&self) {
            None => &self.0,
            Some(replacement) => &replacement.cpp_name.as_str(),
        }
    }

    /// Whether the given function name is prefixed by this type name
    /// and an underscore.
    /// If so, returns the suffix after that point.
    pub(crate) fn prefixes<'a>(&self, func_name: &'a str) -> Option<&'a str> {
        if func_name.starts_with(&self.0) {
            Some(&func_name[self.0.len() + 1..])
        } else {
            None
        }
    }

    fn parse_type_path(p: &TypePath) -> &Ident {
        &p.path.segments.last().unwrap().ident
    }
}

impl Display for TypeName {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str(&self.0)
    }
}

#[derive(Debug)]
enum PreludePolicy {
    Exclude,
    IncludeNormal,
    IncludeTemplated,
}

#[derive(Debug)]
pub(crate) struct TypeDetails {
    /// The name used by cxx for this type.
    cxx_name: String,
    /// C++ equivalent name for a Rust type.
    pub(crate) cpp_name: String,
    /// Whether this can be safely represented by value.
    pub(crate) by_value_safe: bool,
    /// Whether and how to include this in the prelude given to bindgen.
    prelude_policy: PreludePolicy,
}

impl TypeDetails {
    fn new(
        cxx_name: String,
        cpp_name: String,
        by_value_safe: bool,
        prelude_policy: PreludePolicy,
    ) -> Self {
        TypeDetails {
            cxx_name,
            cpp_name,
            by_value_safe,
            prelude_policy,
        }
    }

    fn get_prelude_entry(&self) -> Option<String> {
        match self.prelude_policy {
            PreludePolicy::Exclude => None,
            PreludePolicy::IncludeNormal | PreludePolicy::IncludeTemplated => {
                let proper_cpp_name = &self.cpp_name;
                let cxx_name = &self.cxx_name;
                let (templating, payload) = match self.prelude_policy {
                    PreludePolicy::IncludeNormal => ("", "char* ptr"),
                    PreludePolicy::IncludeTemplated => ("template<typename T> ", "T* ptr"),
                    _ => unreachable!(),
                };
                Some(format!(
                    indoc! {"
                    /**
                    *

                    */
                    {}class {} {{
                        {};
                    }};

                    "},
                    proper_cpp_name, templating, cxx_name, payload
                ))
            }
        }
    }
}

lazy_static! {
    pub(crate) static ref KNOWN_TYPES: HashMap<TypeName, TypeDetails> = {
        let mut map = HashMap::new();
        map.insert(
            TypeName::new("UniquePtr"),
            TypeDetails::new(
                "UniquePtr".into(),
                "std::unique_ptr".into(),
                true,
                PreludePolicy::IncludeTemplated,
            ),
        );
        map.insert(
            TypeName::new("CxxString"),
            TypeDetails::new(
                "CxxString".into(),
                "std::string".into(),
                false,
                PreludePolicy::IncludeNormal,
            ),
        );
        for (cpp_type, rust_type) in (3..7)
            .map(|x| 2i32.pow(x))
            .map(|x| {
                vec![
                    (format!("uint{}_t", x), format!("u{}", x)),
                    (format!("int{}_t", x), format!("i{}", x)),
                ]
            })
            .flatten()
        {
            map.insert(
                TypeName::new(&rust_type),
                TypeDetails::new(rust_type.into(), cpp_type, true, PreludePolicy::Exclude),
            );
        }
        map
    };
}

lazy_static! {
    static ref DEADNAME_MAP: HashMap<String, String> = {
        let mut map = HashMap::new();
        map.insert("std_unique_ptr".into(), "UniquePtr".into());
        map.insert("std_string".into(), "CxxString".into());
        map
    };
}

/// Prelude of C++ for squirting into bindgen. This configures
/// bindgen to output simpler types to replace some STL types
/// that bindgen just can't cope with. Although we then replace
/// those types with cxx types (e.g. UniquePtr), this intermediate
/// step is still necessary because bindgen can't otherwise
/// give us the templated types (e.g. when faced with the STL
/// unique_ptr, bindgen would normally give us std_unique_ptr
/// as opposed to std_unique_ptr<T>.)
pub(crate) fn get_prelude() -> String {
    itertools::join(
        KNOWN_TYPES.values().filter_map(|t| t.get_prelude_entry()),
        "\n",
    )
}

pub(crate) fn to_cpp_name(typ: &Type) -> String {
    match typ {
        Type::Path(ref typ) => TypeName::from_type_path(typ).to_cpp_name().to_string(),
        Type::Reference(ref typr) => {
            let const_bit = match typr.mutability {
                None => "const ",
                Some(_) => "",
            };
            format!(
                "{}{}&",
                const_bit,
                TypeName::from_type(typr.elem.as_ref())
                    .to_cpp_name()
                    .to_string()
            )
        }
        _ => unimplemented!(),
    }
}

#[cfg(test)]
mod tests {
    use crate::TypeName;

    #[test]
    fn test_ints() {
        assert_eq!(TypeName::new("i8").to_cpp_name(), "int8_t");
        assert_eq!(TypeName::new("u64").to_cpp_name(), "uint64_t");
    }
}
<|endoftext|>


<commit_before>use error::SdpParserResult;
use SdpLine;

pub fn parse_repeat(value: &str) -> Result<SdpLine, SdpParserResult> {
    // TODO implement this if it's ever needed
    println!("repeat: {}", value);
    Ok(SdpLine::Repeat{value: String::from(value)})
}

#[test]
fn test_repeat_works() {
    // FIXME use a proper r value here
    assert!(parse_repeat("0 0").is_ok());
}

pub fn parse_zone(value: &str) -> Result<SdpLine, SdpParserResult> {
    // TODO implement this if it's ever needed
    println!("zone: {}", value);
    Ok(SdpLine::Zone {value: String::from(value)})
}

#[test]
fn test_zone_works() {
    // FIXME use a proper z value here
    assert!(parse_zone("0 0").is_ok());
}

pub fn parse_key(value: &str) -> Result<SdpLine, SdpParserResult> {
    // TODO implement this if it's ever needed
    println!("key: {}", value);
    Ok(SdpLine::Key {value: String::from(value)})
}

#[test]
fn test_keys_works() {
    // FIXME use a proper k value here
    assert!(parse_key("12345").is_ok());
}

pub fn parse_information(value: &str) -> Result<SdpLine, SdpParserResult> {
    println!("information: {}", value);
    Ok(SdpLine::Information {value: String::from(value)})
}

#[test]
fn test_information_works() {
    assert!(parse_information("foobar").is_ok());
}

pub fn parse_uri(value: &str) -> Result<SdpLine, SdpParserResult> {
    // TODO check if this is really a URI
    println!("uri: {}", value);
    Ok(SdpLine::Uri {value: String::from(value)})
}

#[test]
fn test_uri_works() {
    assert!(parse_uri("http://www.mozilla.org").is_ok());
}

pub fn parse_email(value: &str) -> Result<SdpLine, SdpParserResult> {
    // TODO check if this is really an email address
    println!("email: {}", value);
    Ok(SdpLine::Email {value: String::from(value)})
}

#[test]
fn test_email_works() {
    assert!(parse_email("nils@mozilla.com").is_ok());
}

pub fn parse_phone(value: &str) -> Result<SdpLine, SdpParserResult> {
    // TODO check if this is really a phone number
    println!("phone: {}", value);
    Ok(SdpLine::Phone {value: String::from(value)})
}

#[test]
fn test_phone_works() {
    assert!(parse_phone("+123456789").is_ok());
}

<commit_msg>rust formated<commit_after>use error::SdpParserResult;
use SdpLine;

pub fn parse_repeat(value: &str) -> Result<SdpLine, SdpParserResult> {
    // TODO implement this if it's ever needed
    println!("repeat: {}", value);
    Ok(SdpLine::Repeat { value: String::from(value) })
}

#[test]
fn test_repeat_works() {
    // FIXME use a proper r value here
    assert!(parse_repeat("0 0").is_ok());
}

pub fn parse_zone(value: &str) -> Result<SdpLine, SdpParserResult> {
    // TODO implement this if it's ever needed
    println!("zone: {}", value);
    Ok(SdpLine::Zone { value: String::from(value) })
}

#[test]
fn test_zone_works() {
    // FIXME use a proper z value here
    assert!(parse_zone("0 0").is_ok());
}

pub fn parse_key(value: &str) -> Result<SdpLine, SdpParserResult> {
    // TODO implement this if it's ever needed
    println!("key: {}", value);
    Ok(SdpLine::Key { value: String::from(value) })
}

#[test]
fn test_keys_works() {
    // FIXME use a proper k value here
    assert!(parse_key("12345").is_ok());
}

pub fn parse_information(value: &str) -> Result<SdpLine, SdpParserResult> {
    println!("information: {}", value);
    Ok(SdpLine::Information { value: String::from(value) })
}

#[test]
fn test_information_works() {
    assert!(parse_information("foobar").is_ok());
}

pub fn parse_uri(value: &str) -> Result<SdpLine, SdpParserResult> {
    // TODO check if this is really a URI
    println!("uri: {}", value);
    Ok(SdpLine::Uri { value: String::from(value) })
}

#[test]
fn test_uri_works() {
    assert!(parse_uri("http://www.mozilla.org").is_ok());
}

pub fn parse_email(value: &str) -> Result<SdpLine, SdpParserResult> {
    // TODO check if this is really an email address
    println!("email: {}", value);
    Ok(SdpLine::Email { value: String::from(value) })
}

#[test]
fn test_email_works() {
    assert!(parse_email("nils@mozilla.com").is_ok());
}

pub fn parse_phone(value: &str) -> Result<SdpLine, SdpParserResult> {
    // TODO check if this is really a phone number
    println!("phone: {}", value);
    Ok(SdpLine::Phone { value: String::from(value) })
}

#[test]
fn test_phone_works() {
    assert!(parse_phone("+123456789").is_ok());
}
<|endoftext|>