<commit_before>use std::collections::VecDeque;

#[derive(Debug)]
struct Node {
    children: Vec<Node>,
    value: u64,
}

fn dfs_recursive(n: &Node) {
    println!("{}", n.value);

    for child in &n.children {
        dfs_recursive(child);
    }
}

fn dfs_recursive_postorder(n: &Node) {
    for child in &n.children {
        dfs_recursive(child);
    }

    println!("{}", n.value);
}

fn dfs_stack(n: &Node) {
    let mut stack = vec![n];

    while let Some(current) = stack.pop() {
        println!("{}", current.value);
        stack.extend(&current.children);
    }
}

fn bfs_queue(n: &Node){
    let mut queue = VecDeque::new();
    queue.push_back(n);

    while let Some(current) = queue.pop_front() {
        println!("{}", current.value);
        queue.extend(&current.children);
    }
}

fn create_tree(num_row: u64, num_child: u64) -> Node {
    if num_row == 0 {
        return Node { children: vec![], value: 0 };
    }

    let children = (0..num_child)
        .map(|_| create_tree(num_row - 1, num_child))
        .collect();

    Node { children, value: num_row }
}

fn main() {
    let root = create_tree(3,3);
    println!("Recursive DFS:");
    dfs_recursive(&root);
    println!("Stack DFS:");
    dfs_stack(&root);
    println!("Queue BFS:");
    bfs_queue(&root);
}
<commit_msg>Adding dfs_recursive_inorder_btree to rust<commit_after>use std::collections::VecDeque;

#[derive(Debug)]
struct Node {
    children: Vec<Node>,
    value: u64,
}

fn dfs_recursive(n: &Node) {
    println!("{}", n.value);

    for child in &n.children {
        dfs_recursive(child);
    }
}

fn dfs_recursive_postorder(n: &Node) {
    for child in &n.children {
        dfs_recursive(child);
    }

    println!("{}", n.value);
}

fn dfs_recursive_inorder_btree(n: &Node) {
    if n.children.len() == 2{
        dfs_recursive_inorder_btree(&n.children[1]);
        println!("{}", n.value);
        dfs_recursive_inorder_btree(&n.children[0]);
    } else if n.children.len() == 1 {
        dfs_recursive_inorder_btree(&n.children[0]);
        println!("{}", n.value);
    } else if n.children.len() == 0 {
        println!("{}", n.value);
    } else {
        println!("This is not a binary tree.");
    }
}

fn dfs_stack(n: &Node) {
    let mut stack = vec![n];

    while let Some(current) = stack.pop() {
        println!("{}", current.value);
        stack.extend(&current.children);
    }
}

fn bfs_queue(n: &Node){
    let mut queue = VecDeque::new();
    queue.push_back(n);

    while let Some(current) = queue.pop_front() {
        println!("{}", current.value);
        queue.extend(&current.children);
    }
}

fn create_tree(num_row: u64, num_child: u64) -> Node {
    if num_row == 0 {
        return Node { children: vec![], value: 0 };
    }

    let children = (0..num_child)
        .map(|_| create_tree(num_row - 1, num_child))
        .collect();

    Node { children, value: num_row }
}

fn main() {
    let root = create_tree(3,2);
    println!("Recursive DFS:");
    dfs_recursive(&root);
    println!("Stack DFS:");
    dfs_stack(&root);
    println!("Queue BFS:");
    bfs_queue(&root);
    println!("Recursive PostOrder DFS: ");
    dfs_recursive_postorder(&root);
    println!("Recursive DFS BTree:");
    dfs_recursive_inorder_btree(&root);
}
<|endoftext|>


<commit_before>extern crate core_compat;

use std::path::Path;

use core_compat::DataManager;
use core_compat::MapManager;
use core_compat::SpriteManager;
use core_compat::{ListManager, ListType};
use core_compat::entity::rmd_type::RmdType;
use core_compat::entity::sprite_type::SpriteType;

#[test]
fn test_map_sprite_load_map00001() {
    // setup needed paths
    let data_path = Path::new("../data/DATAs/");
    let map_path = Path::new("../data/DATAs/Map/");
    let sprite_path = Path::new("../data/RLEs/");
    // setup the managers;
    let mut map_manager = MapManager::new(&map_path);
    let mut data_manager = DataManager::new(&data_path);
    let mut sprite_manager = SpriteManager::new(&sprite_path);
    let list_manager = ListManager::new(sprite_path).unwrap();
    // load the map files
    map_manager.load_map(1).unwrap();
    let map = map_manager.get_map(1).unwrap();
    // check map data
    assert_eq!(map.number(), 1);
    assert_eq!((map.size_x() * map.size_y()) as usize, map.tiles().len());
    // load the data files for each tile
    let obj_list = list_manager.get_list(ListType::Object).unwrap();
    let tle_list = list_manager.get_list(ListType::Tile).unwrap();
    for map_tile in map.tiles().iter() {
        // load references to the data files
        // -- map tile objects
        let obj_entry = map_tile.obj_rmd_entry;
        if obj_entry.file() != 0 {
            let file = obj_entry.file() as usize;
            let index = obj_entry.index() as usize;
            let rmd = data_manager.get_data(RmdType::Object, file).unwrap();
            let entry = rmd.get_entry(index).unwrap();
            println!("Obj entry file: {}", file);
            for img in entry.images() {
                for id in img.get_image_id_list().iter() {
                    println!("\tLooking for obj list item: {}", id);
                    let item = obj_list.get_item(*id as usize).unwrap();
                    // load the RLE's pointed to by the list item
                    let sprite = sprite_manager.get_sprite(item.entry, SpriteType::Object).unwrap();
                }
            }
        }
        // -- map tile sprites
        let tle_entry = map_tile.tle_rmd_entry;
        if tle_entry.file() != 0 {
            let file = tle_entry.file() as usize;
            let index = tle_entry.index() as usize;
            let rmd = data_manager.get_data(RmdType::Tile, file).unwrap();
            let entry = rmd.get_entry(index).unwrap();
            assert!(entry.image_count() > 0);
        }
    }
    assert!(false);
}
<commit_msg>Load tile sprites in test<commit_after>extern crate core_compat;

use std::path::Path;

use core_compat::DataManager;
use core_compat::MapManager;
use core_compat::SpriteManager;
use core_compat::{ListManager, ListType};
use core_compat::entity::rmd_type::RmdType;
use core_compat::entity::sprite_type::SpriteType;

#[test]
fn test_map_sprite_load_map00001() {
    // setup needed paths
    let data_path = Path::new("../data/DATAs/");
    let map_path = Path::new("../data/DATAs/Map/");
    let sprite_path = Path::new("../data/RLEs/");
    // setup the managers;
    let mut map_manager = MapManager::new(&map_path);
    let mut data_manager = DataManager::new(&data_path);
    let mut sprite_manager = SpriteManager::new(&sprite_path);
    let list_manager = ListManager::new(sprite_path).unwrap();
    // load the map files
    map_manager.load_map(1).unwrap();
    let map = map_manager.get_map(1).unwrap();
    // check map data
    assert_eq!(map.number(), 1);
    assert_eq!((map.size_x() * map.size_y()) as usize, map.tiles().len());
    // load the data files for each tile
    let obj_list = list_manager.get_list(ListType::Object).unwrap();
    let tle_list = list_manager.get_list(ListType::Tile).unwrap();
    for map_tile in map.tiles().iter() {
        // load references to the data files
        // -- map tile objects
        let obj_entry = map_tile.obj_rmd_entry;
        if obj_entry.file() != 0 {
            let file = obj_entry.file() as usize;
            let index = obj_entry.index() as usize;
            let rmd = data_manager.get_data(RmdType::Object, file).unwrap();
            let entry = rmd.get_entry(index).unwrap();
            println!("Obj entry file: {}", file);
            for img in entry.images() {
                for id in img.get_image_id_list().iter() {
                    println!("\tLooking for obj list item: {}", id);
                    let item = obj_list.get_item(*id as usize).unwrap();
                    // load the RLE's pointed to by the list item
                    let sprite = sprite_manager.get_sprite(item.entry, SpriteType::Object).unwrap();
                }
            }
        }
        // -- map tile sprites
        let tle_entry = map_tile.tle_rmd_entry;
        if tle_entry.file() != 0 {
            let file = tle_entry.file() as usize;
            let index = tle_entry.index() as usize;
            let rmd = data_manager.get_data(RmdType::Tile, file).unwrap();
            let entry = rmd.get_entry(index).unwrap();
            println!("Tle entry file: {}", file);
            for img in entry.images() {
                for id in img.get_image_id_list().iter() {
                    println!("\tLooking for tle list item: {}", id);
                    let item = tle_list.get_item(*id as usize).unwrap();
                    // load the RLE's pointed to by the list item
                    let sprite = sprite_manager.get_sprite(item.entry, SpriteType::Tile).unwrap();
                }
            }
        }
    }
    assert!(false);
}
<|endoftext|>


<commit_before>use js::value::{Value, VNumber, VInteger, VFunction, VObject, ResultValue};
use js::function::{NativeFunction, NativeFunc};
use js::object::ObjectData;
use collections::treemap::TreeMap;
use rand::random;
use std::io::stdio;
use std::f64;
use std::gc::Gc;
use std::cell::RefCell;

/// Get the absolute value of a number
pub fn abs(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().abs()
	} else {
		f64::NAN
	})))
}
/// Get the arccos of a number
pub fn acos(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().acos()
	} else {
		f64::NAN
	})))
}
/// Get the arcsine of a number
pub fn asin(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().asin()
	} else {
		f64::NAN
	})))
}
/// Get the arctangent of a number
pub fn atan(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().atan()
	} else {
		f64::NAN
	})))
}
/// Get the arctangent of a numbers
pub fn atan2(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().atan2(&args.get(1).borrow().to_num())
	} else {
		f64::NAN
	})))
}
/// Get the cubic root of a number
pub fn cbrt(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().cbrt()
	} else {
		f64::NAN
	})))
}
/// Get lowest integer above a number
pub fn ceil(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().ceil()
	} else {
		f64::NAN
	})))
}
/// Get the cosine of a number
pub fn cos(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().cos()
	} else {
		f64::NAN
	})))
}
/// Get the power to raise the natural logarithm to get the number
pub fn exp(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().exp()
	} else {
		f64::NAN
	})))
}
/// Get the highest integer below a number
pub fn floor(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().floor()
	} else {
		f64::NAN
	})))
}
/// Get the natural logarithm of a number
pub fn log(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().log(&f64::consts::E)
	} else {
		f64::NAN
	})))
}
/// Generate a random floating-point number between 0 and 1
pub fn _random(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(random())))
}
/// Get the sine of a number
pub fn sin(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().sin()
	} else {
		f64::NAN
	})))
}
/// Get the tangent of a number
pub fn tan(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().tan()
	} else {
		f64::NAN
	})))
}
/// Create a new 'Math' object
pub fn _create() -> Value {
	let mut math = TreeMap::new();
	math.insert(~"E", Gc::new(VNumber(f64::consts::E)));
	math.insert(~"LN2", Gc::new(VNumber(f64::consts::LN_2)));
	math.insert(~"LN10", Gc::new(VNumber(f64::consts::LN_10)));
	math.insert(~"LOG2E", Gc::new(VNumber(f64::consts::LOG2_E)));
	math.insert(~"LOG10E", Gc::new(VNumber(f64::consts::LOG10_E)));
	math.insert(~"SQRT1_2", Gc::new(VNumber(0.5f64.sqrt())));
	math.insert(~"SQRT2", Gc::new(VNumber(f64::consts::SQRT2)));
	math.insert(~"PI", Gc::new(VNumber(f64::consts::PI)));
	math.insert(~"abs", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(abs, 1))))));
	math.insert(~"acos", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(acos, 1))))));
	math.insert(~"asin", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(asin, 1))))));
	math.insert(~"atan", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(atan, 1))))));
	math.insert(~"atan2", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(atan2, 2))))));
	math.insert(~"cbrt", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(cbrt, 1))))));
	math.insert(~"ceil", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(ceil, 1))))));
	math.insert(~"cos", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(cos, 1))))));
	math.insert(~"exp", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(exp, 1))))));
	math.insert(~"floor", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(floor, 1))))));
	math.insert(~"log", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(log, 1))))));
	math.insert(~"random", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(_random, 0))))));
	math.insert(~"sin", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(sin, 1))))));
	math.insert(~"tan", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(tan, 1))))));
	Gc::new(VObject(RefCell::new(math)))
}<commit_msg>Add Math.max(a, b, ...c)<commit_after>use js::value::{Value, VNumber, VInteger, VFunction, VObject, ResultValue};
use js::function::{NativeFunction, NativeFunc};
use js::object::ObjectData;
use collections::treemap::TreeMap;
use rand::random;
use std::io::stdio;
use std::f64;
use std::gc::Gc;
use std::cell::RefCell;

/// Get the absolute value of a number
pub fn abs(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().abs()
	} else {
		f64::NAN
	})))
}
/// Get the arccos of a number
pub fn acos(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().acos()
	} else {
		f64::NAN
	})))
}
/// Get the arcsine of a number
pub fn asin(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().asin()
	} else {
		f64::NAN
	})))
}
/// Get the arctangent of a number
pub fn atan(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().atan()
	} else {
		f64::NAN
	})))
}
/// Get the arctangent of a numbers
pub fn atan2(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().atan2(&args.get(1).borrow().to_num())
	} else {
		f64::NAN
	})))
}
/// Get the cubic root of a number
pub fn cbrt(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().cbrt()
	} else {
		f64::NAN
	})))
}
/// Get lowest integer above a number
pub fn ceil(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().ceil()
	} else {
		f64::NAN
	})))
}
/// Get the cosine of a number
pub fn cos(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().cos()
	} else {
		f64::NAN
	})))
}
/// Get the power to raise the natural logarithm to get the number
pub fn exp(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().exp()
	} else {
		f64::NAN
	})))
}
/// Get the highest integer below a number
pub fn floor(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().floor()
	} else {
		f64::NAN
	})))
}
/// Get the natural logarithm of a number
pub fn log(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().log(&f64::consts::E)
	} else {
		f64::NAN
	})))
}
/// Get the maximum of several numbers
pub fn max(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	let mut max = f64::NEG_INFINITY;
	for arg in args.iter() {
		let num = arg.borrow().to_num();
		max = max.max(num);
	}
	Ok(Gc::new(VNumber(max)))
}
/// Generate a random floating-point number between 0 and 1
pub fn _random(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(random())))
}
/// Get the sine of a number
pub fn sin(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().sin()
	} else {
		f64::NAN
	})))
}
/// Get the tangent of a number
pub fn tan(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	Ok(Gc::new(VNumber(if args.len() >= 1 {
		args.get(0).borrow().to_num().tan()
	} else {
		f64::NAN
	})))
}
/// Create a new 'Math' object
pub fn _create() -> Value {
	let mut math = TreeMap::new();
	math.insert(~"E", Gc::new(VNumber(f64::consts::E)));
	math.insert(~"LN2", Gc::new(VNumber(f64::consts::LN_2)));
	math.insert(~"LN10", Gc::new(VNumber(f64::consts::LN_10)));
	math.insert(~"LOG2E", Gc::new(VNumber(f64::consts::LOG2_E)));
	math.insert(~"LOG10E", Gc::new(VNumber(f64::consts::LOG10_E)));
	math.insert(~"SQRT1_2", Gc::new(VNumber(0.5f64.sqrt())));
	math.insert(~"SQRT2", Gc::new(VNumber(f64::consts::SQRT2)));
	math.insert(~"PI", Gc::new(VNumber(f64::consts::PI)));
	math.insert(~"abs", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(abs, 1))))));
	math.insert(~"acos", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(acos, 1))))));
	math.insert(~"asin", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(asin, 1))))));
	math.insert(~"atan", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(atan, 1))))));
	math.insert(~"atan2", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(atan2, 2))))));
	math.insert(~"cbrt", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(cbrt, 1))))));
	math.insert(~"ceil", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(ceil, 1))))));
	math.insert(~"cos", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(cos, 1))))));
	math.insert(~"exp", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(exp, 1))))));
	math.insert(~"floor", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(floor, 1))))));
	math.insert(~"log", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(log, 1))))));
	math.insert(~"max", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(max, 2))))));
	math.insert(~"random", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(_random, 0))))));
	math.insert(~"sin", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(sin, 1))))));
	math.insert(~"tan", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(tan, 1))))));
	Gc::new(VObject(RefCell::new(math)))
}<|endoftext|>


<commit_before>use hir::{Adt, ModuleDef, Struct};
use ide_db::defs::{Definition, NameRefClass};
use syntax::{
    ast::{self, AstNode, GenericParamsOwner, VisibilityOwner},
    match_ast,
};

use crate::{assist_context::AssistBuilder, AssistContext, AssistId, AssistKind, Assists};

// Assist: convert_tuple_struct_to_named_struct
//
// Converts tuple struct to struct with named fields.
//
// ```
// struct Point$0(f32, f32);
//
// impl Point {
//     pub fn new(x: f32, y: f32) -> Self {
//         Point(x, y)
//     }
//
//     pub fn x(&self) -> f32 {
//         self.0
//     }
//
//     pub fn y(&self) -> f32 {
//         self.1
//     }
// }
// ```
// ->
// ```
// struct Point { field1: f32, field2: f32 }
//
// impl Point {
//     pub fn new(x: f32, y: f32) -> Self {
//         Point { field1: x, field2: y }
//     }
//
//     pub fn x(&self) -> f32 {
//         self.field1
//     }
//
//     pub fn y(&self) -> f32 {
//         self.field2
//     }
// }
// ```
pub(crate) fn convert_tuple_struct_to_named_struct(
    acc: &mut Assists,
    ctx: &AssistContext,
) -> Option<()> {
    let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
    let tuple_fields = match strukt.field_list()? {
        ast::FieldList::TupleFieldList(it) => it,
        ast::FieldList::RecordFieldList(_) => return None,
    };
    let strukt_def = ctx.sema.to_def(&strukt)?;

    let target = strukt.syntax().text_range();
    acc.add(
        AssistId("convert_tuple_struct_to_named_struct", AssistKind::RefactorRewrite),
        "Convert to named struct",
        target,
        |edit| {
            let names = generate_names(tuple_fields.fields());
            edit_field_references(ctx, edit, tuple_fields.fields(), &names);
            edit_struct_references(ctx, edit, strukt_def, &names);
            edit_struct_def(ctx, edit, &strukt, tuple_fields, names);
        },
    )
}

fn edit_struct_def(
    ctx: &AssistContext,
    edit: &mut AssistBuilder,
    strukt: &ast::Struct,
    tuple_fields: ast::TupleFieldList,
    names: Vec<ast::Name>,
) {
    let record_fields = tuple_fields
        .fields()
        .zip(names)
        .filter_map(|(f, name)| Some(ast::make::record_field(f.visibility(), name, f.ty()?)));
    let record_fields = ast::make::record_field_list(record_fields);
    let tuple_fields_text_range = tuple_fields.syntax().text_range();

    edit.edit_file(ctx.frange.file_id);

    if let Some(w) = strukt.where_clause() {
        edit.delete(w.syntax().text_range());
        edit.insert(tuple_fields_text_range.start(), ast::make::tokens::single_newline().text());
        edit.insert(tuple_fields_text_range.start(), w.syntax().text());
        edit.insert(tuple_fields_text_range.start(), ",");
        edit.insert(tuple_fields_text_range.start(), ast::make::tokens::single_newline().text());
    } else {
        edit.insert(tuple_fields_text_range.start(), ast::make::tokens::single_space().text());
    }

    edit.replace(tuple_fields_text_range, record_fields.to_string());
    strukt.semicolon_token().map(|t| edit.delete(t.text_range()));
}

fn edit_struct_references(
    ctx: &AssistContext,
    edit: &mut AssistBuilder,
    strukt: Struct,
    names: &[ast::Name],
) {
    let strukt_def = Definition::ModuleDef(ModuleDef::Adt(Adt::Struct(strukt)));
    let usages = strukt_def.usages(&ctx.sema).include_self_kw_refs(true).all();

    for (file_id, refs) in usages {
        edit.edit_file(file_id);
        for r in refs {
            for node in r.name.syntax().ancestors() {
                match_ast! {
                    match node {
                        ast::TupleStructPat(tuple_struct_pat) => {
                            let path = match tuple_struct_pat.path() {
                                Some(it) => it,
                                None => continue,
                            };

                            edit.replace(
                                tuple_struct_pat.syntax().text_range(),
                                ast::make::record_pat_with_fields(
                                    path,
                                    ast::make::record_pat_field_list(tuple_struct_pat.fields().zip(names).map(
                                        |(pat, name)| {
                                            ast::make::record_pat_field(
                                                ast::make::name_ref(&name.to_string()),
                                                pat,
                                            )
                                        },
                                    )),
                                )
                                .to_string(),
                            );
                        },
                        // for tuple struct creations like Foo(42)
                        ast::CallExpr(call_expr) => {
                            let path = match call_expr.syntax().descendants().find_map(ast::PathExpr::cast).map(|expr| expr.path()) {
                                Some(Some(it)) => it,
                                _ => continue,
                            };

                            // this also includes method calls like Foo::new(42), we should skip them
                            if let Some(Some(name_ref)) = path.segment().map(|s| s.name_ref()) {
                                match NameRefClass::classify(&ctx.sema, &name_ref) {
                                    Some(NameRefClass::Definition(Definition::SelfType(_))) => {},
                                    Some(NameRefClass::Definition(def)) if def == strukt_def => {},
                                    _ => continue,
                                };
                            }

                            let arg_list = match call_expr.syntax().descendants().find_map(ast::ArgList::cast) {
                                Some(it) => it,
                                None => continue,
                            };

                            edit.replace(
                                call_expr.syntax().text_range(),
                                ast::make::record_expr(
                                    path,
                                    ast::make::record_expr_field_list(arg_list.args().zip(names).map(
                                        |(expr, name)| {
                                            ast::make::record_expr_field(
                                                ast::make::name_ref(&name.to_string()),
                                                Some(expr),
                                            )
                                        },
                                    )),
                                )
                                .to_string(),
                            );
                        },
                        _ => ()
                    }
                }
            }
        }
    }
}

fn edit_field_references(
    ctx: &AssistContext,
    edit: &mut AssistBuilder,
    fields: impl Iterator<Item = ast::TupleField>,
    names: &[ast::Name],
) {
    for (field, name) in fields.zip(names) {
        let field = match ctx.sema.to_def(&field) {
            Some(it) => it,
            None => continue,
        };
        let def = Definition::Field(field);
        let usages = def.usages(&ctx.sema).all();
        for (file_id, refs) in usages {
            edit.edit_file(file_id);
            for r in refs {
                if let Some(name_ref) = r.name.as_name_ref() {
                    edit.replace(name_ref.syntax().text_range(), name.text());
                }
            }
        }
    }
}

fn generate_names(fields: impl Iterator<Item = ast::TupleField>) -> Vec<ast::Name> {
    fields.enumerate().map(|(i, _)| ast::make::name(&format!("field{}", i + 1))).collect()
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn not_applicable_other_than_tuple_struct() {
        check_assist_not_applicable(
            convert_tuple_struct_to_named_struct,
            r#"struct Foo$0 { bar: u32 };"#,
        );
        check_assist_not_applicable(convert_tuple_struct_to_named_struct, r#"struct Foo$0;"#);
    }

    #[test]
    fn convert_simple_struct() {
        check_assist(
            convert_tuple_struct_to_named_struct,
            r#"
struct Inner;
struct A$0(Inner);

impl A {
    fn new(inner: Inner) -> A {
        A(inner)
    }

    fn new_with_default() -> A {
        A::new(Inner)
    }

    fn into_inner(self) -> Inner {
        self.0
    }
}"#,
            r#"
struct Inner;
struct A { field1: Inner }

impl A {
    fn new(inner: Inner) -> A {
        A { field1: inner }
    }

    fn new_with_default() -> A {
        A::new(Inner)
    }

    fn into_inner(self) -> Inner {
        self.field1
    }
}"#,
        );
    }

    #[test]
    fn convert_struct_referenced_via_self_kw() {
        check_assist(
            convert_tuple_struct_to_named_struct,
            r#"
struct Inner;
struct A$0(Inner);

impl A {
    fn new(inner: Inner) -> Self {
        Self(inner)
    }

    fn new_with_default() -> Self {
        Self::new(Inner)
    }

    fn into_inner(self) -> Inner {
        self.0
    }
}"#,
            r#"
struct Inner;
struct A { field1: Inner }

impl A {
    fn new(inner: Inner) -> Self {
        Self { field1: inner }
    }

    fn new_with_default() -> Self {
        Self::new(Inner)
    }

    fn into_inner(self) -> Inner {
        self.field1
    }
}"#,
        );
    }

    #[test]
    fn convert_destructured_struct() {
        check_assist(
            convert_tuple_struct_to_named_struct,
            r#"
struct Inner;
struct A$0(Inner);

impl A {
    fn into_inner(self) -> Inner {
        let A(first) = self;
        first
    }

    fn into_inner_via_self(self) -> Inner {
        let Self(first) = self;
        first
    }
}"#,
            r#"
struct Inner;
struct A { field1: Inner }

impl A {
    fn into_inner(self) -> Inner {
        let A { field1: first } = self;
        first
    }

    fn into_inner_via_self(self) -> Inner {
        let Self { field1: first } = self;
        first
    }
}"#,
        );
    }

    #[test]
    fn convert_struct_with_visibility() {
        check_assist(
            convert_tuple_struct_to_named_struct,
            r#"
struct A$0(pub u32, pub(crate) u64);

impl A {
    fn new() -> A {
        A(42, 42)
    }

    fn into_first(self) -> u32 {
        self.0
    }

    fn into_second(self) -> u64 {
        self.1
    }
}"#,
            r#"
struct A { pub field1: u32, pub(crate) field2: u64 }

impl A {
    fn new() -> A {
        A { field1: 42, field2: 42 }
    }

    fn into_first(self) -> u32 {
        self.field1
    }

    fn into_second(self) -> u64 {
        self.field2
    }
}"#,
        );
    }

    #[test]
    fn convert_struct_with_multi_file_references() {
        check_assist(
            convert_tuple_struct_to_named_struct,
            r#"
//- /main.rs
struct Inner;
struct A$0(Inner);

mod foo;

//- /foo.rs
use crate::{A, Inner};
fn f() {
    let a = A(Inner);
}
"#,
            r#"
//- /main.rs
struct Inner;
struct A { field1: Inner }

mod foo;

//- /foo.rs
use crate::{A, Inner};
fn f() {
    let a = A { field1: Inner };
}
"#,
        );
    }

    #[test]
    fn convert_struct_with_where_clause() {
        check_assist(
            convert_tuple_struct_to_named_struct,
            r#"
struct Wrap$0<T>(T)
where
    T: Display;
"#,
            r#"
struct Wrap<T>
where
    T: Display,
{ field1: T }

"#,
        );
    }
}
<commit_msg>Move reference editing logic into own function to make error handling more ease in "Convert to named struct" assist<commit_after>use ide_db::defs::{Definition, NameRefClass};
use syntax::{
    ast::{self, AstNode, GenericParamsOwner, VisibilityOwner},
    match_ast, SyntaxNode,
};

use crate::{assist_context::AssistBuilder, AssistContext, AssistId, AssistKind, Assists};

// Assist: convert_tuple_struct_to_named_struct
//
// Converts tuple struct to struct with named fields.
//
// ```
// struct Point$0(f32, f32);
//
// impl Point {
//     pub fn new(x: f32, y: f32) -> Self {
//         Point(x, y)
//     }
//
//     pub fn x(&self) -> f32 {
//         self.0
//     }
//
//     pub fn y(&self) -> f32 {
//         self.1
//     }
// }
// ```
// ->
// ```
// struct Point { field1: f32, field2: f32 }
//
// impl Point {
//     pub fn new(x: f32, y: f32) -> Self {
//         Point { field1: x, field2: y }
//     }
//
//     pub fn x(&self) -> f32 {
//         self.field1
//     }
//
//     pub fn y(&self) -> f32 {
//         self.field2
//     }
// }
// ```
pub(crate) fn convert_tuple_struct_to_named_struct(
    acc: &mut Assists,
    ctx: &AssistContext,
) -> Option<()> {
    let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
    let tuple_fields = match strukt.field_list()? {
        ast::FieldList::TupleFieldList(it) => it,
        ast::FieldList::RecordFieldList(_) => return None,
    };
    let strukt_def = ctx.sema.to_def(&strukt)?;

    let target = strukt.syntax().text_range();
    acc.add(
        AssistId("convert_tuple_struct_to_named_struct", AssistKind::RefactorRewrite),
        "Convert to named struct",
        target,
        |edit| {
            let names = generate_names(tuple_fields.fields());
            edit_field_references(ctx, edit, tuple_fields.fields(), &names);
            edit_struct_references(ctx, edit, strukt_def, &names);
            edit_struct_def(ctx, edit, &strukt, tuple_fields, names);
        },
    )
}

fn edit_struct_def(
    ctx: &AssistContext,
    edit: &mut AssistBuilder,
    strukt: &ast::Struct,
    tuple_fields: ast::TupleFieldList,
    names: Vec<ast::Name>,
) {
    let record_fields = tuple_fields
        .fields()
        .zip(names)
        .filter_map(|(f, name)| Some(ast::make::record_field(f.visibility(), name, f.ty()?)));
    let record_fields = ast::make::record_field_list(record_fields);
    let tuple_fields_text_range = tuple_fields.syntax().text_range();

    edit.edit_file(ctx.frange.file_id);

    if let Some(w) = strukt.where_clause() {
        edit.delete(w.syntax().text_range());
        edit.insert(tuple_fields_text_range.start(), ast::make::tokens::single_newline().text());
        edit.insert(tuple_fields_text_range.start(), w.syntax().text());
        edit.insert(tuple_fields_text_range.start(), ",");
        edit.insert(tuple_fields_text_range.start(), ast::make::tokens::single_newline().text());
    } else {
        edit.insert(tuple_fields_text_range.start(), ast::make::tokens::single_space().text());
    }

    edit.replace(tuple_fields_text_range, record_fields.to_string());
    strukt.semicolon_token().map(|t| edit.delete(t.text_range()));
}

fn edit_struct_references(
    ctx: &AssistContext,
    edit: &mut AssistBuilder,
    strukt: hir::Struct,
    names: &[ast::Name],
) {
    let strukt_def = Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(strukt)));
    let usages = strukt_def.usages(&ctx.sema).include_self_kw_refs(true).all();

    let edit_node = |edit: &mut AssistBuilder, node: SyntaxNode| -> Option<()> {
        match_ast! {
            match node {
                ast::TupleStructPat(tuple_struct_pat) => {
                    edit.replace(
                        tuple_struct_pat.syntax().text_range(),
                        ast::make::record_pat_with_fields(
                            tuple_struct_pat.path()?,
                            ast::make::record_pat_field_list(tuple_struct_pat.fields().zip(names).map(
                                |(pat, name)| {
                                    ast::make::record_pat_field(
                                        ast::make::name_ref(&name.to_string()),
                                        pat,
                                    )
                                },
                            )),
                        )
                        .to_string(),
                    );
                },
                // for tuple struct creations like Foo(42)
                ast::CallExpr(call_expr) => {
                    let path = call_expr.syntax().descendants().find_map(ast::PathExpr::cast).and_then(|expr| expr.path())?;

                    // this also includes method calls like Foo::new(42), we should skip them
                    if let Some(name_ref) = path.segment().and_then(|s| s.name_ref()) {
                        match NameRefClass::classify(&ctx.sema, &name_ref) {
                            Some(NameRefClass::Definition(Definition::SelfType(_))) => {},
                            Some(NameRefClass::Definition(def)) if def == strukt_def => {},
                            _ => return None,
                        };
                    }

                    let arg_list = call_expr.syntax().descendants().find_map(ast::ArgList::cast)?;

                    edit.replace(
                        call_expr.syntax().text_range(),
                        ast::make::record_expr(
                            path,
                            ast::make::record_expr_field_list(arg_list.args().zip(names).map(
                                |(expr, name)| {
                                    ast::make::record_expr_field(
                                        ast::make::name_ref(&name.to_string()),
                                        Some(expr),
                                    )
                                },
                            )),
                        )
                        .to_string(),
                    );
                },
                _ => ()
            }
        }
        Some(())
    };

    for (file_id, refs) in usages {
        edit.edit_file(file_id);
        for r in refs {
            for node in r.name.syntax().ancestors() {
                edit_node(edit, node);
            }
        }
    }
}

fn edit_field_references(
    ctx: &AssistContext,
    edit: &mut AssistBuilder,
    fields: impl Iterator<Item = ast::TupleField>,
    names: &[ast::Name],
) {
    for (field, name) in fields.zip(names) {
        let field = match ctx.sema.to_def(&field) {
            Some(it) => it,
            None => continue,
        };
        let def = Definition::Field(field);
        let usages = def.usages(&ctx.sema).all();
        for (file_id, refs) in usages {
            edit.edit_file(file_id);
            for r in refs {
                if let Some(name_ref) = r.name.as_name_ref() {
                    edit.replace(name_ref.syntax().text_range(), name.text());
                }
            }
        }
    }
}

fn generate_names(fields: impl Iterator<Item = ast::TupleField>) -> Vec<ast::Name> {
    fields.enumerate().map(|(i, _)| ast::make::name(&format!("field{}", i + 1))).collect()
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn not_applicable_other_than_tuple_struct() {
        check_assist_not_applicable(
            convert_tuple_struct_to_named_struct,
            r#"struct Foo$0 { bar: u32 };"#,
        );
        check_assist_not_applicable(convert_tuple_struct_to_named_struct, r#"struct Foo$0;"#);
    }

    #[test]
    fn convert_simple_struct() {
        check_assist(
            convert_tuple_struct_to_named_struct,
            r#"
struct Inner;
struct A$0(Inner);

impl A {
    fn new(inner: Inner) -> A {
        A(inner)
    }

    fn new_with_default() -> A {
        A::new(Inner)
    }

    fn into_inner(self) -> Inner {
        self.0
    }
}"#,
            r#"
struct Inner;
struct A { field1: Inner }

impl A {
    fn new(inner: Inner) -> A {
        A { field1: inner }
    }

    fn new_with_default() -> A {
        A::new(Inner)
    }

    fn into_inner(self) -> Inner {
        self.field1
    }
}"#,
        );
    }

    #[test]
    fn convert_struct_referenced_via_self_kw() {
        check_assist(
            convert_tuple_struct_to_named_struct,
            r#"
struct Inner;
struct A$0(Inner);

impl A {
    fn new(inner: Inner) -> Self {
        Self(inner)
    }

    fn new_with_default() -> Self {
        Self::new(Inner)
    }

    fn into_inner(self) -> Inner {
        self.0
    }
}"#,
            r#"
struct Inner;
struct A { field1: Inner }

impl A {
    fn new(inner: Inner) -> Self {
        Self { field1: inner }
    }

    fn new_with_default() -> Self {
        Self::new(Inner)
    }

    fn into_inner(self) -> Inner {
        self.field1
    }
}"#,
        );
    }

    #[test]
    fn convert_destructured_struct() {
        check_assist(
            convert_tuple_struct_to_named_struct,
            r#"
struct Inner;
struct A$0(Inner);

impl A {
    fn into_inner(self) -> Inner {
        let A(first) = self;
        first
    }

    fn into_inner_via_self(self) -> Inner {
        let Self(first) = self;
        first
    }
}"#,
            r#"
struct Inner;
struct A { field1: Inner }

impl A {
    fn into_inner(self) -> Inner {
        let A { field1: first } = self;
        first
    }

    fn into_inner_via_self(self) -> Inner {
        let Self { field1: first } = self;
        first
    }
}"#,
        );
    }

    #[test]
    fn convert_struct_with_visibility() {
        check_assist(
            convert_tuple_struct_to_named_struct,
            r#"
struct A$0(pub u32, pub(crate) u64);

impl A {
    fn new() -> A {
        A(42, 42)
    }

    fn into_first(self) -> u32 {
        self.0
    }

    fn into_second(self) -> u64 {
        self.1
    }
}"#,
            r#"
struct A { pub field1: u32, pub(crate) field2: u64 }

impl A {
    fn new() -> A {
        A { field1: 42, field2: 42 }
    }

    fn into_first(self) -> u32 {
        self.field1
    }

    fn into_second(self) -> u64 {
        self.field2
    }
}"#,
        );
    }

    #[test]
    fn convert_struct_with_multi_file_references() {
        check_assist(
            convert_tuple_struct_to_named_struct,
            r#"
//- /main.rs
struct Inner;
struct A$0(Inner);

mod foo;

//- /foo.rs
use crate::{A, Inner};
fn f() {
    let a = A(Inner);
}
"#,
            r#"
//- /main.rs
struct Inner;
struct A { field1: Inner }

mod foo;

//- /foo.rs
use crate::{A, Inner};
fn f() {
    let a = A { field1: Inner };
}
"#,
        );
    }

    #[test]
    fn convert_struct_with_where_clause() {
        check_assist(
            convert_tuple_struct_to_named_struct,
            r#"
struct Wrap$0<T>(T)
where
    T: Display;
"#,
            r#"
struct Wrap<T>
where
    T: Display,
{ field1: T }

"#,
        );
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use std::io::{self, Read, Write};

use futures::{Future, Wake, Tokens};
use futures::stream::{Stream, StreamResult, Fuse};
use futuremio::*;

pub trait Parse: Sized + Send + 'static {
    type Parser: Default + Send + 'static;
    type Error: Send + 'static + From<io::Error>;

    fn parse(parser: &mut Self::Parser, buf: &[u8]) -> Option<Result<(Self, usize), Self::Error>>;
}

/// A stream for parsing from an underlying reader, using an unbounded internal
/// buffer.
pub struct ParseStream<R, P: Parse> {
    source: R,
    source_ready: ReadinessStream,
    parser: P::Parser,
    buf: Vec<u8>,

    // how far into the buffer have we parsed? note: we drain lazily
    pos: usize,

    // is there new data that we need to try to parse?
    need_parse: bool,

    // has `source` yielded an EOF?
    eof: bool,
}

impl<R, P> ParseStream<R, P>
    where R: Read + Send + 'static,
          P: Parse
{
    pub fn new(source: R, source_ready: ReadinessStream) -> ParseStream<R, P> {
        ParseStream {
            source: source,
            source_ready: source_ready,
            parser: Default::default(),
            buf: Vec::with_capacity(2048),
            pos: 0,
            need_parse: false,
            eof: false,
        }
    }
}

// TODO: move this into method
fn read<R: Read>(socket: &mut R, input: &mut Vec<u8>) -> io::Result<(usize, bool)> {
    loop {
        match socket.read(unsafe { slice_to_end(input) }) {
            Ok(0) => return Ok((0, true)),
            Ok(n) => {
                let len = input.len();
                unsafe {
                    input.set_len(len + n);
                }
                return Ok((n, false));
            }
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => return Ok((0, false)),
            Err(e) => return Err(e),
        }
    }

    unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
        use std::slice;
        if v.capacity() == 0 {
            v.reserve(16);
        }
        if v.capacity() == v.len() {
            v.reserve(1);
        }
        slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
                                  v.capacity() - v.len())
    }
}

impl<R, P: Parse> ParseStream<R, P> {
    fn drain(&mut self) {
        self.buf.drain(..self.pos);
        self.pos = 0;
    }
}

impl<R, P> Stream for ParseStream<R, P>
    where R: Read + Send + 'static,
          P: Parse
{
    type Item = P;
    type Error = P::Error;

    fn poll(&mut self, tokens: &Tokens) -> Option<StreamResult<P, P::Error>> {
        if !self.eof {
            match self.source_ready.poll(tokens) {
                // TODO: consider refactoring `poll` API to make this more readable...
                None => {}
                Some(Err(e)) => return Some(Err(e.into())),
                Some(Ok(Some(()))) => {
                    // drain any stale contents, to make as much space as we can
                    // before reading
                    self.drain();

                    match read(&mut self.source, &mut self.buf) {
                        Ok((n, eof)) => {
                            self.eof = eof;
                            if n > 0 {
                                self.need_parse = true
                            }
                        }
                        Err(e) => return Some(Err(e.into())),
                    }
                }
                _ => unreachable!(),
            }
        }

        if self.need_parse {
            if let Some(res) = P::parse(&mut self.parser, &self.buf) {
                return Some(res.map(|(i, n)| {
                    self.pos += n;
                    Some(i)
                }))
            }

            // don't try to parse again until we've seen more bytes
            self.need_parse = false;
        }

        if self.eof {
            Some(Ok(None))
        } else {
            None
        }
    }

    fn schedule(&mut self, wake: Arc<Wake>) {
        // TODO: think through this carefully...
        if self.need_parse {
            // Empty tokens because in a `need_parse` situation, we'll attempt
            // to parse regardless of tokens
            wake.wake(&Tokens::empty())
        } else {
            self.source_ready.schedule(wake)
        }
    }
}

// TODO: make this a method
fn write<W: Write>(sink: &mut W, buf: &mut Vec<u8>) -> io::Result<()> {
    loop {
        match sink.write(&buf) {
            Ok(0) => {
                // TODO: copied from mio example, clean up
                return Err(io::Error::new(io::ErrorKind::Other, "early eof2"));
            }
            Ok(n) => {
                buf.drain(..n); // TODO: consider draining more lazily, i.e. only just before returning
                if buf.len() == 0 {
                    return Ok(());
                }
            }
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => return Ok(()),
            Err(e) => return Err(e),
        }
    }
}

pub trait Serialize: Send + 'static {
    fn serialize(&self, buf: &mut Vec<u8>);
}

/// Serialize a stream of items into a writer, using an unbounded internal
/// buffer.
///
/// Represented as a future which yields () on successfully writing the entire
/// stream (which requires the stream to terminate), or an error if there is any
/// error along the way.
pub struct StreamWriter<W, S> {
    sink: W,
    sink_ready: ReadinessStream,
    items: Fuse<S>,
    buf: Vec<u8>,
}

impl<W, S> StreamWriter<W, S>
    where W: Write + Send + 'static,
          S: Stream,
          S::Item: Serialize,
          S::Error: From<io::Error>
{
    pub fn new(sink: W, sink_ready: ReadinessStream, items: S) -> StreamWriter<W, S> {
        StreamWriter {
            sink: sink,
            sink_ready: sink_ready,
            items: items.fuse(),
            buf: Vec::with_capacity(2048),
        }
    }
}

impl<W, S> Future for StreamWriter<W, S>
    where W: Write + Send + 'static,
          S: Stream,
          S::Item: Serialize,
          S::Error: From<io::Error>
{
    type Item = ();
    type Error = S::Error;

    fn poll(&mut self, tokens: &Tokens) -> Option<Result<(), S::Error>> {
        loop {
            match self.items.poll(tokens) {
                Some(Err(e)) => return Some(Err(e)),
                Some(Ok(Some(item))) => item.serialize(&mut self.buf),
                _ => break,
            }
        }

        // TODO: optimization for case where we just transitioned from no bytes
        // to write to having bytes to write; in that case, we should try to
        // write regardless of sink_ready.poll, because we haven't asked for a
        // readiness notifcation. Saves a trip around the event loop.

        if self.buf.len() > 0 {
            match self.sink_ready.poll(tokens) {
                Some(Err(e)) => Some(Err(e.into())),
                Some(Ok(Some(()))) => {
                    if let Err(e) = write(&mut self.sink, &mut self.buf) {
                        Some(Err(e.into()))
                    } else {
                        None
                    }
                }
                _ => None,
            }
        } else if self.items.is_done() {
            // Nothing more to write to sink, and no more incoming items; we're done!
            Some(Ok(()))
        } else {
            None
        }
    }

    fn schedule(&mut self, wake: Arc<Wake>) {
        // wake up on writability only if we have something to write
        if self.buf.len() > 0 {
            self.sink_ready.schedule(wake.clone());
        }

        // for now, we are always happy to write more items into our unbounded buffer
        self.items.schedule(wake);
    }
}
<commit_msg>Fix StreamWriter's item reading loop to use `Tokens::all()` after the first iteration<commit_after>use std::sync::Arc;
use std::io::{self, Read, Write};

use futures::{Future, Wake, Tokens};
use futures::stream::{Stream, StreamResult, Fuse};
use futuremio::*;

pub trait Parse: Sized + Send + 'static {
    type Parser: Default + Send + 'static;
    type Error: Send + 'static + From<io::Error>;

    fn parse(parser: &mut Self::Parser, buf: &[u8]) -> Option<Result<(Self, usize), Self::Error>>;
}

/// A stream for parsing from an underlying reader, using an unbounded internal
/// buffer.
pub struct ParseStream<R, P: Parse> {
    source: R,
    source_ready: ReadinessStream,
    parser: P::Parser,
    buf: Vec<u8>,

    // how far into the buffer have we parsed? note: we drain lazily
    pos: usize,

    // is there new data that we need to try to parse?
    need_parse: bool,

    // has `source` yielded an EOF?
    eof: bool,
}

impl<R, P> ParseStream<R, P>
    where R: Read + Send + 'static,
          P: Parse
{
    pub fn new(source: R, source_ready: ReadinessStream) -> ParseStream<R, P> {
        ParseStream {
            source: source,
            source_ready: source_ready,
            parser: Default::default(),
            buf: Vec::with_capacity(2048),
            pos: 0,
            need_parse: false,
            eof: false,
        }
    }
}

// TODO: move this into method
fn read<R: Read>(socket: &mut R, input: &mut Vec<u8>) -> io::Result<(usize, bool)> {
    loop {
        match socket.read(unsafe { slice_to_end(input) }) {
            Ok(0) => return Ok((0, true)),
            Ok(n) => {
                let len = input.len();
                unsafe {
                    input.set_len(len + n);
                }
                return Ok((n, false));
            }
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => return Ok((0, false)),
            Err(e) => return Err(e),
        }
    }

    unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
        use std::slice;
        if v.capacity() == 0 {
            v.reserve(16);
        }
        if v.capacity() == v.len() {
            v.reserve(1);
        }
        slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
                                  v.capacity() - v.len())
    }
}

impl<R, P: Parse> ParseStream<R, P> {
    fn drain(&mut self) {
        self.buf.drain(..self.pos);
        self.pos = 0;
    }
}

impl<R, P> Stream for ParseStream<R, P>
    where R: Read + Send + 'static,
          P: Parse
{
    type Item = P;
    type Error = P::Error;

    fn poll(&mut self, tokens: &Tokens) -> Option<StreamResult<P, P::Error>> {
        if !self.eof {
            match self.source_ready.poll(tokens) {
                // TODO: consider refactoring `poll` API to make this more readable...
                None => {}
                Some(Err(e)) => return Some(Err(e.into())),
                Some(Ok(Some(()))) => {
                    // drain any stale contents, to make as much space as we can
                    // before reading
                    self.drain();

                    match read(&mut self.source, &mut self.buf) {
                        Ok((n, eof)) => {
                            self.eof = eof;
                            if n > 0 {
                                self.need_parse = true
                            }
                        }
                        Err(e) => return Some(Err(e.into())),
                    }
                }
                _ => unreachable!(),
            }
        }

        if self.need_parse {
            if let Some(res) = P::parse(&mut self.parser, &self.buf) {
                return Some(res.map(|(i, n)| {
                    self.pos += n;
                    Some(i)
                }))
            }

            // don't try to parse again until we've seen more bytes
            self.need_parse = false;
        }

        if self.eof {
            Some(Ok(None))
        } else {
            None
        }
    }

    fn schedule(&mut self, wake: Arc<Wake>) {
        // TODO: think through this carefully...
        if self.need_parse {
            // Empty tokens because in a `need_parse` situation, we'll attempt
            // to parse regardless of tokens
            wake.wake(&Tokens::empty())
        } else {
            self.source_ready.schedule(wake)
        }
    }
}

// TODO: make this a method
fn write<W: Write>(sink: &mut W, buf: &mut Vec<u8>) -> io::Result<()> {
    loop {
        match sink.write(&buf) {
            Ok(0) => {
                // TODO: copied from mio example, clean up
                return Err(io::Error::new(io::ErrorKind::Other, "early eof2"));
            }
            Ok(n) => {
                buf.drain(..n); // TODO: consider draining more lazily, i.e. only just before returning
                if buf.len() == 0 {
                    return Ok(());
                }
            }
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => return Ok(()),
            Err(e) => return Err(e),
        }
    }
}

pub trait Serialize: Send + 'static {
    fn serialize(&self, buf: &mut Vec<u8>);
}

/// Serialize a stream of items into a writer, using an unbounded internal
/// buffer.
///
/// Represented as a future which yields () on successfully writing the entire
/// stream (which requires the stream to terminate), or an error if there is any
/// error along the way.
pub struct StreamWriter<W, S> {
    sink: W,
    sink_ready: ReadinessStream,
    items: Fuse<S>,
    buf: Vec<u8>,
}

impl<W, S> StreamWriter<W, S>
    where W: Write + Send + 'static,
          S: Stream,
          S::Item: Serialize,
          S::Error: From<io::Error>
{
    pub fn new(sink: W, sink_ready: ReadinessStream, items: S) -> StreamWriter<W, S> {
        StreamWriter {
            sink: sink,
            sink_ready: sink_ready,
            items: items.fuse(),
            buf: Vec::with_capacity(2048),
        }
    }
}

impl<W, S> Future for StreamWriter<W, S>
    where W: Write + Send + 'static,
          S: Stream,
          S::Item: Serialize,
          S::Error: From<io::Error>
{
    type Item = ();
    type Error = S::Error;

    fn poll(&mut self, tokens: &Tokens) -> Option<Result<(), S::Error>> {
        // make sure to pass down `tokens` only on the *first* poll for items
        let mut tokens_for_items = Some(tokens);
        loop {
            match self.items.poll(tokens_for_items.take().unwrap_or(&Tokens::all())) {
                Some(Err(e)) => return Some(Err(e)),
                Some(Ok(Some(item))) => item.serialize(&mut self.buf),
                _ => break,
            }
        }

        // TODO: optimization for case where we just transitioned from no bytes
        // to write to having bytes to write; in that case, we should try to
        // write regardless of sink_ready.poll, because we haven't asked for a
        // readiness notifcation. Saves a trip around the event loop.

        if self.buf.len() > 0 {
            match self.sink_ready.poll(tokens) {
                Some(Err(e)) => Some(Err(e.into())),
                Some(Ok(Some(()))) => {
                    if let Err(e) = write(&mut self.sink, &mut self.buf) {
                        Some(Err(e.into()))
                    } else {
                        None
                    }
                }
                _ => None,
            }
        } else if self.items.is_done() {
            // Nothing more to write to sink, and no more incoming items; we're done!
            Some(Ok(()))
        } else {
            None
        }
    }

    fn schedule(&mut self, wake: Arc<Wake>) {
        // wake up on writability only if we have something to write
        if self.buf.len() > 0 {
            self.sink_ready.schedule(wake.clone());
        }

        // for now, we are always happy to write more items into our unbounded buffer
        self.items.schedule(wake);
    }
}
<|endoftext|>


<commit_before>// edition:2018
// check-pass
#![allow(unused)]
#![deny(rust_2021_prelude_collisions)]

struct S;

impl S {
    fn try_into(self) -> S {
        S
    }
}

struct X;

trait Hey {
    fn from_iter(_: i32) -> Self;
}

impl Hey for X {
    fn from_iter(_: i32) -> Self {
        X
    }
}

fn main() {
    // See https://github.com/rust-lang/rust/issues/86633
    let s = S;
    let s2 = s.try_into();

    // See https://github.com/rust-lang/rust/issues/86902
    X::from_iter(1);
}
<commit_msg>Add generic types to prelude collision lint test.<commit_after>// edition:2018
// check-pass
#![allow(unused)]
#![deny(rust_2021_prelude_collisions)]

struct S;

impl S {
    fn try_into(self) -> S {
        S
    }
}

struct X;

trait Hey {
    fn from_iter(_: i32) -> Self;
}

impl Hey for X {
    fn from_iter(_: i32) -> Self {
        X
    }
}

struct Y<T>(T);

impl Hey for Y<i32> {
    fn from_iter(_: i32) -> Self {
        Y(0)
    }
}

struct Z<T>(T);

impl Hey for Z<i32> {
    fn from_iter(_: i32) -> Self {
        Z(0)
    }
}

impl std::iter::FromIterator<u32> for Z<u32> {
    fn from_iter<T: IntoIterator<Item = u32>>(_: T) -> Self {
        todo!()
    }
}

fn main() {
    // See https://github.com/rust-lang/rust/issues/86633
    let s = S;
    let s2 = s.try_into();

    // See https://github.com/rust-lang/rust/issues/86902
    X::from_iter(1);
    Y::from_iter(1);
    Y::<i32>::from_iter(1);
    Z::<i32>::from_iter(1);
}
<|endoftext|>


<commit_before>use futures_core::future::Future;
use futures_core::ready;
use futures_core::task::{Context, Poll};
use futures_io::AsyncWrite;
use futures_io::IoSlice;
use std::io;
use std::mem;
use std::pin::Pin;

/// Future for the
/// [`write_all_vectored`](super::AsyncWriteExt::write_all_vectored) method.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct WriteAllVectored<'a, W: ?Sized + Unpin> {
    writer: &'a mut W,
    bufs: &'a mut [IoSlice<'a>],
}

impl<W: ?Sized + Unpin> Unpin for WriteAllVectored<'_, W> {}

impl<'a, W: AsyncWrite + ?Sized + Unpin> WriteAllVectored<'a, W> {
    pub(super) fn new(writer: &'a mut W, bufs: &'a mut [IoSlice<'a>]) -> Self {
        Self { writer, bufs: IoSlice::advance(bufs, 0) }
    }
}

impl<W: AsyncWrite + ?Sized + Unpin> Future for WriteAllVectored<'_, W> {
    type Output = io::Result<()>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
        let this = &mut *self;
        while !this.bufs.is_empty() {
            let n = ready!(Pin::new(&mut this.writer).poll_write_vectored(cx, this.bufs))?;
            if n == 0 {
                return Poll::Ready(Err(io::ErrorKind::WriteZero.into()));
            } else {
                this.bufs = IoSlice::advance(mem::take(&mut this.bufs), n);
            }
        }

        Poll::Ready(Ok(()))
    }
}

#[cfg(test)]
mod tests {
    use std::cmp::min;
    use std::future::Future;
    use std::io;
    use std::pin::Pin;
    use std::task::{Context, Poll};

    use crate::io::{AsyncWrite, AsyncWriteExt, IoSlice};
    use crate::task::noop_waker;

    /// Create a new writer that reads from at most `n_bufs` and reads
    /// `per_call` bytes (in total) per call to write.
    fn test_writer(n_bufs: usize, per_call: usize) -> TestWriter {
        TestWriter { n_bufs, per_call, written: Vec::new() }
    }

    // TODO: maybe move this the future-test crate?
    struct TestWriter {
        n_bufs: usize,
        per_call: usize,
        written: Vec<u8>,
    }

    impl AsyncWrite for TestWriter {
        fn poll_write(
            self: Pin<&mut Self>,
            cx: &mut Context<'_>,
            buf: &[u8],
        ) -> Poll<io::Result<usize>> {
            self.poll_write_vectored(cx, &[IoSlice::new(buf)])
        }

        fn poll_write_vectored(
            mut self: Pin<&mut Self>,
            _cx: &mut Context<'_>,
            bufs: &[IoSlice<'_>],
        ) -> Poll<io::Result<usize>> {
            let mut left = self.per_call;
            let mut written = 0;
            for buf in bufs.iter().take(self.n_bufs) {
                let n = min(left, buf.len());
                self.written.extend_from_slice(&buf[0..n]);
                left -= n;
                written += n;
            }
            Poll::Ready(Ok(written))
        }

        fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
            Poll::Ready(Ok(()))
        }

        fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
            Poll::Ready(Ok(()))
        }
    }

    // TODO: maybe move this the future-test crate?
    macro_rules! assert_poll_ok {
        ($e:expr, $expected:expr) => {
            let expected = $expected;
            match $e {
                Poll::Ready(Ok(ok)) if ok == expected => {}
                got => {
                    panic!("unexpected result, got: {:?}, wanted: Ready(Ok({:?}))", got, expected)
                }
            }
        };
    }

    #[test]
    fn test_writer_read_from_one_buf() {
        let waker = noop_waker();
        let mut cx = Context::from_waker(&waker);

        let mut dst = test_writer(1, 2);
        let mut dst = Pin::new(&mut dst);

        assert_poll_ok!(dst.as_mut().poll_write(&mut cx, &[]), 0);
        assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, &[]), 0);

        // Read at most 2 bytes.
        assert_poll_ok!(dst.as_mut().poll_write(&mut cx, &[1, 1, 1]), 2);
        let bufs = &[IoSlice::new(&[2, 2, 2])];
        assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 2);

        // Only read from first buf.
        let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4, 4])];
        assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 1);

        assert_eq!(dst.written, &[1, 1, 2, 2, 3]);
    }

    #[test]
    fn test_writer_read_from_multiple_bufs() {
        let waker = noop_waker();
        let mut cx = Context::from_waker(&waker);

        let mut dst = test_writer(3, 3);
        let mut dst = Pin::new(&mut dst);

        // Read at most 3 bytes from two buffers.
        let bufs = &[IoSlice::new(&[1]), IoSlice::new(&[2, 2, 2])];
        assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 3);

        // Read at most 3 bytes from three buffers.
        let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4]), IoSlice::new(&[5, 5])];
        assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 3);

        assert_eq!(dst.written, &[1, 2, 2, 3, 4, 5]);
    }

    #[test]
    fn test_write_all_vectored() {
        let waker = noop_waker();
        let mut cx = Context::from_waker(&waker);

        #[rustfmt::skip] // Becomes unreadable otherwise.
        let tests: Vec<(_, &'static [u8])> = vec![
            (vec![], &[]),
            (vec![IoSlice::new(&[]), IoSlice::new(&[])], &[]),
            (vec![IoSlice::new(&[1])], &[1]),
            (vec![IoSlice::new(&[1, 2])], &[1, 2]),
            (vec![IoSlice::new(&[1, 2, 3])], &[1, 2, 3]),
            (vec![IoSlice::new(&[1, 2, 3, 4])], &[1, 2, 3, 4]),
            (vec![IoSlice::new(&[1, 2, 3, 4, 5])], &[1, 2, 3, 4, 5]),
            (vec![IoSlice::new(&[1]), IoSlice::new(&[2])], &[1, 2]),
            (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2])], &[1, 1, 2, 2]),
            (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 1, 2, 2, 2]),
            (vec![IoSlice::new(&[1, 1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 1, 2, 2, 2, 2]),
            (vec![IoSlice::new(&[1]), IoSlice::new(&[2]), IoSlice::new(&[3])], &[1, 2, 3]),
            (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3])], &[1, 1, 2, 2, 3, 3]),
            (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 1, 1, 2, 2, 2, 3, 3, 3]),
        ];

        for (mut input, wanted) in tests {
            let mut dst = test_writer(2, 2);
            {
                let mut future = dst.write_all_vectored(&mut *input);
                match Pin::new(&mut future).poll(&mut cx) {
                    Poll::Ready(Ok(())) => {}
                    other => panic!("unexpected result polling future: {:?}", other),
                }
            }
            assert_eq!(&*dst.written, &*wanted);
        }
    }
}
<commit_msg>Update to new io_slice_advance interface<commit_after>use futures_core::future::Future;
use futures_core::ready;
use futures_core::task::{Context, Poll};
use futures_io::AsyncWrite;
use futures_io::IoSlice;
use std::io;
use std::pin::Pin;

/// Future for the
/// [`write_all_vectored`](super::AsyncWriteExt::write_all_vectored) method.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct WriteAllVectored<'a, W: ?Sized + Unpin> {
    writer: &'a mut W,
    bufs: &'a mut [IoSlice<'a>],
}

impl<W: ?Sized + Unpin> Unpin for WriteAllVectored<'_, W> {}

impl<'a, W: AsyncWrite + ?Sized + Unpin> WriteAllVectored<'a, W> {
    pub(super) fn new(writer: &'a mut W, mut bufs: &'a mut [IoSlice<'a>]) -> Self {
        IoSlice::advance_slices(&mut bufs, 0);
        Self { writer, bufs }
    }
}

impl<W: AsyncWrite + ?Sized + Unpin> Future for WriteAllVectored<'_, W> {
    type Output = io::Result<()>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
        let this = &mut *self;
        while !this.bufs.is_empty() {
            let n = ready!(Pin::new(&mut this.writer).poll_write_vectored(cx, this.bufs))?;
            if n == 0 {
                return Poll::Ready(Err(io::ErrorKind::WriteZero.into()));
            } else {
                IoSlice::advance_slices(&mut this.bufs, n);
            }
        }

        Poll::Ready(Ok(()))
    }
}

#[cfg(test)]
mod tests {
    use std::cmp::min;
    use std::future::Future;
    use std::io;
    use std::pin::Pin;
    use std::task::{Context, Poll};

    use crate::io::{AsyncWrite, AsyncWriteExt, IoSlice};
    use crate::task::noop_waker;

    /// Create a new writer that reads from at most `n_bufs` and reads
    /// `per_call` bytes (in total) per call to write.
    fn test_writer(n_bufs: usize, per_call: usize) -> TestWriter {
        TestWriter { n_bufs, per_call, written: Vec::new() }
    }

    // TODO: maybe move this the future-test crate?
    struct TestWriter {
        n_bufs: usize,
        per_call: usize,
        written: Vec<u8>,
    }

    impl AsyncWrite for TestWriter {
        fn poll_write(
            self: Pin<&mut Self>,
            cx: &mut Context<'_>,
            buf: &[u8],
        ) -> Poll<io::Result<usize>> {
            self.poll_write_vectored(cx, &[IoSlice::new(buf)])
        }

        fn poll_write_vectored(
            mut self: Pin<&mut Self>,
            _cx: &mut Context<'_>,
            bufs: &[IoSlice<'_>],
        ) -> Poll<io::Result<usize>> {
            let mut left = self.per_call;
            let mut written = 0;
            for buf in bufs.iter().take(self.n_bufs) {
                let n = min(left, buf.len());
                self.written.extend_from_slice(&buf[0..n]);
                left -= n;
                written += n;
            }
            Poll::Ready(Ok(written))
        }

        fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
            Poll::Ready(Ok(()))
        }

        fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
            Poll::Ready(Ok(()))
        }
    }

    // TODO: maybe move this the future-test crate?
    macro_rules! assert_poll_ok {
        ($e:expr, $expected:expr) => {
            let expected = $expected;
            match $e {
                Poll::Ready(Ok(ok)) if ok == expected => {}
                got => {
                    panic!("unexpected result, got: {:?}, wanted: Ready(Ok({:?}))", got, expected)
                }
            }
        };
    }

    #[test]
    fn test_writer_read_from_one_buf() {
        let waker = noop_waker();
        let mut cx = Context::from_waker(&waker);

        let mut dst = test_writer(1, 2);
        let mut dst = Pin::new(&mut dst);

        assert_poll_ok!(dst.as_mut().poll_write(&mut cx, &[]), 0);
        assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, &[]), 0);

        // Read at most 2 bytes.
        assert_poll_ok!(dst.as_mut().poll_write(&mut cx, &[1, 1, 1]), 2);
        let bufs = &[IoSlice::new(&[2, 2, 2])];
        assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 2);

        // Only read from first buf.
        let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4, 4])];
        assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 1);

        assert_eq!(dst.written, &[1, 1, 2, 2, 3]);
    }

    #[test]
    fn test_writer_read_from_multiple_bufs() {
        let waker = noop_waker();
        let mut cx = Context::from_waker(&waker);

        let mut dst = test_writer(3, 3);
        let mut dst = Pin::new(&mut dst);

        // Read at most 3 bytes from two buffers.
        let bufs = &[IoSlice::new(&[1]), IoSlice::new(&[2, 2, 2])];
        assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 3);

        // Read at most 3 bytes from three buffers.
        let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4]), IoSlice::new(&[5, 5])];
        assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 3);

        assert_eq!(dst.written, &[1, 2, 2, 3, 4, 5]);
    }

    #[test]
    fn test_write_all_vectored() {
        let waker = noop_waker();
        let mut cx = Context::from_waker(&waker);

        #[rustfmt::skip] // Becomes unreadable otherwise.
        let tests: Vec<(_, &'static [u8])> = vec![
            (vec![], &[]),
            (vec![IoSlice::new(&[]), IoSlice::new(&[])], &[]),
            (vec![IoSlice::new(&[1])], &[1]),
            (vec![IoSlice::new(&[1, 2])], &[1, 2]),
            (vec![IoSlice::new(&[1, 2, 3])], &[1, 2, 3]),
            (vec![IoSlice::new(&[1, 2, 3, 4])], &[1, 2, 3, 4]),
            (vec![IoSlice::new(&[1, 2, 3, 4, 5])], &[1, 2, 3, 4, 5]),
            (vec![IoSlice::new(&[1]), IoSlice::new(&[2])], &[1, 2]),
            (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2])], &[1, 1, 2, 2]),
            (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 1, 2, 2, 2]),
            (vec![IoSlice::new(&[1, 1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 1, 2, 2, 2, 2]),
            (vec![IoSlice::new(&[1]), IoSlice::new(&[2]), IoSlice::new(&[3])], &[1, 2, 3]),
            (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3])], &[1, 1, 2, 2, 3, 3]),
            (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 1, 1, 2, 2, 2, 3, 3, 3]),
        ];

        for (mut input, wanted) in tests {
            let mut dst = test_writer(2, 2);
            {
                let mut future = dst.write_all_vectored(&mut *input);
                match Pin::new(&mut future).poll(&mut cx) {
                    Poll::Ready(Ok(())) => {}
                    other => panic!("unexpected result polling future: {:?}", other),
                }
            }
            assert_eq!(&*dst.written, &*wanted);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
// Copyright (C) 2018 LEE Dongjun <redongjun@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
// Boston, MA 02110-1335, USA.

use glib::prelude::*;
use gst::prelude::*;

use std::io::Write;
use std::sync::{Arc, Mutex};
use std::{thread, time};

fn init() {
    use std::sync::Once;
    static INIT: Once = Once::new();

    INIT.call_once(|| {
        gst::init().unwrap();
        gstthreadshare::plugin_register_static().expect("gstthreadshare tcpclientsrc test");
    });
}

#[test]
fn test_push() {
    init();

    let handler = thread::spawn(move || {
        use std::net;

        let listener = net::TcpListener::bind("0.0.0.0:5000").unwrap();
        let stream = listener.incoming().next().unwrap();
        let buffer = [0; 160];
        let mut socket = stream.unwrap();
        for _ in 0..3 {
            let _ = socket.write(&buffer);
            thread::sleep(time::Duration::from_millis(20));
        }
    });

    let pipeline = gst::Pipeline::new(None);

    let tcpclientsrc = gst::ElementFactory::make("ts-tcpclientsrc", None).unwrap();
    let appsink = gst::ElementFactory::make("appsink", None).unwrap();
    appsink.set_property("sync", &false).unwrap();
    appsink.set_property("async", &false).unwrap();

    pipeline.add_many(&[&tcpclientsrc, &appsink]).unwrap();
    tcpclientsrc.link(&appsink).unwrap();

    let caps = gst::Caps::new_simple("foo/bar", &[]);
    tcpclientsrc.set_property("caps", &caps).unwrap();
    tcpclientsrc.set_property("port", &5000i32).unwrap();

    appsink.set_property("emit-signals", &true).unwrap();

    let samples = Arc::new(Mutex::new(Vec::new()));

    let appsink = appsink.dynamic_cast::<gst_app::AppSink>().unwrap();
    let samples_clone = samples.clone();
    appsink.connect_new_sample(move |appsink| {
        let sample = appsink
            .emit("pull-sample", &[])
            .unwrap()
            .unwrap()
            .get::<gst::Sample>()
            .unwrap()
            .unwrap();

        let mut samples = samples_clone.lock().unwrap();
        samples.push(sample);
        Ok(gst::FlowSuccess::Ok)
    });

    pipeline.set_state(gst::State::Playing).unwrap();

    let mut eos = false;
    let bus = pipeline.get_bus().unwrap();
    while let Some(msg) = bus.timed_pop(5 * gst::SECOND) {
        use gst::MessageView;
        match msg.view() {
            MessageView::Eos(..) => {
                eos = true;
                break;
            }
            MessageView::Error(..) => unreachable!(),
            _ => (),
        }
    }

    assert!(eos);
    let samples = samples.lock().unwrap();
    for sample in samples.iter() {
        assert_eq!(Some(caps.as_ref()), sample.get_caps());
    }

    let total_received_size = samples.iter().fold(0, |acc, sample| {
        acc + sample.get_buffer().unwrap().get_size()
    });
    assert_eq!(total_received_size, 3 * 160);

    pipeline.set_state(gst::State::Null).unwrap();

    handler.join().unwrap();
}
<commit_msg>threadshare: fix race condition in tcpclientsrc test<commit_after>// Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
// Copyright (C) 2018 LEE Dongjun <redongjun@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
// Boston, MA 02110-1335, USA.

use glib::prelude::*;
use gst::prelude::*;

use std::io::Write;
use std::sync::mpsc;
use std::sync::{Arc, Mutex};
use std::{thread, time};

fn init() {
    use std::sync::Once;
    static INIT: Once = Once::new();

    INIT.call_once(|| {
        gst::init().unwrap();
        gstthreadshare::plugin_register_static().expect("gstthreadshare tcpclientsrc test");
    });
}

#[test]
fn test_push() {
    init();

    let (listening_tx, listening_rx) = mpsc::channel();
    let handler = thread::spawn(move || {
        use std::net;

        let listener = net::TcpListener::bind("0.0.0.0:5000").unwrap();
        listening_tx.send(()).unwrap();
        let stream = listener.incoming().next().unwrap();
        let buffer = [0; 160];
        let mut socket = stream.unwrap();
        for _ in 0..3 {
            let _ = socket.write(&buffer);
            thread::sleep(time::Duration::from_millis(20));
        }
    });

    let pipeline = gst::Pipeline::new(None);

    let tcpclientsrc = gst::ElementFactory::make("ts-tcpclientsrc", None).unwrap();
    let appsink = gst::ElementFactory::make("appsink", None).unwrap();
    appsink.set_property("sync", &false).unwrap();
    appsink.set_property("async", &false).unwrap();

    pipeline.add_many(&[&tcpclientsrc, &appsink]).unwrap();
    tcpclientsrc.link(&appsink).unwrap();

    let caps = gst::Caps::new_simple("foo/bar", &[]);
    tcpclientsrc.set_property("caps", &caps).unwrap();
    tcpclientsrc.set_property("port", &5000i32).unwrap();

    appsink.set_property("emit-signals", &true).unwrap();

    let samples = Arc::new(Mutex::new(Vec::new()));

    let appsink = appsink.dynamic_cast::<gst_app::AppSink>().unwrap();
    let samples_clone = samples.clone();
    appsink.connect_new_sample(move |appsink| {
        let sample = appsink
            .emit("pull-sample", &[])
            .unwrap()
            .unwrap()
            .get::<gst::Sample>()
            .unwrap()
            .unwrap();

        let mut samples = samples_clone.lock().unwrap();
        samples.push(sample);
        Ok(gst::FlowSuccess::Ok)
    });

    // Wait for the server to listen
    listening_rx.recv().unwrap();
    pipeline.set_state(gst::State::Playing).unwrap();

    let mut eos = false;
    let bus = pipeline.get_bus().unwrap();
    while let Some(msg) = bus.timed_pop(5 * gst::SECOND) {
        use gst::MessageView;
        match msg.view() {
            MessageView::Eos(..) => {
                eos = true;
                break;
            }
            MessageView::Error(err) => panic!("{:?}", err),
            _ => (),
        }
    }

    assert!(eos);
    let samples = samples.lock().unwrap();
    for sample in samples.iter() {
        assert_eq!(Some(caps.as_ref()), sample.get_caps());
    }

    let total_received_size = samples.iter().fold(0, |acc, sample| {
        acc + sample.get_buffer().unwrap().get_size()
    });
    assert_eq!(total_received_size, 3 * 160);

    pipeline.set_state(gst::State::Null).unwrap();

    handler.join().unwrap();
}
<|endoftext|>


<commit_before>// Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
// Boston, MA 02110-1335, USA.

#[macro_use]
extern crate pretty_assertions;

use glib::prelude::*;

fn init() {
    use std::sync::{Once, ONCE_INIT};
    static INIT: Once = ONCE_INIT;

    INIT.call_once(|| {
        gst::init().unwrap();
        gstrsclosedcaption::plugin_register_static().expect("mccenc test");
    });
}

/// Encode a single CDP packet and compare the output
#[test]
fn test_encode() {
    init();

    let input = [
        0x96, 0x69, 0x52, 0x4f, 0x67, 0x00, 0x00, 0x72, 0xf4, 0xfc, 0x80, 0x80, 0xfd, 0x80, 0x80,
        0xff, 0x02, 0x22, 0xfe, 0x8c, 0xff, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
        0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
        0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
        0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x73, 0x91, 0x81, 0x65, 0x6e, 0x67,
        0x81, 0x7f, 0xff, 0x74, 0x00, 0x00, 0x1c,
    ];

    let expected_output = b"File Format=MacCaption_MCC V1.0\r\n\
\r\n\
///////////////////////////////////////////////////////////////////////////////////\r\n\
// Computer Prompting and Captioning Company\r\n\
// Ancillary Data Packet Transfer File\r\n\
//\r\n\
// Permission to generate this format is granted provided that\r\n\
//   1. This ANC Transfer file format is used on an as-is basis and no warranty is given, and\r\n\
//   2. This entire descriptive information text is included in a generated .mcc file.\r\n\
//\r\n\
// General file format:\r\n\
//   HH:MM:SS:FF(tab)[Hexadecimal ANC data in groups of 2 characters]\r\n\
//     Hexadecimal data starts with the Ancillary Data Packet DID (Data ID defined in S291M)\r\n\
//       and concludes with the Check Sum following the User Data Words.\r\n\
//     Each time code line must contain at most one complete ancillary data packet.\r\n\
//     To transfer additional ANC Data successive lines may contain identical time code.\r\n\
//     Time Code Rate=[24, 25, 30, 30DF, 50, 60]\r\n\
//\r\n\
//   ANC data bytes may be represented by one ASCII character according to the following schema:\r\n\
//     G  FAh 00h 00h\r\n\
//     H  2 x (FAh 00h 00h)\r\n\
//     I  3 x (FAh 00h 00h)\r\n\
//     J  4 x (FAh 00h 00h)\r\n\
//     K  5 x (FAh 00h 00h)\r\n\
//     L  6 x (FAh 00h 00h)\r\n\
//     M  7 x (FAh 00h 00h)\r\n\
//     N  8 x (FAh 00h 00h)\r\n\
//     O  9 x (FAh 00h 00h)\r\n\
//     P  FBh 80h 80h\r\n\
//     Q  FCh 80h 80h\r\n\
//     R  FDh 80h 80h\r\n\
//     S  96h 69h\r\n\
//     T  61h 01h\r\n\
//     U  E1h 00h 00h 00h\r\n\
//     Z  00h\r\n\
//\r\n\
///////////////////////////////////////////////////////////////////////////////////\r\n\
\r\n\
UUID=14720C04-857D-40E2-86FC-F080DE44CE74\r\n\
Creation Program=GStreamer MCC Encoder 0.4.0\r\n\
Creation Date=Thursday, December 27, 2018\r\n\
Creation Time=17:34:47\r\n\
Time Code Rate=30DF\r\n\
\r\n\
11:12:13;14	T52S524F67ZZ72F4QRFF0222FE8CFFOM739181656E67817FFF74ZZ1CZ\r\n";

    let mut h = gst_check::Harness::new("mccenc");
    {
        let enc = h.get_element().expect("could not create encoder");
        enc.set_property("uuid", &"14720C04-857D-40E2-86FC-F080DE44CE74")
            .unwrap();
        enc.set_property(
            "creation-date",
            &glib::DateTime::new_utc(2018, 12, 27, 17, 34, 47.0),
        )
        .unwrap();
    }

    h.set_src_caps_str(
        "closedcaption/x-cea-708, format=(string)cdp, framerate=(fraction)30000/1001",
    );

    let tc = gst_video::ValidVideoTimeCode::new(
        gst::Fraction::new(30000, 1001),
        None,
        gst_video::VideoTimeCodeFlags::DROP_FRAME,
        11,
        12,
        13,
        14,
        0,
    )
    .unwrap();

    let buf = {
        let mut buf = gst::Buffer::from_mut_slice(Vec::from(&input[..]));
        let buf_ref = buf.get_mut().unwrap();
        gst_video::VideoTimeCodeMeta::add(buf_ref, &tc);
        buf_ref.set_pts(gst::ClockTime::from_seconds(0));
        buf
    };

    assert_eq!(h.push(buf), Ok(gst::FlowSuccess::Ok));
    h.push_event(gst::Event::new_eos().build());

    let buf = h.pull().expect("Couldn't pull buffer");
    let timecode = buf
        .get_meta::<gst_video::VideoTimeCodeMeta>()
        .expect("No timecode for buffer")
        .get_tc();
    assert_eq!(timecode, tc);

    let pts = buf.get_pts();
    assert_eq!(pts, gst::ClockTime::from_seconds(0));

    let map = buf.map_readable().expect("Couldn't map buffer readable");
    assert_eq!(
        std::str::from_utf8(map.as_ref()),
        std::str::from_utf8(expected_output.as_ref())
    );
}
<commit_msg>mccenc: Fix expected test output to contain the new version number<commit_after>// Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
// Boston, MA 02110-1335, USA.

#[macro_use]
extern crate pretty_assertions;

use glib::prelude::*;

fn init() {
    use std::sync::{Once, ONCE_INIT};
    static INIT: Once = ONCE_INIT;

    INIT.call_once(|| {
        gst::init().unwrap();
        gstrsclosedcaption::plugin_register_static().expect("mccenc test");
    });
}

/// Encode a single CDP packet and compare the output
#[test]
fn test_encode() {
    init();

    let input = [
        0x96, 0x69, 0x52, 0x4f, 0x67, 0x00, 0x00, 0x72, 0xf4, 0xfc, 0x80, 0x80, 0xfd, 0x80, 0x80,
        0xff, 0x02, 0x22, 0xfe, 0x8c, 0xff, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
        0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
        0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
        0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x73, 0x91, 0x81, 0x65, 0x6e, 0x67,
        0x81, 0x7f, 0xff, 0x74, 0x00, 0x00, 0x1c,
    ];

    let expected_output = b"File Format=MacCaption_MCC V1.0\r\n\
\r\n\
///////////////////////////////////////////////////////////////////////////////////\r\n\
// Computer Prompting and Captioning Company\r\n\
// Ancillary Data Packet Transfer File\r\n\
//\r\n\
// Permission to generate this format is granted provided that\r\n\
//   1. This ANC Transfer file format is used on an as-is basis and no warranty is given, and\r\n\
//   2. This entire descriptive information text is included in a generated .mcc file.\r\n\
//\r\n\
// General file format:\r\n\
//   HH:MM:SS:FF(tab)[Hexadecimal ANC data in groups of 2 characters]\r\n\
//     Hexadecimal data starts with the Ancillary Data Packet DID (Data ID defined in S291M)\r\n\
//       and concludes with the Check Sum following the User Data Words.\r\n\
//     Each time code line must contain at most one complete ancillary data packet.\r\n\
//     To transfer additional ANC Data successive lines may contain identical time code.\r\n\
//     Time Code Rate=[24, 25, 30, 30DF, 50, 60]\r\n\
//\r\n\
//   ANC data bytes may be represented by one ASCII character according to the following schema:\r\n\
//     G  FAh 00h 00h\r\n\
//     H  2 x (FAh 00h 00h)\r\n\
//     I  3 x (FAh 00h 00h)\r\n\
//     J  4 x (FAh 00h 00h)\r\n\
//     K  5 x (FAh 00h 00h)\r\n\
//     L  6 x (FAh 00h 00h)\r\n\
//     M  7 x (FAh 00h 00h)\r\n\
//     N  8 x (FAh 00h 00h)\r\n\
//     O  9 x (FAh 00h 00h)\r\n\
//     P  FBh 80h 80h\r\n\
//     Q  FCh 80h 80h\r\n\
//     R  FDh 80h 80h\r\n\
//     S  96h 69h\r\n\
//     T  61h 01h\r\n\
//     U  E1h 00h 00h 00h\r\n\
//     Z  00h\r\n\
//\r\n\
///////////////////////////////////////////////////////////////////////////////////\r\n\
\r\n\
UUID=14720C04-857D-40E2-86FC-F080DE44CE74\r\n\
Creation Program=GStreamer MCC Encoder 0.5.0\r\n\
Creation Date=Thursday, December 27, 2018\r\n\
Creation Time=17:34:47\r\n\
Time Code Rate=30DF\r\n\
\r\n\
11:12:13;14	T52S524F67ZZ72F4QRFF0222FE8CFFOM739181656E67817FFF74ZZ1CZ\r\n";

    let mut h = gst_check::Harness::new("mccenc");
    {
        let enc = h.get_element().expect("could not create encoder");
        enc.set_property("uuid", &"14720C04-857D-40E2-86FC-F080DE44CE74")
            .unwrap();
        enc.set_property(
            "creation-date",
            &glib::DateTime::new_utc(2018, 12, 27, 17, 34, 47.0),
        )
        .unwrap();
    }

    h.set_src_caps_str(
        "closedcaption/x-cea-708, format=(string)cdp, framerate=(fraction)30000/1001",
    );

    let tc = gst_video::ValidVideoTimeCode::new(
        gst::Fraction::new(30000, 1001),
        None,
        gst_video::VideoTimeCodeFlags::DROP_FRAME,
        11,
        12,
        13,
        14,
        0,
    )
    .unwrap();

    let buf = {
        let mut buf = gst::Buffer::from_mut_slice(Vec::from(&input[..]));
        let buf_ref = buf.get_mut().unwrap();
        gst_video::VideoTimeCodeMeta::add(buf_ref, &tc);
        buf_ref.set_pts(gst::ClockTime::from_seconds(0));
        buf
    };

    assert_eq!(h.push(buf), Ok(gst::FlowSuccess::Ok));
    h.push_event(gst::Event::new_eos().build());

    let buf = h.pull().expect("Couldn't pull buffer");
    let timecode = buf
        .get_meta::<gst_video::VideoTimeCodeMeta>()
        .expect("No timecode for buffer")
        .get_tc();
    assert_eq!(timecode, tc);

    let pts = buf.get_pts();
    assert_eq!(pts, gst::ClockTime::from_seconds(0));

    let map = buf.map_readable().expect("Couldn't map buffer readable");
    assert_eq!(
        std::str::from_utf8(map.as_ref()),
        std::str::from_utf8(expected_output.as_ref())
    );
}
<|endoftext|>


<commit_before>use vec3::Vec3;
use pointlight::PointLight;
use sphere::Sphere;
use plane::Plane;
use diffusematerial::DiffuseMaterial;
use light::Light;
use prim::Prim;

mod vec3;
mod ray;
mod camera;
mod prim;
mod sphere;
mod plane;
mod light;
mod pointlight;
mod material;
mod flatmaterial;
mod diffusematerial;
mod intersection;
mod scene;
mod renderer;
mod export;

fn main() {
    let image_width = 480;
    let image_height = 360;

    let max_lights = 10;
    let max_prims = 1000;

    let mut lights: Vec<Box<Light>> = Vec::with_capacity(max_lights);
    lights.push(box PointLight {position: Vec3 {x: 50.0, y: 90.0, z: 50.0}, color: Vec3 {x: 1.0, y: 1.0, z: 1.0}});

    let grey  = DiffuseMaterial {k_a: 0.0, k_d: 1.0, k_s: 0.0, diffuse: Vec3 {x: 0.6, y: 0.6, z: 0.6}, ambient: Vec3{x: 0.0, y: 0.0, z: 0.0}};
    let red   = DiffuseMaterial {k_a: 0.0, k_d: 0.9, k_s: 0.1, diffuse: Vec3 {x: 1.0, y: 0.0, z: 0.0}, ambient: Vec3{x: 0.0, y: 0.0, z: 0.0}};
    let green = DiffuseMaterial {k_a: 0.0, k_d: 0.9, k_s: 0.1, diffuse: Vec3 {x: 0.0, y: 1.0, z: 0.0}, ambient: Vec3{x: 0.0, y: 0.0, z: 0.0}};
    let blue  = DiffuseMaterial {k_a: 0.0, k_d: 0.2, k_s: 0.8, diffuse: Vec3 {x: 0.0, y: 0.0, z: 1.0}, ambient: Vec3{x: 0.0, y: 0.0, z: 0.0}};

    let mut prims: Vec<Box<Prim>> = Vec::with_capacity(max_prims);
    prims.push(box Plane {a: 0.0,  b:  0.0, c: 1.0, d: 0.0,   material: box grey  }); // Ahead
    prims.push(box Plane {a: 0.0,  b: -1.0, c: 0.0, d: 100.0, material: box grey  }); // Bottom
    prims.push(box Plane {a: 0.0,  b:  1.0, c: 0.0, d: 0.0,   material: box grey  }); // Top
    prims.push(box Plane {a: 1.0,  b:  0.0, c: 0.0, d: 0.0,   material: box red   }); // Left
    prims.push(box Plane {a: -1.0, b:  0.0, c: 0.0, d: 100.0, material: box green }); // Right
    prims.push(box Sphere {center: Vec3 {x: 30.0, y: 15.0, z: 20.0}, radius: 15.0, material: box blue});
    prims.push(box Sphere {center: Vec3 {x: 70.0, y: 17.0, z: 80.0}, radius: 17.0, material: box blue});

    let camera = camera::Camera::new(
        Vec3 {x: 50.0, y: 25.0, z: 300.0},
        Vec3 {x: 50.0, y: 50.0, z: 50.0},
        Vec3 {x: 0.0, y: 1.0, z: 0.0},
        45.0,
        image_width,
        image_height
    );

    let scene = scene::Scene {
        lights: lights,
        prims: prims,
        background: Vec3 {x: 1.0, y: 1.0, z: 1.0}
    };

    let renderer = renderer::Renderer {
        reflect_depth: 2,
        refract_depth: 4,
        use_octree: false,
        shadows: false,
        threads: 1
    };
    let image_data = renderer.render(camera, scene);

    ::export::to_ppm(image_data, image_width, image_height, "test.ppm");
}
<commit_msg>Add some render time info output.<commit_after>extern crate time;

use vec3::Vec3;
use pointlight::PointLight;
use sphere::Sphere;
use plane::Plane;
use diffusematerial::DiffuseMaterial;
use light::Light;
use prim::Prim;

mod vec3;
mod ray;
mod camera;
mod prim;
mod sphere;
mod plane;
mod light;
mod pointlight;
mod material;
mod flatmaterial;
mod diffusematerial;
mod intersection;
mod scene;
mod renderer;
mod export;

fn main() {
    let start_time = ::time::get_time().sec;

    let image_width = 480;
    let image_height = 360;
    let out_file = "test.ppm";

    let max_lights = 10;
    let max_prims = 1000;

    let mut lights: Vec<Box<Light>> = Vec::with_capacity(max_lights);
    lights.push(box PointLight {position: Vec3 {x: 50.0, y: 90.0, z: 50.0}, color: Vec3 {x: 1.0, y: 1.0, z: 1.0}});

    let grey  = DiffuseMaterial {k_a: 0.0, k_d: 1.0, k_s: 0.0, diffuse: Vec3 {x: 0.6, y: 0.6, z: 0.6}, ambient: Vec3{x: 0.0, y: 0.0, z: 0.0}};
    let red   = DiffuseMaterial {k_a: 0.0, k_d: 0.9, k_s: 0.1, diffuse: Vec3 {x: 1.0, y: 0.0, z: 0.0}, ambient: Vec3{x: 0.0, y: 0.0, z: 0.0}};
    let green = DiffuseMaterial {k_a: 0.0, k_d: 0.9, k_s: 0.1, diffuse: Vec3 {x: 0.0, y: 1.0, z: 0.0}, ambient: Vec3{x: 0.0, y: 0.0, z: 0.0}};
    let blue  = DiffuseMaterial {k_a: 0.0, k_d: 0.2, k_s: 0.8, diffuse: Vec3 {x: 0.0, y: 0.0, z: 1.0}, ambient: Vec3{x: 0.0, y: 0.0, z: 0.0}};

    let mut prims: Vec<Box<Prim>> = Vec::with_capacity(max_prims);
    prims.push(box Plane {a: 0.0,  b:  0.0, c: 1.0, d: 0.0,   material: box grey  }); // Ahead
    prims.push(box Plane {a: 0.0,  b: -1.0, c: 0.0, d: 100.0, material: box grey  }); // Bottom
    prims.push(box Plane {a: 0.0,  b:  1.0, c: 0.0, d: 0.0,   material: box grey  }); // Top
    prims.push(box Plane {a: 1.0,  b:  0.0, c: 0.0, d: 0.0,   material: box red   }); // Left
    prims.push(box Plane {a: -1.0, b:  0.0, c: 0.0, d: 100.0, material: box green }); // Right
    prims.push(box Sphere {center: Vec3 {x: 30.0, y: 15.0, z: 20.0}, radius: 15.0, material: box blue});
    prims.push(box Sphere {center: Vec3 {x: 70.0, y: 17.0, z: 80.0}, radius: 17.0, material: box blue});

    let camera = camera::Camera::new(
        Vec3 {x: 50.0, y: 25.0, z: 150.0},
        Vec3 {x: 50.0, y: 50.0, z: 50.0},
        Vec3 {x: 0.0, y: 1.0, z: 0.0},
        45.0,
        image_width,
        image_height
    );

    let scene = scene::Scene {
        lights: lights,
        prims: prims,
        background: Vec3 {x: 1.0, y: 1.0, z: 1.0}
    };

    let renderer = renderer::Renderer {
        reflect_depth: 2,
        refract_depth: 4,
        use_octree: false,
        shadows: false,
        threads: 1
    };
    let image_data = renderer.render(camera, scene);
    let render_time = ::time::get_time().sec;

    ::export::to_ppm(image_data, image_width, image_height, out_file);
    let export_time = ::time::get_time().sec;

    println!("Start: {}, Render done: {} ({}s), Write done: {} ({}s), Total: {}s, written to {}",
        start_time,
        render_time,
        render_time - start_time,
        export_time,
        export_time - render_time,
        export_time - start_time,
        out_file
    );
}
<|endoftext|>


<commit_before>use std::slice;

use binding::vm;
use class::object;
use types;

pub struct VM;

impl VM {
    pub fn init() {
        vm::init();
    }

    pub fn parse_arguments(argc: types::argc, arguments: *const types::rb_value) -> Vec<object::Object> {
        let arguments = unsafe {
            slice::from_raw_parts(arguments, argc as usize).to_vec()
        };

        arguments.iter().map(|value| object::Object::from(*value)).collect()
    }

    pub fn parse_itself(itself: types::rb_value) -> object::Object {
        object::Object::from(itself)
    }
}
<commit_msg>Create VM::create_arguments()<commit_after>use std::slice;

use binding::vm;
use class::object;
use types;

use class::traits::RawObject;

pub struct VM;

impl VM {
    pub fn init() {
        vm::init();
    }

    pub fn parse_arguments(argc: types::argc, arguments: *const types::rb_value) -> Vec<object::Object> {
        let arguments = unsafe {
            slice::from_raw_parts(arguments, argc as usize).to_vec()
        };

        arguments.iter().map(|value| object::Object::from(*value)).collect()
    }

    pub fn create_arguments(arguments: Vec<object::Object>) -> (types::c_int, *const types::rb_value) {
        (arguments.len() as types::c_int, Self::arguments_as_ptr(arguments))
    }

    pub fn parse_itself(itself: types::rb_value) -> object::Object {
        object::Object::from(itself)
    }

    fn arguments_as_ptr(arguments: Vec<object::Object>) -> *const types::rb_value {
        arguments
            .iter()
            .map(|object| object.value())
            .collect::<Vec<types::rb_value>>()
            .as_ptr()
    }
}
<|endoftext|>