<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// compile-flags: -Z print-type-sizes

// This file illustrates how enums with a non-null field are handled,
// modelled after cases like `Option<&u32>` and such.
//
// It uses NonZero directly, rather than `&_` or `Unique<_>`, because
// the test is not set up to deal with target-dependent pointer width.
//
// It avoids using u64/i64 because on some targets that is only 4-byte
// aligned (while on most it is 8-byte aligned) and so the resulting
// padding and overall computed sizes can be quite different.

#![feature(nonzero)]
#![allow(dead_code)]

extern crate core;
use core::nonzero::{NonZero, Zeroable};

pub enum MyOption<T> { None, Some(T) }

impl<T> Default for MyOption<T> {
    fn default() -> Self { MyOption::None }
}

pub enum EmbeddedDiscr {
    None,
    Record { pre: u8, val: NonZero<u32>, post: u16 },
}

impl Default for EmbeddedDiscr {
    fn default() -> Self { EmbeddedDiscr::None }
}

#[derive(Default)]
pub struct IndirectNonZero<T: Zeroable + One> {
    pre: u8,
    nested: NestedNonZero<T>,
    post: u16,
}

pub struct NestedNonZero<T: Zeroable> {
    pre: u8,
    val: NonZero<T>,
    post: u16,
}

impl<T: Zeroable+One> Default for NestedNonZero<T> {
    fn default() -> Self {
        unsafe {
            NestedNonZero { pre: 0, val: NonZero::new_unchecked(T::one()), post: 0 }
        }
    }
}

pub trait One {
    fn one() -> Self;
}

impl One for u32 {
    fn one() -> Self { 1 }
}

pub fn main() {
    let _x: MyOption<NonZero<u32>> = Default::default();
    let _y: EmbeddedDiscr = Default::default();
    let _z: MyOption<IndirectNonZero<u32>> = Default::default();
}
<commit_msg>Remove unnecessary unsafe in test/ui/print_type_sizes/nullable.rs<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// compile-flags: -Z print-type-sizes

// This file illustrates how enums with a non-null field are handled,
// modelled after cases like `Option<&u32>` and such.
//
// It uses NonZero directly, rather than `&_` or `Unique<_>`, because
// the test is not set up to deal with target-dependent pointer width.
//
// It avoids using u64/i64 because on some targets that is only 4-byte
// aligned (while on most it is 8-byte aligned) and so the resulting
// padding and overall computed sizes can be quite different.

#![feature(nonzero)]
#![allow(dead_code)]

extern crate core;
use core::nonzero::{NonZero, Zeroable};

pub enum MyOption<T> { None, Some(T) }

impl<T> Default for MyOption<T> {
    fn default() -> Self { MyOption::None }
}

pub enum EmbeddedDiscr {
    None,
    Record { pre: u8, val: NonZero<u32>, post: u16 },
}

impl Default for EmbeddedDiscr {
    fn default() -> Self { EmbeddedDiscr::None }
}

#[derive(Default)]
pub struct IndirectNonZero<T: Zeroable + One> {
    pre: u8,
    nested: NestedNonZero<T>,
    post: u16,
}

pub struct NestedNonZero<T: Zeroable> {
    pre: u8,
    val: NonZero<T>,
    post: u16,
}

impl<T: Zeroable+One> Default for NestedNonZero<T> {
    fn default() -> Self {
        NestedNonZero { pre: 0, val: NonZero::new(T::one()).unwrap(), post: 0 }
    }
}

pub trait One {
    fn one() -> Self;
}

impl One for u32 {
    fn one() -> Self { 1 }
}

pub fn main() {
    let _x: MyOption<NonZero<u32>> = Default::default();
    let _y: EmbeddedDiscr = Default::default();
    let _z: MyOption<IndirectNonZero<u32>> = Default::default();
}
<|endoftext|>


<commit_before>use super::content::Content;
use super::encodings::{self, bytes_to_string, string_to_bytes};
use super::{Dictionary, Object, ObjectId};
use crate::xref::Xref;
use crate::{Error, Result};
use encoding::all::UTF_16BE;
use encoding::types::{DecoderTrap, EncoderTrap, Encoding};
use log::info;
use std::collections::BTreeMap;
use std::io::Write;
use std::str;

/// PDF document.
#[derive(Debug, Clone)]
pub struct Document {
	/// The version of the PDF specification to which the file conforms.
	pub version: String,

	/// The trailer gives the location of the cross-reference table and of certain special objects.
	pub trailer: Dictionary,

	/// The cross-reference table contains locations of the indirect objects.
	pub reference_table: Xref,

	/// The objects that make up the document contained in the file.
	pub objects: BTreeMap<ObjectId, Object>,

	/// Current maximum object id within the document.
	pub max_id: u32,
}

impl Document {
	/// Create new PDF document.
	pub fn new() -> Document {
		Document {
			version: "1.4".to_string(),
			trailer: Dictionary::new(),
			reference_table: Xref::new(0),
			objects: BTreeMap::new(),
			max_id: 0,
		}
	}

	/// Get object by object id, will recursively dereference a referenced object.
	pub fn get_object(&self, id: ObjectId) -> Result<&Object> {
		if let Some(object) = self.objects.get(&id) {
			if let Ok(id) = object.as_reference() {
				return self.get_object(id);
			} else {
				return Ok(object);
			}
		}
		Err(Error::ObjectNotFound)
	}

	/// Get mutable reference to object by object id, will iteratively dereference a referenced object.
	pub fn get_object_mut(&mut self, id: ObjectId) -> Result<&mut Object> {
		let mut object = self.objects.get(&id).ok_or(Error::ObjectNotFound)?;
		let mut cur_id = id;

		while let Ok(id) = object.as_reference() {
			cur_id = id;
			object = self.objects.get(&cur_id).ok_or(Error::ObjectNotFound)?;
		}

		Ok(self.objects.get_mut(&cur_id).unwrap())
	}

	/// Get dictionary object by id.
	pub fn get_dictionary(&self, id: ObjectId) -> Result<&Dictionary> {
		self.get_object(id).and_then(Object::as_dict)
	}

	/// Traverse objects from trailer recursively, return all referenced object IDs.
	pub fn traverse_objects<A: Fn(&mut Object) -> ()>(&mut self, action: A) -> Vec<ObjectId> {
		fn traverse_array<A: Fn(&mut Object) -> ()>(array: &mut Vec<Object>, action: &A, refs: &mut Vec<ObjectId>) {
			for item in array.iter_mut() {
				traverse_object(item, action, refs);
			}
		}
		fn traverse_dictionary<A: Fn(&mut Object) -> ()>(dict: &mut Dictionary, action: &A, refs: &mut Vec<ObjectId>) {
			for (_, v) in dict.iter_mut() {
				traverse_object(v, action, refs);
			}
		}
		fn traverse_object<A: Fn(&mut Object) -> ()>(object: &mut Object, action: &A, refs: &mut Vec<ObjectId>) {
			action(object);
			match *object {
				Object::Array(ref mut array) => traverse_array(array, action, refs),
				Object::Dictionary(ref mut dict) => traverse_dictionary(dict, action, refs),
				Object::Stream(ref mut stream) => traverse_dictionary(&mut stream.dict, action, refs),
				Object::Reference(id) => {
					if !refs.contains(&id) {
						refs.push(id);
					}
				}
				_ => {}
			}
		}
		let mut refs = vec![];
		traverse_dictionary(&mut self.trailer, &action, &mut refs);
		let mut index = 0;
		while index < refs.len() {
			if let Some(object) = self.objects.get_mut(&refs[index]) {
				traverse_object(object, &action, &mut refs);
			}
			index += 1;
		}
		refs
	}

	/// Get catalog dictionary.
	pub fn catalog(&self) -> Result<&Dictionary> {
		self.trailer.get(b"Root").and_then(Object::as_reference).and_then(|id| self.get_dictionary(id))
	}

	/// Get page numbers and corresponding object ids.
	pub fn get_pages(&self) -> BTreeMap<u32, ObjectId> {
		fn collect_pages(doc: &Document, page_tree_id: ObjectId, page_number: &mut u32, pages: &mut BTreeMap<u32, ObjectId>) {
			if let Ok(kids) = doc.get_dictionary(page_tree_id).and_then(|page_tree| page_tree.get(b"Kids")).and_then(Object::as_array) {
				for kid in kids {
					if let Ok(kid_id) = kid.as_reference() {
						if let Ok(type_name) = doc.get_dictionary(kid_id).and_then(Dictionary::type_name) {
							match type_name {
								"Page" => {
									pages.insert(*page_number, kid_id);
									*page_number += 1;
								}
								"Pages" => {
									collect_pages(doc, kid_id, page_number, pages);
								}
								_ => {}
							}
						}
					}
				}
			}
		}

		let mut pages = BTreeMap::new();
		let mut page_number = 1;
		if let Ok(page_tree_id) = self.catalog().and_then(|cat| cat.get(b"Pages")).and_then(Object::as_reference) {
			collect_pages(self, page_tree_id, &mut page_number, &mut pages);
		}
		pages
	}

	/// Get content stream object ids of a page.
	pub fn get_page_contents(&self, page_id: ObjectId) -> Vec<ObjectId> {
		let mut streams = vec![];
		if let Ok(page) = self.get_dictionary(page_id) {
			if let Ok(contents) = page.get(b"Contents") {
				match *contents {
					Object::Reference(ref id) => {
						streams.push(*id);
					}
					Object::Array(ref arr) => {
						for content in arr {
							if let Ok(id) = content.as_reference() { streams.push(id) }
						}
					}
					_ => {}
				}
			}
		}
		streams
	}

	/// Get content of a page.
	pub fn get_page_content(&self, page_id: ObjectId) -> Result<Vec<u8>> {
		let mut content = Vec::new();
		let content_streams = self.get_page_contents(page_id);
		for object_id in content_streams {
			if let Ok(content_stream) = self.get_object(object_id).and_then(Object::as_stream) {
				match content_stream.decompressed_content() {
					Ok(data) => content.write_all(&data)?,
					Err(_) => content.write_all(&content_stream.content)?,
				};
			}
		}
		Ok(content)
	}

	/// Get decoded page content;
	pub fn get_and_decode_page_content(&self, page_id: ObjectId) -> Result<Content> {
		let content_data = self.get_page_content(page_id)?;
		Content::decode(&content_data)
	}

	/// Get resources used by a page.
	pub fn get_page_resources(&self, page_id: ObjectId) -> (Option<&Dictionary>, Vec<ObjectId>) {
		fn collect_resources(page_node: &Dictionary, resource_ids: &mut Vec<ObjectId>, doc: &Document) {
			if let Ok(resources_id) = page_node.get(b"Resources").and_then(Object::as_reference) {
				resource_ids.push(resources_id);
			}
			if let Ok(page_tree) = page_node.get(b"Parent").and_then(Object::as_reference).and_then(|id| doc.get_dictionary(id)) {
				collect_resources(page_tree, resource_ids, doc);
			}
		};

		let mut resource_dict = None;
		let mut resource_ids = Vec::new();
		if let Ok(page) = self.get_dictionary(page_id) {
			resource_dict = page.get(b"Resources").and_then(Object::as_dict).ok();
			collect_resources(page, &mut resource_ids, self);
		}
		(resource_dict, resource_ids)
	}

	/// Get fonts used by a page.
	pub fn get_page_fonts(&self, page_id: ObjectId) -> BTreeMap<Vec<u8>, &Dictionary> {
		fn collect_fonts_from_resources<'a>(resources: &'a Dictionary, fonts: &mut BTreeMap<Vec<u8>, &'a Dictionary>, doc: &'a Document) {
			if let Ok(font_dict) = resources.get(b"Font").and_then(Object::as_dict) {
				for (name, value) in font_dict.iter() {
					let font = match *value {
						Object::Reference(id) => doc.get_dictionary(id).ok(),
						Object::Dictionary(ref dict) => Some(dict),
						_ => None,
					};
					if !fonts.contains_key(name) {
						font.map(|font| fonts.insert(name.clone(), font));
					}
				}
			}
		};

		let mut fonts = BTreeMap::new();
		let (resource_dict, resource_ids) = self.get_page_resources(page_id);
		if let Some(resources) = resource_dict {
			collect_fonts_from_resources(resources, &mut fonts, self);
		}
		for resource_id in resource_ids {
			if let Ok(resources) = self.get_dictionary(resource_id) {
				collect_fonts_from_resources(resources, &mut fonts, self);
			}
		}
		fonts
	}

	pub fn decode_text(encoding: Option<&str>, bytes: &[u8]) -> String {
		if let Some(encoding) = encoding {
			info!("{}", encoding);
			match encoding {
				"StandardEncoding" => bytes_to_string(encodings::STANDARD_ENCODING, bytes),
				"MacRomanEncoding" => bytes_to_string(encodings::MAC_ROMAN_ENCODING, bytes),
				"MacExpertEncoding" => bytes_to_string(encodings::MAC_EXPERT_ENCODING, bytes),
				"WinAnsiEncoding" => bytes_to_string(encodings::WIN_ANSI_ENCODING, bytes),
				"UniGB-UCS2-H" | "UniGB−UTF16−H" => UTF_16BE.decode(bytes, DecoderTrap::Ignore).unwrap(),
				"Identity-H" => "?Identity-H Unimplemented?".to_string(), // Unimplemented
				_ => String::from_utf8_lossy(bytes).to_string(),
			}
		} else {
			bytes_to_string(encodings::STANDARD_ENCODING, bytes)
		}
	}

	pub fn encode_text(encoding: Option<&str>, text: &str) -> Vec<u8> {
		if let Some(encoding) = encoding {
			match encoding {
				"StandardEncoding" => string_to_bytes(encodings::STANDARD_ENCODING, text),
				"MacRomanEncoding" => string_to_bytes(encodings::MAC_ROMAN_ENCODING, text),
				"MacExpertEncoding" => string_to_bytes(encodings::MAC_EXPERT_ENCODING, text),
				"WinAnsiEncoding" => string_to_bytes(encodings::WIN_ANSI_ENCODING, text),
				"UniGB-UCS2-H" | "UniGB−UTF16−H" => UTF_16BE.encode(text, EncoderTrap::Ignore).unwrap(),
				"Identity-H" => vec![], // Unimplemented
				_ => text.as_bytes().to_vec(),
			}
		} else {
			string_to_bytes(encodings::STANDARD_ENCODING, text)
		}
	}
}

impl Default for Document {
	fn default() -> Self {
		Self::new()
	}
}
<commit_msg>Protect against a corrupted page tree.<commit_after>use super::content::Content;
use super::encodings::{self, bytes_to_string, string_to_bytes};
use super::{Dictionary, Object, ObjectId};
use crate::xref::Xref;
use crate::{Error, Result};
use encoding::all::UTF_16BE;
use encoding::types::{DecoderTrap, EncoderTrap, Encoding};
use log::info;
use std::collections::BTreeMap;
use std::io::Write;
use std::str;

/// PDF document.
#[derive(Debug, Clone)]
pub struct Document {
	/// The version of the PDF specification to which the file conforms.
	pub version: String,

	/// The trailer gives the location of the cross-reference table and of certain special objects.
	pub trailer: Dictionary,

	/// The cross-reference table contains locations of the indirect objects.
	pub reference_table: Xref,

	/// The objects that make up the document contained in the file.
	pub objects: BTreeMap<ObjectId, Object>,

	/// Current maximum object id within the document.
	pub max_id: u32,
}

impl Document {
	/// Create new PDF document.
	pub fn new() -> Document {
		Document {
			version: "1.4".to_string(),
			trailer: Dictionary::new(),
			reference_table: Xref::new(0),
			objects: BTreeMap::new(),
			max_id: 0,
		}
	}

	/// Get object by object id, will recursively dereference a referenced object.
	pub fn get_object(&self, id: ObjectId) -> Result<&Object> {
		if let Some(object) = self.objects.get(&id) {
			if let Ok(id) = object.as_reference() {
				return self.get_object(id);
			} else {
				return Ok(object);
			}
		}
		Err(Error::ObjectNotFound)
	}

	/// Get mutable reference to object by object id, will iteratively dereference a referenced object.
	pub fn get_object_mut(&mut self, id: ObjectId) -> Result<&mut Object> {
		let mut object = self.objects.get(&id).ok_or(Error::ObjectNotFound)?;
		let mut cur_id = id;

		while let Ok(id) = object.as_reference() {
			cur_id = id;
			object = self.objects.get(&cur_id).ok_or(Error::ObjectNotFound)?;
		}

		Ok(self.objects.get_mut(&cur_id).unwrap())
	}

	/// Get dictionary object by id.
	pub fn get_dictionary(&self, id: ObjectId) -> Result<&Dictionary> {
		self.get_object(id).and_then(Object::as_dict)
	}

	/// Traverse objects from trailer recursively, return all referenced object IDs.
	pub fn traverse_objects<A: Fn(&mut Object) -> ()>(&mut self, action: A) -> Vec<ObjectId> {
		fn traverse_array<A: Fn(&mut Object) -> ()>(array: &mut Vec<Object>, action: &A, refs: &mut Vec<ObjectId>) {
			for item in array.iter_mut() {
				traverse_object(item, action, refs);
			}
		}
		fn traverse_dictionary<A: Fn(&mut Object) -> ()>(dict: &mut Dictionary, action: &A, refs: &mut Vec<ObjectId>) {
			for (_, v) in dict.iter_mut() {
				traverse_object(v, action, refs);
			}
		}
		fn traverse_object<A: Fn(&mut Object) -> ()>(object: &mut Object, action: &A, refs: &mut Vec<ObjectId>) {
			action(object);
			match *object {
				Object::Array(ref mut array) => traverse_array(array, action, refs),
				Object::Dictionary(ref mut dict) => traverse_dictionary(dict, action, refs),
				Object::Stream(ref mut stream) => traverse_dictionary(&mut stream.dict, action, refs),
				Object::Reference(id) => {
					if !refs.contains(&id) {
						refs.push(id);
					}
				}
				_ => {}
			}
		}
		let mut refs = vec![];
		traverse_dictionary(&mut self.trailer, &action, &mut refs);
		let mut index = 0;
		while index < refs.len() {
			if let Some(object) = self.objects.get_mut(&refs[index]) {
				traverse_object(object, &action, &mut refs);
			}
			index += 1;
		}
		refs
	}

	/// Get catalog dictionary.
	pub fn catalog(&self) -> Result<&Dictionary> {
		self.trailer.get(b"Root").and_then(Object::as_reference).and_then(|id| self.get_dictionary(id))
	}

	const PAGE_TREE_DEPTH_LIMIT : usize = 256;

	/// Get page numbers and corresponding object ids.
	pub fn get_pages(&self) -> BTreeMap<u32, ObjectId> {
		fn collect_pages(doc: &Document, page_tree_id: ObjectId, page_number: &mut u32, pages: &mut BTreeMap<u32, ObjectId>, depth: usize) {
			if let Ok(kids) = doc.get_dictionary(page_tree_id).and_then(|page_tree| page_tree.get(b"Kids")).and_then(Object::as_array) {
				for kid in kids {
					if let Ok(kid_id) = kid.as_reference() {
						if let Ok(type_name) = doc.get_dictionary(kid_id).and_then(Dictionary::type_name) {
							match type_name {
								"Page" => {
									pages.insert(*page_number, kid_id);
									*page_number += 1;
								}
								"Pages" => {
									if depth <= Document::PAGE_TREE_DEPTH_LIMIT {
										collect_pages(doc, kid_id, page_number, pages, depth+1);
									}
								}
								_ => {}
							}
						}
					}
				}
			}
		}

		let mut pages = BTreeMap::new();
		let mut page_number = 1;
		if let Ok(page_tree_id) = self.catalog().and_then(|cat| cat.get(b"Pages")).and_then(Object::as_reference) {
			collect_pages(self, page_tree_id, &mut page_number, &mut pages, 0);
		}
		pages
	}

	/// Get content stream object ids of a page.
	pub fn get_page_contents(&self, page_id: ObjectId) -> Vec<ObjectId> {
		let mut streams = vec![];
		if let Ok(page) = self.get_dictionary(page_id) {
			if let Ok(contents) = page.get(b"Contents") {
				match *contents {
					Object::Reference(ref id) => {
						streams.push(*id);
					}
					Object::Array(ref arr) => {
						for content in arr {
							if let Ok(id) = content.as_reference() { streams.push(id) }
						}
					}
					_ => {}
				}
			}
		}
		streams
	}

	/// Get content of a page.
	pub fn get_page_content(&self, page_id: ObjectId) -> Result<Vec<u8>> {
		let mut content = Vec::new();
		let content_streams = self.get_page_contents(page_id);
		for object_id in content_streams {
			if let Ok(content_stream) = self.get_object(object_id).and_then(Object::as_stream) {
				match content_stream.decompressed_content() {
					Ok(data) => content.write_all(&data)?,
					Err(_) => content.write_all(&content_stream.content)?,
				};
			}
		}
		Ok(content)
	}

	/// Get decoded page content;
	pub fn get_and_decode_page_content(&self, page_id: ObjectId) -> Result<Content> {
		let content_data = self.get_page_content(page_id)?;
		Content::decode(&content_data)
	}

	/// Get resources used by a page.
	pub fn get_page_resources(&self, page_id: ObjectId) -> (Option<&Dictionary>, Vec<ObjectId>) {
		fn collect_resources(page_node: &Dictionary, resource_ids: &mut Vec<ObjectId>, doc: &Document) {
			if let Ok(resources_id) = page_node.get(b"Resources").and_then(Object::as_reference) {
				resource_ids.push(resources_id);
			}
			if let Ok(page_tree) = page_node.get(b"Parent").and_then(Object::as_reference).and_then(|id| doc.get_dictionary(id)) {
				collect_resources(page_tree, resource_ids, doc);
			}
		};

		let mut resource_dict = None;
		let mut resource_ids = Vec::new();
		if let Ok(page) = self.get_dictionary(page_id) {
			resource_dict = page.get(b"Resources").and_then(Object::as_dict).ok();
			collect_resources(page, &mut resource_ids, self);
		}
		(resource_dict, resource_ids)
	}

	/// Get fonts used by a page.
	pub fn get_page_fonts(&self, page_id: ObjectId) -> BTreeMap<Vec<u8>, &Dictionary> {
		fn collect_fonts_from_resources<'a>(resources: &'a Dictionary, fonts: &mut BTreeMap<Vec<u8>, &'a Dictionary>, doc: &'a Document) {
			if let Ok(font_dict) = resources.get(b"Font").and_then(Object::as_dict) {
				for (name, value) in font_dict.iter() {
					let font = match *value {
						Object::Reference(id) => doc.get_dictionary(id).ok(),
						Object::Dictionary(ref dict) => Some(dict),
						_ => None,
					};
					if !fonts.contains_key(name) {
						font.map(|font| fonts.insert(name.clone(), font));
					}
				}
			}
		};

		let mut fonts = BTreeMap::new();
		let (resource_dict, resource_ids) = self.get_page_resources(page_id);
		if let Some(resources) = resource_dict {
			collect_fonts_from_resources(resources, &mut fonts, self);
		}
		for resource_id in resource_ids {
			if let Ok(resources) = self.get_dictionary(resource_id) {
				collect_fonts_from_resources(resources, &mut fonts, self);
			}
		}
		fonts
	}

	pub fn decode_text(encoding: Option<&str>, bytes: &[u8]) -> String {
		if let Some(encoding) = encoding {
			info!("{}", encoding);
			match encoding {
				"StandardEncoding" => bytes_to_string(encodings::STANDARD_ENCODING, bytes),
				"MacRomanEncoding" => bytes_to_string(encodings::MAC_ROMAN_ENCODING, bytes),
				"MacExpertEncoding" => bytes_to_string(encodings::MAC_EXPERT_ENCODING, bytes),
				"WinAnsiEncoding" => bytes_to_string(encodings::WIN_ANSI_ENCODING, bytes),
				"UniGB-UCS2-H" | "UniGB−UTF16−H" => UTF_16BE.decode(bytes, DecoderTrap::Ignore).unwrap(),
				"Identity-H" => "?Identity-H Unimplemented?".to_string(), // Unimplemented
				_ => String::from_utf8_lossy(bytes).to_string(),
			}
		} else {
			bytes_to_string(encodings::STANDARD_ENCODING, bytes)
		}
	}

	pub fn encode_text(encoding: Option<&str>, text: &str) -> Vec<u8> {
		if let Some(encoding) = encoding {
			match encoding {
				"StandardEncoding" => string_to_bytes(encodings::STANDARD_ENCODING, text),
				"MacRomanEncoding" => string_to_bytes(encodings::MAC_ROMAN_ENCODING, text),
				"MacExpertEncoding" => string_to_bytes(encodings::MAC_EXPERT_ENCODING, text),
				"WinAnsiEncoding" => string_to_bytes(encodings::WIN_ANSI_ENCODING, text),
				"UniGB-UCS2-H" | "UniGB−UTF16−H" => UTF_16BE.encode(text, EncoderTrap::Ignore).unwrap(),
				"Identity-H" => vec![], // Unimplemented
				_ => text.as_bytes().to_vec(),
			}
		} else {
			string_to_bytes(encodings::STANDARD_ENCODING, text)
		}
	}
}

impl Default for Document {
	fn default() -> Self {
		Self::new()
	}
}
<|endoftext|>


<commit_before>use crate::TextRange;

use ra_syntax::ast::PatKind;
use ra_syntax::{
    algo::visit::{visitor, Visitor},
    ast::{self, AttrsOwner, NameOwner, TypeAscriptionOwner, TypeParamsOwner},
    AstNode, SourceFile, SyntaxKind, SyntaxNode, WalkEvent,
};

#[derive(Debug, Clone)]
pub struct StructureNode {
    pub parent: Option<usize>,
    pub label: String,
    pub navigation_range: TextRange,
    pub node_range: TextRange,
    pub kind: SyntaxKind,
    pub detail: Option<String>,
    pub deprecated: bool,
}

pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
    let mut res = Vec::new();
    let mut stack = Vec::new();

    for event in file.syntax().preorder() {
        match event {
            WalkEvent::Enter(node) => {
                if let Some(mut symbol) = structure_node(&node) {
                    symbol.parent = stack.last().copied();
                    stack.push(res.len());
                    res.push(symbol);
                }
            }
            WalkEvent::Leave(node) => {
                if structure_node(&node).is_some() {
                    stack.pop().unwrap();
                }
            }
        }
    }
    res
}

fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
    fn decl<N: NameOwner + AttrsOwner>(node: N) -> Option<StructureNode> {
        decl_with_detail(node, None)
    }

    fn decl_with_ascription<N: NameOwner + AttrsOwner + TypeAscriptionOwner>(
        node: N,
    ) -> Option<StructureNode> {
        let ty = node.ascribed_type();
        decl_with_type_ref(node, ty)
    }

    fn decl_with_type_ref<N: NameOwner + AttrsOwner>(
        node: N,
        type_ref: Option<ast::TypeRef>,
    ) -> Option<StructureNode> {
        let detail = type_ref.map(|type_ref| {
            let mut detail = String::new();
            collapse_ws(type_ref.syntax(), &mut detail);
            detail
        });
        decl_with_detail(node, detail)
    }

    fn decl_with_detail<N: NameOwner + AttrsOwner>(
        node: N,
        detail: Option<String>,
    ) -> Option<StructureNode> {
        let name = node.name()?;

        Some(StructureNode {
            parent: None,
            label: name.text().to_string(),
            navigation_range: name.syntax().text_range(),
            node_range: node.syntax().text_range(),
            kind: node.syntax().kind(),
            detail,
            deprecated: node.attrs().filter_map(|x| x.as_named()).any(|x| x == "deprecated"),
        })
    }

    fn collapse_ws(node: &SyntaxNode, output: &mut String) {
        let mut can_insert_ws = false;
        node.text().for_each_chunk(|chunk| {
            for line in chunk.lines() {
                let line = line.trim();
                if line.is_empty() {
                    if can_insert_ws {
                        output.push(' ');
                        can_insert_ws = false;
                    }
                } else {
                    output.push_str(line);
                    can_insert_ws = true;
                }
            }
        })
    }

    visitor()
        .visit(|fn_def: ast::FnDef| {
            let mut detail = String::from("fn");
            if let Some(type_param_list) = fn_def.type_param_list() {
                collapse_ws(type_param_list.syntax(), &mut detail);
            }
            if let Some(param_list) = fn_def.param_list() {
                collapse_ws(param_list.syntax(), &mut detail);
            }
            if let Some(ret_type) = fn_def.ret_type() {
                detail.push_str(" ");
                collapse_ws(ret_type.syntax(), &mut detail);
            }

            decl_with_detail(fn_def, Some(detail))
        })
        .visit(decl::<ast::StructDef>)
        .visit(decl::<ast::EnumDef>)
        .visit(decl::<ast::EnumVariant>)
        .visit(decl::<ast::TraitDef>)
        .visit(decl::<ast::Module>)
        .visit(|td: ast::TypeAliasDef| {
            let ty = td.type_ref();
            decl_with_type_ref(td, ty)
        })
        .visit(decl_with_ascription::<ast::NamedFieldDef>)
        .visit(decl_with_ascription::<ast::ConstDef>)
        .visit(decl_with_ascription::<ast::StaticDef>)
        .visit(|im: ast::ImplBlock| {
            let target_type = im.target_type()?;
            let target_trait = im.target_trait();
            let label = match target_trait {
                None => format!("impl {}", target_type.syntax().text()),
                Some(t) => {
                    format!("impl {} for {}", t.syntax().text(), target_type.syntax().text(),)
                }
            };

            let node = StructureNode {
                parent: None,
                label,
                navigation_range: target_type.syntax().text_range(),
                node_range: im.syntax().text_range(),
                kind: im.syntax().kind(),
                detail: None,
                deprecated: false,
            };
            Some(node)
        })
        .visit(|mc: ast::MacroCall| {
            let first_token = mc.syntax().first_token().unwrap();
            if first_token.text().as_str() != "macro_rules" {
                return None;
            }
            decl(mc)
        })
        .visit(|let_statement: &ast::LetStmt| {
            let let_syntax = let_statement.syntax();

            let mut label = String::new();
            collapse_ws(let_syntax, &mut label);

            let pat = match let_statement.pat()?.kind() {
                PatKind::BindPat(bind_pat) => bind_pat,
                _ => return None,
            };

            Some(StructureNode {
                parent: None,
                label,
                navigation_range: pat.syntax().range(),
                node_range: let_syntax.range(),
                kind: let_syntax.kind(),
                detail: None,
                deprecated: false,
            })
        })
        .accept(&node)?
}

#[cfg(test)]
mod tests {
    use super::*;
    use insta::assert_debug_snapshot_matches;

    #[test]
    fn test_file_structure() {
        let file = SourceFile::parse(
            r#"
struct Foo {
    x: i32
}

mod m {
    fn bar1() {}
    fn bar2<T>(t: T) -> T {}
    fn bar3<A,
        B>(a: A,
        b: B) -> Vec<
        u32
    > {}
}

enum E { X, Y(i32) }
type T = ();
static S: i32 = 92;
const C: i32 = 92;

impl E {}

impl fmt::Debug for E {}

macro_rules! mc {
    () => {}
}

#[deprecated]
fn obsolete() {}

#[deprecated(note = "for awhile")]
fn very_obsolete() {}
"#,
        )
        .ok()
        .unwrap();
        let structure = file_structure(&file);
        assert_debug_snapshot_matches!("file_structure", structure);
    }
}
<commit_msg>Fix rebase issue<commit_after>use crate::TextRange;

use ra_syntax::ast::PatKind;
use ra_syntax::{
    algo::visit::{visitor, Visitor},
    ast::{self, AttrsOwner, NameOwner, TypeAscriptionOwner, TypeParamsOwner},
    AstNode, SourceFile, SyntaxKind, SyntaxNode, WalkEvent,
};

#[derive(Debug, Clone)]
pub struct StructureNode {
    pub parent: Option<usize>,
    pub label: String,
    pub navigation_range: TextRange,
    pub node_range: TextRange,
    pub kind: SyntaxKind,
    pub detail: Option<String>,
    pub deprecated: bool,
}

pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
    let mut res = Vec::new();
    let mut stack = Vec::new();

    for event in file.syntax().preorder() {
        match event {
            WalkEvent::Enter(node) => {
                if let Some(mut symbol) = structure_node(&node) {
                    symbol.parent = stack.last().copied();
                    stack.push(res.len());
                    res.push(symbol);
                }
            }
            WalkEvent::Leave(node) => {
                if structure_node(&node).is_some() {
                    stack.pop().unwrap();
                }
            }
        }
    }
    res
}

fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
    fn decl<N: NameOwner + AttrsOwner>(node: N) -> Option<StructureNode> {
        decl_with_detail(node, None)
    }

    fn decl_with_ascription<N: NameOwner + AttrsOwner + TypeAscriptionOwner>(
        node: N,
    ) -> Option<StructureNode> {
        let ty = node.ascribed_type();
        decl_with_type_ref(node, ty)
    }

    fn decl_with_type_ref<N: NameOwner + AttrsOwner>(
        node: N,
        type_ref: Option<ast::TypeRef>,
    ) -> Option<StructureNode> {
        let detail = type_ref.map(|type_ref| {
            let mut detail = String::new();
            collapse_ws(type_ref.syntax(), &mut detail);
            detail
        });
        decl_with_detail(node, detail)
    }

    fn decl_with_detail<N: NameOwner + AttrsOwner>(
        node: N,
        detail: Option<String>,
    ) -> Option<StructureNode> {
        let name = node.name()?;

        Some(StructureNode {
            parent: None,
            label: name.text().to_string(),
            navigation_range: name.syntax().text_range(),
            node_range: node.syntax().text_range(),
            kind: node.syntax().kind(),
            detail,
            deprecated: node.attrs().filter_map(|x| x.as_named()).any(|x| x == "deprecated"),
        })
    }

    fn collapse_ws(node: &SyntaxNode, output: &mut String) {
        let mut can_insert_ws = false;
        node.text().for_each_chunk(|chunk| {
            for line in chunk.lines() {
                let line = line.trim();
                if line.is_empty() {
                    if can_insert_ws {
                        output.push(' ');
                        can_insert_ws = false;
                    }
                } else {
                    output.push_str(line);
                    can_insert_ws = true;
                }
            }
        })
    }

    visitor()
        .visit(|fn_def: ast::FnDef| {
            let mut detail = String::from("fn");
            if let Some(type_param_list) = fn_def.type_param_list() {
                collapse_ws(type_param_list.syntax(), &mut detail);
            }
            if let Some(param_list) = fn_def.param_list() {
                collapse_ws(param_list.syntax(), &mut detail);
            }
            if let Some(ret_type) = fn_def.ret_type() {
                detail.push_str(" ");
                collapse_ws(ret_type.syntax(), &mut detail);
            }

            decl_with_detail(fn_def, Some(detail))
        })
        .visit(decl::<ast::StructDef>)
        .visit(decl::<ast::EnumDef>)
        .visit(decl::<ast::EnumVariant>)
        .visit(decl::<ast::TraitDef>)
        .visit(decl::<ast::Module>)
        .visit(|td: ast::TypeAliasDef| {
            let ty = td.type_ref();
            decl_with_type_ref(td, ty)
        })
        .visit(decl_with_ascription::<ast::NamedFieldDef>)
        .visit(decl_with_ascription::<ast::ConstDef>)
        .visit(decl_with_ascription::<ast::StaticDef>)
        .visit(|im: ast::ImplBlock| {
            let target_type = im.target_type()?;
            let target_trait = im.target_trait();
            let label = match target_trait {
                None => format!("impl {}", target_type.syntax().text()),
                Some(t) => {
                    format!("impl {} for {}", t.syntax().text(), target_type.syntax().text(),)
                }
            };

            let node = StructureNode {
                parent: None,
                label,
                navigation_range: target_type.syntax().text_range(),
                node_range: im.syntax().text_range(),
                kind: im.syntax().kind(),
                detail: None,
                deprecated: false,
            };
            Some(node)
        })
        .visit(|mc: ast::MacroCall| {
            let first_token = mc.syntax().first_token().unwrap();
            if first_token.text().as_str() != "macro_rules" {
                return None;
            }
            decl(mc)
        })
        .visit(|let_statement: ast::LetStmt| {
            let let_syntax = let_statement.syntax();

            let mut label = String::new();
            collapse_ws(let_syntax, &mut label);

            let pat = match let_statement.pat()?.kind() {
                PatKind::BindPat(bind_pat) => bind_pat,
                _ => return None,
            };

            Some(StructureNode {
                parent: None,
                label,
                navigation_range: pat.syntax().range(),
                node_range: let_syntax.range(),
                kind: let_syntax.kind(),
                detail: None,
                deprecated: false,
            })
        })
        .accept(&node)?
}

#[cfg(test)]
mod tests {
    use super::*;
    use insta::assert_debug_snapshot_matches;

    #[test]
    fn test_file_structure() {
        let file = SourceFile::parse(
            r#"
struct Foo {
    x: i32
}

mod m {
    fn bar1() {}
    fn bar2<T>(t: T) -> T {}
    fn bar3<A,
        B>(a: A,
        b: B) -> Vec<
        u32
    > {}
}

enum E { X, Y(i32) }
type T = ();
static S: i32 = 92;
const C: i32 = 92;

impl E {}

impl fmt::Debug for E {}

macro_rules! mc {
    () => {}
}

#[deprecated]
fn obsolete() {}

#[deprecated(note = "for awhile")]
fn very_obsolete() {}
"#,
        )
        .ok()
        .unwrap();
        let structure = file_structure(&file);
        assert_debug_snapshot_matches!("file_structure", structure);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
mod macros;

use coerce::{AsBool,AsNumber};

use french_press::ScopeManager;
use js_types::binding::Binding;
use js_types::js_var::{JsVar, JsType};
use js_types::js_var::JsType::*;

use jsrs_parser::lalr::parse_Stmt;
use jsrs_common::ast::*;
use jsrs_common::ast::Exp::*;
use jsrs_common::ast::BinOp::*;
use jsrs_common::ast::Stmt::*;

pub fn eval_string(string: &str, state: &mut ScopeManager) -> JsVar {
    match parse_Stmt(string) {
        Ok(stmt) => eval_stmt(&stmt, state),
        //Err(e) => JsError(format!("{:?}", e))
        Err(_) => unimplemented!()
    }
    //eval_stmt(parse_Stmt(string).unwrap(), state)
}

pub fn eval_stmt(s: &Stmt, mut state: &mut ScopeManager) -> JsVar {
    match *s {
        Assign(ref var_string, ref exp) => {
            // TODO: this is a hack to return the value properly, which should be changed once we
            // stop using HashMap to store state.
            let mut var = eval_exp(exp, state);
            let cloned = var.clone();
            var.binding = Binding::new(var_string.clone());
            match state.alloc(var, None) {
                Ok(_) => (),
                e @ Err(_) => println!("{:?}", e),
            }
            cloned
        },
        BareExp(ref exp) => eval_exp(exp, &mut state),
        Decl(ref var_string, ref exp) => {
            let mut var = eval_exp(exp, state);
            var.binding = Binding::new(var_string.clone());
            // TODO: use value
            match state.alloc(var.clone(), None) {
                Ok(_) => var,
                e @ Err(_) => panic!("{:?}", e),
            }
        },
        If(ref condition, ref if_block, ref else_block) => {
            if eval_exp(&condition, state).as_bool() {
                eval_stmt(&*if_block, state)
            } else {
                if let Some(ref block) = *else_block {
                    eval_stmt(&*block, state)
                } else {
                    JsVar::new(JsType::JsUndef)
                }
            }
        },
        Ret(_) => panic!("unimplemented: ret statement"),
        Seq(ref s1, ref s2) => {
            let _exp = eval_stmt(&*s1, &mut state);
            eval_stmt(&*s2, &mut state)
        },
        While(ref condition, ref block) => {
            let mut ret_val = JsVar::new(JsUndef);
            loop {
                if eval_exp(&condition, state).as_bool() {
                    ret_val = eval_stmt(&*block, state)
                } else {
                    return ret_val
                }
            }
        }
    }
}

pub fn eval_exp(e: &Exp, mut state: &mut ScopeManager) -> JsVar {
    match e {
        &BinExp(ref e1, ref op, ref e2) => {
            let val1 = eval_exp(e1, state);
            let val2 = eval_exp(e2, state);

            match *op {
                And => JsVar::new(JsBool(val1.as_bool() && val2.as_bool())),
                Or  => JsVar::new(JsBool(val1.as_bool() || val2.as_bool())),

                Ge  => JsVar::new(JsBool(val1.as_bool() >= val2.as_bool())),
                Gt  => JsVar::new(JsBool(val1.as_bool() >  val2.as_bool())),
                Le  => JsVar::new(JsBool(val1.as_bool() <= val2.as_bool())),
                Lt  => JsVar::new(JsBool(val1.as_bool() <  val2.as_bool())),
                Neq => JsVar::new(JsBool(val1.as_bool() != val2.as_bool())),
                Eql => JsVar::new(JsBool(val1.as_bool() == val2.as_bool())),

                Minus => JsVar::new(JsNum(val1.as_number() - val2.as_number())),
                Plus  => JsVar::new(JsNum(val1.as_number() + val2.as_number())),
                Slash => JsVar::new(JsNum(val1.as_number() / val2.as_number())),
                Star  => JsVar::new(JsNum(val1.as_number() * val2.as_number())),
            }
        }
        &Bool(b) => JsVar::new(JsBool(b)),
        &Call(_, _) => {
            unimplemented!()
            //// TODO: create scope with arguments
            //let fun_name = eval_exp(fun_exp, state);
            //match fun_name {
            //    JsFunction(_, _, stmt) => eval_stmt(&*stmt, state),
            //    _ => panic!("TypeError: {} is not a function.", fun_name)
            //}
        },
        &Defun(_, _, _) => {
            unimplemented!()
            // TODO unimpl
            //if let Some(ref var) = *opt_var {
            //    let f = JsFunction(var.clone(), params.clone(), (*block).clone());
            //    state.insert(var.clone(), f);
            //    JsUndefined
            //} else {
            //    JsFunction(String::from(""), params.clone(), (*block).clone())
            //}
        },
        &Float(f) => JsVar::new(JsType::JsNum(f)),
        &Neg(ref exp) => JsVar::new(JsNum(-eval_exp(exp, state).as_number())),
        &Pos(ref exp) => JsVar::new(JsNum(eval_exp(exp, state).as_number())),

        &PostDec(ref exp) => eval_float_post_op!(exp, f, f - 1.0, state),
        &PostInc(ref exp) => eval_float_post_op!(exp, f, f + 1.0, state),
        &PreDec(ref exp)  => eval_float_pre_op!(exp, f, f - 1.0, state),
        &PreInc(ref exp)  => eval_float_pre_op!(exp, f, f + 1.0, state),

        &NewObject(_, _) => unimplemented!(),
        &Object(_) => unimplemented!(),
        &Undefined => JsVar::new(JsUndef),
        &Var(ref var_binding) => {
            match state.load(&Binding::new(var_binding.clone())) {
                Ok((var, _)) => var,
                _ => panic!(format!("ReferenceError: {} is not defined", var_binding))
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::collections::hash_set::HashSet;
    use french_press::init_gc;
    use french_press::js_types::js_type::{JsType, Binding};

    #[test]
    fn test_eval_literals() {
        let mut state = init_gc();
        assert_eq!(JsType::JsNum(5.0f64), eval_string("5.0;\n", &mut state).t);
        assert_eq!(JsType::JsNum(0.0f64), eval_string("0.0;\n", &mut state).t);
        assert_eq!(JsType::JsUndef, eval_string("undefined;\n", &mut state).t);
    }

    //// TODO: handle `var` and no `var` separately
    //#[test]
    //fn test_store_state() {
    //    let mut state = HashMap::new();
    //    assert_eq!(JsUndefined, eval_string("var a = 1;\n", &mut state));
    //    assert_eq!(JsNumber(2.0f64), eval_string("a = 2;\n", &mut state));
    //    assert_eq!(JsUndefined, eval_string("var b = 3;\n", &mut state));
    //    assert_eq!(JsNumber(4.0f64), eval_string("c = 4;\n", &mut state));
    //}

    #[test]
    fn test_inc_dec() {
        let mut state = init_gc();
        //assert_eq!(JsType::JsNum(1.0f64), eval_string("var a = 1;\n", &mut state).t);
        //assert_eq!(&JsType::JsNum(1.0), state.load(&Binding::new("a")).unwrap());

        //assert_eq!(JsType::JsNum(1.0f64), eval_string("a++;\n", &mut state));
        //assert_eq!(&JsNumber(2.0f64), state.get("a").unwrap());

        //assert_eq!(JsNumber(3.0f64), eval_string("++a;\n", &mut state));
        //assert_eq!(&JsNumber(3.0f64), state.get("a").unwrap());

        //assert_eq!(JsNumber(3.0f64), eval_string("a--;\n", &mut state));
        //assert_eq!(&JsNumber(2.0f64), state.get("a").unwrap());

        //assert_eq!(JsNumber(1.0f64), eval_string("--a;\n", &mut state));
        //assert_eq!(&JsNumber(1.0f64), state.get("a").unwrap());
    }

    #[test]
    fn test_binexp() {
        let mut state = init_gc();
        assert_eq!(JsType::JsNum(6.0f64),  eval_string("2.0 + 4.0;\n", &mut state).t);
        assert_eq!(JsType::JsNum(0.5f64),  eval_string("2.0 / 4.0;\n", &mut state).t);
        assert_eq!(JsType::JsNum(-2.0f64), eval_string("2.0 - 4.0;\n", &mut state).t);
        assert_eq!(JsType::JsNum(8.0f64),  eval_string("2.0 * 4.0;\n", &mut state).t);
    }
}
<commit_msg>fix imports in tests<commit_after>#[macro_use]
mod macros;

use coerce::{AsBool,AsNumber};

use french_press::ScopeManager;
use js_types::binding::Binding;
use js_types::js_var::{JsVar, JsType};
use js_types::js_var::JsType::*;

use jsrs_parser::lalr::parse_Stmt;
use jsrs_common::ast::*;
use jsrs_common::ast::Exp::*;
use jsrs_common::ast::BinOp::*;
use jsrs_common::ast::Stmt::*;

pub fn eval_string(string: &str, state: &mut ScopeManager) -> JsVar {
    match parse_Stmt(string) {
        Ok(stmt) => eval_stmt(&stmt, state),
        //Err(e) => JsError(format!("{:?}", e))
        Err(_) => unimplemented!()
    }
    //eval_stmt(parse_Stmt(string).unwrap(), state)
}

pub fn eval_stmt(s: &Stmt, mut state: &mut ScopeManager) -> JsVar {
    match *s {
        Assign(ref var_string, ref exp) => {
            // TODO: this is a hack to return the value properly, which should be changed once we
            // stop using HashMap to store state.
            let mut var = eval_exp(exp, state);
            let cloned = var.clone();
            var.binding = Binding::new(var_string.clone());
            match state.alloc(var, None) {
                Ok(_) => (),
                e @ Err(_) => println!("{:?}", e),
            }
            cloned
        },
        BareExp(ref exp) => eval_exp(exp, &mut state),
        Decl(ref var_string, ref exp) => {
            let mut var = eval_exp(exp, state);
            var.binding = Binding::new(var_string.clone());
            // TODO: use value
            match state.alloc(var.clone(), None) {
                Ok(_) => var,
                e @ Err(_) => panic!("{:?}", e),
            }
        },
        If(ref condition, ref if_block, ref else_block) => {
            if eval_exp(&condition, state).as_bool() {
                eval_stmt(&*if_block, state)
            } else {
                if let Some(ref block) = *else_block {
                    eval_stmt(&*block, state)
                } else {
                    JsVar::new(JsType::JsUndef)
                }
            }
        },
        Ret(_) => panic!("unimplemented: ret statement"),
        Seq(ref s1, ref s2) => {
            let _exp = eval_stmt(&*s1, &mut state);
            eval_stmt(&*s2, &mut state)
        },
        While(ref condition, ref block) => {
            let mut ret_val = JsVar::new(JsUndef);
            loop {
                if eval_exp(&condition, state).as_bool() {
                    ret_val = eval_stmt(&*block, state)
                } else {
                    return ret_val
                }
            }
        }
    }
}

pub fn eval_exp(e: &Exp, mut state: &mut ScopeManager) -> JsVar {
    match e {
        &BinExp(ref e1, ref op, ref e2) => {
            let val1 = eval_exp(e1, state);
            let val2 = eval_exp(e2, state);

            match *op {
                And => JsVar::new(JsBool(val1.as_bool() && val2.as_bool())),
                Or  => JsVar::new(JsBool(val1.as_bool() || val2.as_bool())),

                Ge  => JsVar::new(JsBool(val1.as_bool() >= val2.as_bool())),
                Gt  => JsVar::new(JsBool(val1.as_bool() >  val2.as_bool())),
                Le  => JsVar::new(JsBool(val1.as_bool() <= val2.as_bool())),
                Lt  => JsVar::new(JsBool(val1.as_bool() <  val2.as_bool())),
                Neq => JsVar::new(JsBool(val1.as_bool() != val2.as_bool())),
                Eql => JsVar::new(JsBool(val1.as_bool() == val2.as_bool())),

                Minus => JsVar::new(JsNum(val1.as_number() - val2.as_number())),
                Plus  => JsVar::new(JsNum(val1.as_number() + val2.as_number())),
                Slash => JsVar::new(JsNum(val1.as_number() / val2.as_number())),
                Star  => JsVar::new(JsNum(val1.as_number() * val2.as_number())),
            }
        }
        &Bool(b) => JsVar::new(JsBool(b)),
        &Call(_, _) => {
            unimplemented!()
            //// TODO: create scope with arguments
            //let fun_name = eval_exp(fun_exp, state);
            //match fun_name {
            //    JsFunction(_, _, stmt) => eval_stmt(&*stmt, state),
            //    _ => panic!("TypeError: {} is not a function.", fun_name)
            //}
        },
        &Defun(_, _, _) => {
            unimplemented!()
            // TODO unimpl
            //if let Some(ref var) = *opt_var {
            //    let f = JsFunction(var.clone(), params.clone(), (*block).clone());
            //    state.insert(var.clone(), f);
            //    JsUndefined
            //} else {
            //    JsFunction(String::from(""), params.clone(), (*block).clone())
            //}
        },
        &Float(f) => JsVar::new(JsType::JsNum(f)),
        &Neg(ref exp) => JsVar::new(JsNum(-eval_exp(exp, state).as_number())),
        &Pos(ref exp) => JsVar::new(JsNum(eval_exp(exp, state).as_number())),

        &PostDec(ref exp) => eval_float_post_op!(exp, f, f - 1.0, state),
        &PostInc(ref exp) => eval_float_post_op!(exp, f, f + 1.0, state),
        &PreDec(ref exp)  => eval_float_pre_op!(exp, f, f - 1.0, state),
        &PreInc(ref exp)  => eval_float_pre_op!(exp, f, f + 1.0, state),

        &NewObject(_, _) => unimplemented!(),
        &Object(_) => unimplemented!(),
        &Undefined => JsVar::new(JsUndef),
        &Var(ref var_binding) => {
            match state.load(&Binding::new(var_binding.clone())) {
                Ok((var, _)) => var,
                _ => panic!(format!("ReferenceError: {} is not defined", var_binding))
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::collections::hash_set::HashSet;
    use french_press::init_gc;
    use js_types::js_var::JsType;
    use js_types::binding::Binding;

    #[test]
    fn test_eval_literals() {
        let mut state = init_gc();
        assert_eq!(JsType::JsNum(5.0f64), eval_string("5.0;\n", &mut state).t);
        assert_eq!(JsType::JsNum(0.0f64), eval_string("0.0;\n", &mut state).t);
        assert_eq!(JsType::JsUndef, eval_string("undefined;\n", &mut state).t);
    }

    //// TODO: handle `var` and no `var` separately
    //#[test]
    //fn test_store_state() {
    //    let mut state = HashMap::new();
    //    assert_eq!(JsUndefined, eval_string("var a = 1;\n", &mut state));
    //    assert_eq!(JsNumber(2.0f64), eval_string("a = 2;\n", &mut state));
    //    assert_eq!(JsUndefined, eval_string("var b = 3;\n", &mut state));
    //    assert_eq!(JsNumber(4.0f64), eval_string("c = 4;\n", &mut state));
    //}

    #[test]
    fn test_inc_dec() {
        let mut state = init_gc();
        //assert_eq!(JsType::JsNum(1.0f64), eval_string("var a = 1;\n", &mut state).t);
        //assert_eq!(&JsType::JsNum(1.0), state.load(&Binding::new("a")).unwrap());

        //assert_eq!(JsType::JsNum(1.0f64), eval_string("a++;\n", &mut state));
        //assert_eq!(&JsNumber(2.0f64), state.get("a").unwrap());

        //assert_eq!(JsNumber(3.0f64), eval_string("++a;\n", &mut state));
        //assert_eq!(&JsNumber(3.0f64), state.get("a").unwrap());

        //assert_eq!(JsNumber(3.0f64), eval_string("a--;\n", &mut state));
        //assert_eq!(&JsNumber(2.0f64), state.get("a").unwrap());

        //assert_eq!(JsNumber(1.0f64), eval_string("--a;\n", &mut state));
        //assert_eq!(&JsNumber(1.0f64), state.get("a").unwrap());
    }

    #[test]
    fn test_binexp() {
        let mut state = init_gc();
        assert_eq!(JsType::JsNum(6.0f64),  eval_string("2.0 + 4.0;\n", &mut state).t);
        assert_eq!(JsType::JsNum(0.5f64),  eval_string("2.0 / 4.0;\n", &mut state).t);
        assert_eq!(JsType::JsNum(-2.0f64), eval_string("2.0 - 4.0;\n", &mut state).t);
        assert_eq!(JsType::JsNum(8.0f64),  eval_string("2.0 * 4.0;\n", &mut state).t);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 fd developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use super::CommandTemplate;
use internal::print_error_and_exit;
use std::path::PathBuf;
use std::sync::mpsc::Receiver;
use std::sync::{Arc, Mutex};
use walk::WorkerResult;

/// An event loop that listens for inputs from the `rx` receiver. Each received input will
/// generate a command with the supplied command template. The generated command will then
/// be executed, and this process will continue until the receiver's sender has closed.
pub fn job(
    rx: Arc<Mutex<Receiver<WorkerResult>>>,
    cmd: Arc<CommandTemplate>,
    out_perm: Arc<Mutex<()>>,
) {
    loop {
        // Create a lock on the shared receiver for this thread.
        let lock = rx.lock().unwrap();

        // Obtain the next path from the receiver, else if the channel
        // has closed, exit from the loop
        let value: PathBuf = match lock.recv() {
            Ok(value) => match value {
                WorkerResult::Entry(val) => val,
                WorkerResult::Error(err) => {
                    print_error_and_exit(&format!("{}", err));
                }
            },
            Err(_) => break,
        };

        // Drop the lock so that other threads can read from the the receiver.
        drop(lock);
        // Generate a command and execute it.
        cmd.generate_and_execute(&value, Arc::clone(&out_perm));
    }
}
<commit_msg>--exec: Do not exit on errors<commit_after>// Copyright (c) 2017 fd developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use super::CommandTemplate;
use internal::print_error;
use std::path::PathBuf;
use std::sync::mpsc::Receiver;
use std::sync::{Arc, Mutex};
use walk::WorkerResult;

/// An event loop that listens for inputs from the `rx` receiver. Each received input will
/// generate a command with the supplied command template. The generated command will then
/// be executed, and this process will continue until the receiver's sender has closed.
pub fn job(
    rx: Arc<Mutex<Receiver<WorkerResult>>>,
    cmd: Arc<CommandTemplate>,
    out_perm: Arc<Mutex<()>>,
) {
    loop {
        // Create a lock on the shared receiver for this thread.
        let lock = rx.lock().unwrap();

        // Obtain the next result from the receiver, else if the channel
        // has closed, exit from the loop
        let value: PathBuf = match lock.recv() {
            Ok(WorkerResult::Entry(val)) => val,
            Ok(WorkerResult::Error(err)) => {
                print_error(&format!("{}", err));
                continue;
            }
            Err(_) => break,
        };

        // Drop the lock so that other threads can read from the the receiver.
        drop(lock);
        // Generate a command and execute it.
        cmd.generate_and_execute(&value, Arc::clone(&out_perm));
    }
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

use logger;
use env;
use std::process::Command;

pub struct Executor {
}

impl Executor {
    pub fn new() -> Executor {
        Executor{}
    }

    pub fn start(&self, l: &logger::Logger, e: &env::Env) {
        let es = e.getScript().to_string() + " " + e.getDir();
        let res = Command::new(e.getScript())
            .arg(e.getDir()).status();
        match res {
            Ok(o) => {
                if o.success() {
                    let mut ss = "Executing ".to_string();
                    ss += &es;
                    ss += " OK!";
                    l.info(&ss);
                } else {
                    let os = o.code();
                    let mut ec = es;
                    match os {
                        None => {
                            ec += "Terminated by a signal!";
                        },
                        Some(t) => {
                            ec += " Exit code: ";
                            ec += &(format!("{}", t));
                        }
                    }
                    l.info(&ec);
                }
            },
            Err(e) => {
                let mut ss = "Error of executing ".to_string();
                ss += &es;
                ss += " ";
                ss += &(format!("{}", e));
                self.error__(ss, l);
            }
        }
    }

    fn error__(&self, s: String, l: &logger::Logger) {
        l.error(&s);
        panic!(s);
    }
}
<commit_msg>fix syslog out for Executor<commit_after>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

use logger;
use env;
use std::process::Command;

pub struct Executor {
}

impl Executor {
    pub fn new() -> Executor {
        Executor{}
    }

    pub fn start(&self, l: &logger::Logger, e: &env::Env) {
        let es = e.getScript().to_string() + " " + e.getDir();
        l.info("Trying execute command...");
        let res = Command::new(e.getScript())
            .arg(e.getDir()).status();
        match res {
            Ok(o) => {
                if o.success() {
                    let mut ss = "... ".to_string();
                    ss += &es;
                    ss += " OK!";
                    l.info(&ss);
                } else {
                    let os = o.code();
                    let mut ec = es;
                    match os {
                        None => {
                            ec += "Terminated by a signal!";
                        },
                        Some(t) => {
                            ec += " Exit code: ";
                            ec += &(format!("{}", t));
                        }
                    }
                    l.info(&ec);
                }
            },
            Err(e) => {
                let mut ss = "Error of executing ".to_string();
                ss += &es;
                ss += " ";
                ss += &(format!("{}", e));
                self.error__(ss, l);
            }
        }
    }

    fn error__(&self, s: String, l: &logger::Logger) {
        l.error(&s);
        panic!(s);
    }
}
<|endoftext|>


<commit_before>extern crate clap;
use clap::{App, Arg};
use dicom_ul::pdu::reader::{read_pdu, DEFAULT_MAX_PDU};
use dicom_ul::pdu::writer::write_pdu;
use dicom_ul::pdu::PDU;
use quick_error::quick_error;
use std::net::{Shutdown, TcpListener, TcpStream};
use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender};
use std::thread;
use std::thread::JoinHandle;

type Result<T> = std::result::Result<T, Error>;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: std::io::Error) {
            from()
        }
        DUL(err: dicom_ul::error::Error) {
            from()
        }
        ThreadPanicked {
            from()
        }
        RecvError(err: std::sync::mpsc::RecvError) {
            from()
        }
        SendError(err: std::sync::mpsc::SendError<ThreadMessage>) {
            from()
        }
    }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum ProviderType {
    SCP,
    SCU,
}

#[derive(Debug)]
pub enum ThreadMessage {
    SendPDU {
        to: ProviderType,
        pdu: PDU,
    },
    Err {
        from: ProviderType,
        err: dicom_ul::error::Error,
    },
    Shutdown {
        initiator: ProviderType,
    },
}

fn run(scu_stream: &mut TcpStream, destination_addr: &str) -> Result<()> {
    // Before we do anything, let's also open another connection to the destination
    // SCP.
    match TcpStream::connect(destination_addr) {
        Ok(ref mut scp_stream) => {
            let (message_tx, message_rx): (Sender<ThreadMessage>, Receiver<ThreadMessage>) =
                mpsc::channel();

            let scu_reader_thread: JoinHandle<Result<()>>;
            let scp_reader_thread: JoinHandle<Result<()>>;

            {
                let mut reader = scu_stream.try_clone()?;
                let message_tx = message_tx.clone();
                scu_reader_thread = thread::spawn(move || {
                    loop {
                        match read_pdu(&mut reader, DEFAULT_MAX_PDU) {
                            Ok(pdu) => {
                                message_tx.send(ThreadMessage::SendPDU {
                                    to: ProviderType::SCP,
                                    pdu,
                                })?;
                            }
                            Err(e) => {
                                if let dicom_ul::error::Error::NoPduAvailable = e {
                                    message_tx.send(ThreadMessage::Shutdown {
                                        initiator: ProviderType::SCU,
                                    })?;
                                } else {
                                    message_tx.send(ThreadMessage::Err {
                                        from: ProviderType::SCU,
                                        err: e,
                                    })?;
                                }
                                break;
                            }
                        }
                    }

                    Ok(())
                });
            }

            {
                let mut reader = scp_stream.try_clone()?;
                let message_tx = message_tx.clone();
                scp_reader_thread = thread::spawn(move || {
                    loop {
                        match read_pdu(&mut reader, DEFAULT_MAX_PDU) {
                            Ok(pdu) => {
                                message_tx.send(ThreadMessage::SendPDU {
                                    to: ProviderType::SCU,
                                    pdu,
                                })?;
                            }
                            Err(e) => {
                                if let dicom_ul::error::Error::NoPduAvailable = e {
                                    message_tx.send(ThreadMessage::Shutdown {
                                        initiator: ProviderType::SCP,
                                    })?;
                                } else {
                                    message_tx.send(ThreadMessage::Err {
                                        from: ProviderType::SCP,
                                        err: e,
                                    })?;
                                }
                                break;
                            }
                        }
                    }

                    Ok(())
                });
            }

            loop {
                let message = message_rx.recv()?;
                match message {
                    ThreadMessage::SendPDU { to, pdu } => match to {
                        ProviderType::SCU => {
                            println!("scu <---- scp: {:?}", &pdu);
                            write_pdu(scu_stream, &pdu).unwrap();
                        }
                        ProviderType::SCP => {
                            println!("scu ----> scp: {:?}", &pdu);
                            write_pdu(scp_stream, &pdu).unwrap();
                        }
                    },
                    ThreadMessage::Err { from, err } => {
                        println!("error from {:?}: {}", from, err);
                        break;
                    }
                    ThreadMessage::Shutdown { initiator } => {
                        println!("shutdown initiated from: {:?}", initiator);
                        break;
                    }
                }
            }

            scu_stream.shutdown(Shutdown::Read)?;
            scu_reader_thread
                .join()
                .map_err(|_| Error::ThreadPanicked)??;

            scp_stream.shutdown(Shutdown::Read)?;
            scp_reader_thread
                .join()
                .map_err(|_| Error::ThreadPanicked)??;

            Ok(())
        }
        Err(e) => {
            scu_stream.shutdown(Shutdown::Both)?;
            println!("error connection to destination SCP: {}", e);
            Err(e)?
        }
    }
}

fn main() {
    let matches = App::new("scpproxy")
        .arg(
            Arg::with_name("destination-host")
                .help("The destination host name (SCP)")
                .required(true)
                .index(1),
        )
        .arg(
            Arg::with_name("destination-port")
                .help("The destination host port (SCP)")
                .required(true)
                .index(2),
        )
        .arg(
            Arg::with_name("listen-port")
                .help("The port that we will listen for SCU connections on")
                .short("-lp")
                .long("--listen-port")
                .default_value("3333")
                .takes_value(true),
        )
        .get_matches();

    let destination_host = matches.value_of("destination-host").unwrap();
    let destination_port = matches.value_of("destination-port").unwrap();
    let listen_port = matches.value_of("listen-port").unwrap();

    let listen_addr = format!("0.0.0.0:{}", listen_port);
    let destination_addr = format!("{}:{}", destination_host, destination_port);

    let listener = TcpListener::bind(&listen_addr).unwrap();
    println!("listening on: {}", listen_addr);
    println!("forwarding to: {}", destination_addr);

    for mut stream in listener.incoming() {
        match stream {
            Ok(ref mut scu_stream) => {
                if let Err(e) = run(scu_stream, &destination_addr) {
                    println!("error: {}", e);
                }
            }
            Err(e) => {
                println!("error: {}", e);
            }
        }
    }
}
<commit_msg>Using stderr for errors.<commit_after>extern crate clap;
use clap::{App, Arg};
use dicom_ul::pdu::reader::{read_pdu, DEFAULT_MAX_PDU};
use dicom_ul::pdu::writer::write_pdu;
use dicom_ul::pdu::PDU;
use quick_error::quick_error;
use std::net::{Shutdown, TcpListener, TcpStream};
use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender};
use std::thread;
use std::thread::JoinHandle;

type Result<T> = std::result::Result<T, Error>;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: std::io::Error) {
            from()
        }
        DUL(err: dicom_ul::error::Error) {
            from()
        }
        ThreadPanicked {
            from()
        }
        RecvError(err: std::sync::mpsc::RecvError) {
            from()
        }
        SendError(err: std::sync::mpsc::SendError<ThreadMessage>) {
            from()
        }
    }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum ProviderType {
    SCP,
    SCU,
}

#[derive(Debug)]
pub enum ThreadMessage {
    SendPDU {
        to: ProviderType,
        pdu: PDU,
    },
    Err {
        from: ProviderType,
        err: dicom_ul::error::Error,
    },
    Shutdown {
        initiator: ProviderType,
    },
}

fn run(scu_stream: &mut TcpStream, destination_addr: &str) -> Result<()> {
    // Before we do anything, let's also open another connection to the destination
    // SCP.
    match TcpStream::connect(destination_addr) {
        Ok(ref mut scp_stream) => {
            let (message_tx, message_rx): (Sender<ThreadMessage>, Receiver<ThreadMessage>) =
                mpsc::channel();

            let scu_reader_thread: JoinHandle<Result<()>>;
            let scp_reader_thread: JoinHandle<Result<()>>;

            {
                let mut reader = scu_stream.try_clone()?;
                let message_tx = message_tx.clone();
                scu_reader_thread = thread::spawn(move || {
                    loop {
                        match read_pdu(&mut reader, DEFAULT_MAX_PDU) {
                            Ok(pdu) => {
                                message_tx.send(ThreadMessage::SendPDU {
                                    to: ProviderType::SCP,
                                    pdu,
                                })?;
                            }
                            Err(e) => {
                                if let dicom_ul::error::Error::NoPduAvailable = e {
                                    message_tx.send(ThreadMessage::Shutdown {
                                        initiator: ProviderType::SCU,
                                    })?;
                                } else {
                                    message_tx.send(ThreadMessage::Err {
                                        from: ProviderType::SCU,
                                        err: e,
                                    })?;
                                }
                                break;
                            }
                        }
                    }

                    Ok(())
                });
            }

            {
                let mut reader = scp_stream.try_clone()?;
                let message_tx = message_tx.clone();
                scp_reader_thread = thread::spawn(move || {
                    loop {
                        match read_pdu(&mut reader, DEFAULT_MAX_PDU) {
                            Ok(pdu) => {
                                message_tx.send(ThreadMessage::SendPDU {
                                    to: ProviderType::SCU,
                                    pdu,
                                })?;
                            }
                            Err(e) => {
                                if let dicom_ul::error::Error::NoPduAvailable = e {
                                    message_tx.send(ThreadMessage::Shutdown {
                                        initiator: ProviderType::SCP,
                                    })?;
                                } else {
                                    message_tx.send(ThreadMessage::Err {
                                        from: ProviderType::SCP,
                                        err: e,
                                    })?;
                                }
                                break;
                            }
                        }
                    }

                    Ok(())
                });
            }

            loop {
                let message = message_rx.recv()?;
                match message {
                    ThreadMessage::SendPDU { to, pdu } => match to {
                        ProviderType::SCU => {
                            println!("scu <---- scp: {:?}", &pdu);
                            write_pdu(scu_stream, &pdu).unwrap();
                        }
                        ProviderType::SCP => {
                            println!("scu ----> scp: {:?}", &pdu);
                            write_pdu(scp_stream, &pdu).unwrap();
                        }
                    },
                    ThreadMessage::Err { from, err } => {
                        eprintln!("error from {:?}: {}", from, err);
                        break;
                    }
                    ThreadMessage::Shutdown { initiator } => {
                        println!("shutdown initiated from: {:?}", initiator);
                        break;
                    }
                }
            }

            scu_stream.shutdown(Shutdown::Read)?;
            scu_reader_thread
                .join()
                .map_err(|_| Error::ThreadPanicked)??;

            scp_stream.shutdown(Shutdown::Read)?;
            scp_reader_thread
                .join()
                .map_err(|_| Error::ThreadPanicked)??;

            Ok(())
        }
        Err(e) => {
            scu_stream.shutdown(Shutdown::Both)?;
            eprintln!("error connection to destination SCP: {}", e);
            Err(e)?
        }
    }
}

fn main() {
    let matches = App::new("scpproxy")
        .arg(
            Arg::with_name("destination-host")
                .help("The destination host name (SCP)")
                .required(true)
                .index(1),
        )
        .arg(
            Arg::with_name("destination-port")
                .help("The destination host port (SCP)")
                .required(true)
                .index(2),
        )
        .arg(
            Arg::with_name("listen-port")
                .help("The port that we will listen for SCU connections on")
                .short("-lp")
                .long("--listen-port")
                .default_value("3333")
                .takes_value(true),
        )
        .get_matches();

    let destination_host = matches.value_of("destination-host").unwrap();
    let destination_port = matches.value_of("destination-port").unwrap();
    let listen_port = matches.value_of("listen-port").unwrap();

    let listen_addr = format!("0.0.0.0:{}", listen_port);
    let destination_addr = format!("{}:{}", destination_host, destination_port);

    let listener = TcpListener::bind(&listen_addr).unwrap();
    println!("listening on: {}", listen_addr);
    println!("forwarding to: {}", destination_addr);

    for mut stream in listener.incoming() {
        match stream {
            Ok(ref mut scu_stream) => {
                if let Err(e) = run(scu_stream, &destination_addr) {
                    eprintln!("error: {}", e);
                }
            }
            Err(e) => {
                eprintln!("error: {}", e);
            }
        }
    }
}
<|endoftext|>


<commit_before>use dicom_core::value::Value;
use dicom_object::open_file;
use dicom_test_files;

#[test]
fn test_ob_value_with_unknown_length() {
    let path =
        dicom_test_files::path("pydicom/JPEG2000.dcm").expect("test DICOM file should exist");
    let object = open_file(&path).unwrap();
    let element = object.element_by_name("PixelData").unwrap();

    match element.value() {
        Value::PixelSequence { fragments, .. } => {
            // check if the leading and trailing bytes look right
            assert_eq!(fragments.len(), 1);
            let fragment = &fragments[0];
            assert_eq!(fragment[0..2], [255, 79]);
            assert_eq!(fragment[fragment.len() - 2..fragment.len()], [255, 217]);
        }
        value => {
            panic!("expected a pixel sequence, but got {:?}", value);
        }
    }
}
<commit_msg>Add integration test<commit_after>use std::{fs::File, io::BufReader};

use dicom_core::value::Value;
use dicom_encoding::text::SpecificCharacterSet;
use dicom_object::{mem::InMemDicomObject, open_file};
use dicom_test_files;

#[test]
fn test_ob_value_with_unknown_length() {
    let path =
        dicom_test_files::path("pydicom/JPEG2000.dcm").expect("test DICOM file should exist");
    let object = open_file(&path).unwrap();
    let element = object.element_by_name("PixelData").unwrap();

    match element.value() {
        Value::PixelSequence { fragments, .. } => {
            // check if the leading and trailing bytes look right
            assert_eq!(fragments.len(), 1);
            let fragment = &fragments[0];
            assert_eq!(fragment[0..2], [255, 79]);
            assert_eq!(fragment[fragment.len() - 2..fragment.len()], [255, 217]);
        }
        value => {
            panic!("expected a pixel sequence, but got {:?}", value);
        }
    }
}

#[test]
fn test_expl_vr_le_no_meta() {
    let path = dicom_test_files::path("pydicom/ExplVR_LitEndNoMeta.dcm")
        .expect("test DICOM file should exist");
    let source = BufReader::new(File::open(path).unwrap());
    let ts = dicom_transfer_syntax_registry::entries::EXPLICIT_VR_LITTLE_ENDIAN.erased();
    let object =
        InMemDicomObject::read_dataset_with_ts_cs(source, &ts, SpecificCharacterSet::Default)
            .unwrap();

    let sop_instance_uid = object.element_by_name("SOPInstanceUID").unwrap();
    assert_eq!(sop_instance_uid.to_str().unwrap(), "1.2.333.4444.5.6.7.8",);

    let series_instance_uid = object.element_by_name("SeriesInstanceUID").unwrap();
    assert_eq!(
        series_instance_uid.to_str().unwrap(),
        "1.2.333.4444.5.6.7.8.99\0",
    );

    let frame_of_reference_uid = object.element_by_name("FrameOfReferenceUID").unwrap();
    assert_eq!(
        frame_of_reference_uid.to_str().unwrap(),
        "1.2.333.4444.5.6.7.8.9",
    );
}
<|endoftext|>


<commit_before>#![allow(unused_variables)]

use std::thread::Thread;

use super::square::{Square,Rank,File};
use super::moves::Move;
use super::color::{White,Black};
use super::piece::Piece;
use super::piece::Type::{Pawn,King,Queen,Bishop,Knight,Rook};
use super::pos::Position;
use super::castle::{Kingside,Queenside};

use self::Action::{Continue,Stop};

macro_rules! send {
    ($tx: expr, $x: expr) => ({
        match $tx.send_opt($x) {
            Ok(()) => (),
            Err(_) => return Stop,
        }
    })
}

enum Action {
    Continue,
    Stop,
}
impl Action {
    fn is_stop(&self) -> bool {
        match *self {
            Continue => false,
            Stop => true,
        }
    }
}

pub fn receive_psudo_legal(p: Position) -> Receiver<Move> {
    let (tx,rx) = sync_channel(0);
    Thread::spawn(move || gen_psudo_legal(&p, tx)).detach();
    rx
}

pub fn gen_psudo_legal(p: &Position, tx: SyncSender<Move>) {
    if gen_en_passant(p, &tx).is_stop() {
        return;
    }
    if gen_castle(p, &tx).is_stop() {
        return;
    }
    for file in range(0,8) {
        for rank in range(0,8) {
            if gen_move_from(p, Square::new(File(file),Rank(rank)), &tx).is_stop() {
                return;
            }
        }
    }
}

//Functions below return Err(()) if the receiver hung up.

fn gen_move_from(p: &Position, from: Square, tx: &SyncSender<Move>) -> Action {
    let piece_id = match p.at(from) {
        None => return Continue,
        Some(val) => val,
    };
    if piece_id.color() != p.side_to_move() {
        return Continue;
    }
    match piece_id.piece_type() {
        Pawn => gen_pawn_from(p, from, tx),
        Queen|Bishop|Rook => gen_slider_from(p, from, tx),
        King|Knight => gen_fixed_from(p, from, tx),
    }
}

// (file, rank)
type Diff = (int, int);

fn shift(s: Square, dir: Diff) -> Option<Square> {
    let (dx, dy) = dir;
    let (File(file), Rank(rank)) = s.to_tuple();
    Square::from_int(file as int + dx, rank as int + dy)
}

fn gen_slider_from(p: &Position, from: Square, tx: &SyncSender<Move>) -> Action {
    let rook_slide:   &[Diff] = &[(1,0), (0,1), (-1,0), (0,-1)];
    let bishop_slide: &[Diff] = &[(1,1), (1,-1), (-1,-1), (-1,1)];
    let queen_slide:  &[Diff] = &[(1,0), (0,1), (-1,0), (0,-1), (1,1), (1,-1), (-1,-1), (-1,1)];

    let piece_id = p.at(from).unwrap();
    let piece_type = piece_id.piece_type();
    let piece_color = piece_id.color();

    let slide = match piece_type {
        Rook => rook_slide,
        Bishop => bishop_slide,
        Queen => queen_slide,
        _ => panic!(),
    };

    for dir in slide.iter() {
        let mut curr_pos = shift(from, *dir);
        //while curr_pos is valid and there is no piece there.
        while curr_pos.is_some() && p.at(curr_pos.unwrap()).is_none() {
            let curr_move = Move::new(from, curr_pos.unwrap());
            send!(tx, curr_move);
            curr_pos = shift(curr_pos.unwrap(), *dir);
        }
        //if curr_pos is valid
        if curr_pos.is_some() {
            let to = curr_pos.unwrap();
            let dest: Option<Piece> = p.at(to);
            //that square is always occupied
            let dest_piece: Piece = dest.unwrap();
            let dest_color = dest_piece.color();
            //if there is an enemy at the destination
            if dest_color == piece_color.invert() {
                let curr_move = Move::new(from, to).set_capture(true);
                send!(tx, curr_move);
            }
        }
    }

    Continue
}

fn gen_fixed_from(p: &Position, from: Square, tx: &SyncSender<Move>) -> Action {
    let king_fixed:   &[Diff] = &[(1,0), (0,1), (-1,0), (0,-1), (1,1), (1,-1), (-1,-1), (-1,1)];
    let knight_fixed: &[Diff] = &[(2,1), (2,-1), (-2,-1), (-2,1), (1,2), (1,-2), (-1,-2), (-1,2)];

    let piece_id = p.at(from).unwrap();
    let piece_type = piece_id.piece_type();
    let piece_color = piece_id.color();

    let fixed = match piece_type {
        King => king_fixed,
        Knight => knight_fixed,
        _ => panic!(),
    };

    for dir in fixed.iter() {
        let new_pos = shift(from, *dir);
        if new_pos.is_some() {
            let to = new_pos.unwrap();
            let dest: Option<Piece> = p.at(to);
            let (is_valid, is_capture) = match dest {
                Some(val) => {
                    if val.color() == piece_color { (false, false) }
                    else { (true, true) }
                },
                None => (true, false),
            };
            if is_valid {
                let curr_move = Move::new(from, to).set_capture(is_capture);
                send!(tx, curr_move);
            }
        }
    }

    Continue
}

fn gen_pawn_from(p: &Position, from: Square, tx: &SyncSender<Move>) -> Action {
    let piece_color = p.at(from).unwrap().color();
    let (File(_), Rank(from_rank)) = from.to_tuple();
    //rank_up is the 1-based rank from the piece-owner's side.
    let (dy, rank_up): (int, u8) = match piece_color {
        White => ( 1, 1u8 + from_rank ),
        Black => (-1, 8u8 - from_rank ),
    };
    let move_dir: Diff = (0, dy);
    let to: Square = shift(from, move_dir).unwrap();
    // if destination is empty
    if p.at(to).is_none() {
        match rank_up {
            7 => {
                for new_piece in [Queen, Knight, Rook, Bishop].iter() {
                    let curr_move = Move::new(from, to).set_promote(Some(*new_piece));
                    send!(tx, curr_move);
                }
            },
            2 => {
                let curr_move = Move::new(from, to);
                send!(tx, curr_move);
                let to2: Square = shift(to, move_dir).unwrap();
                let curr_move2 = Move::new(from, to2).set_pawn_double_move(true);
                send!(tx, curr_move2);
            },
            _ => {
                let curr_move = Move::new(from, to);
                send!(tx, curr_move);
            },
        }
    }

    for dx in [1,-1].iter() {
        let capture_dir: Diff = (*dx, dy);
        let capture_new_pos: Option<Square> = shift(from, capture_dir);
        let capture_to: Square = match capture_new_pos {
            Some(val) => val,
            None => continue,
        };
        let dest: Option<Piece> = p.at(capture_to);
        let dest_piece: Piece = match dest {
            Some(val) => val,
            None => continue,
        };
        let dest_color = dest_piece.color();
        if dest_color == piece_color.invert() {
            if rank_up == 7 {
                for new_piece in [Queen, Knight, Rook, Bishop].iter() {
                    let curr_move = Move::new(from, capture_to).set_capture(true);
                    let curr_move = curr_move.set_promote(Some(*new_piece));
                    send!(tx, curr_move);
                }
            } else {
                let curr_move = Move::new(from, capture_to).set_capture(true);
                send!(tx, curr_move);
            }
        }
    }

    Continue
}

fn gen_en_passant(p: &Position, tx: &SyncSender<Move>) -> Action {
    let to_file = match p.en_passant() {
        Some(f) => f,
        None => return Continue,
    };
    let (from_rank, to_rank) = match p.side_to_move() {
        White => (Rank(4), Rank(5)),
        Black => (Rank(3), Rank(2)),
    };
    let (x, y, z);
    let from_file_all: &[File] = match to_file {
        File(0) => { x = [File(1)]; &x },
        File(7) => { y = [File(6)]; &y },
        File(f) => { z = [File(f-1), File(f+1)]; &z },
    };

    let expect_piece = Piece::new(p.side_to_move(), Pawn);
    let to = Square::new(to_file, to_rank);

    for &from_file in from_file_all.iter() {
        let from = Square::new(from_file, from_rank);
        if p.at(from) == Some(expect_piece) {
            let curr_move = Move::new(from, to).set_en_passant(true);
            send!(tx, curr_move);
        }
    }

    Continue
}

fn gen_castle(p: &Position, tx: &SyncSender<Move>) -> Action {
    match p.side_to_move() {
        White => {
            if p.can_castle_now(Kingside, White) {
                let from = Square::new(File(4),Rank(0));
                let to   = Square::new(File(6),Rank(0));
                let curr_move = Move::new(from, to).set_castle(Some(Kingside));
                send!(tx, curr_move);
            }
            if p.can_castle_now(Queenside, White) {
                let from = Square::new(File(4),Rank(0));
                let to   = Square::new(File(2),Rank(0));
                let curr_move = Move::new(from, to).set_castle(Some(Queenside));
                send!(tx, curr_move);
            }
        }
        Black => {
            if p.can_castle_now(Kingside, Black) {
                let from = Square::new(File(4),Rank(7));
                let to   = Square::new(File(6),Rank(7));
                let curr_move = Move::new(from, to).set_castle(Some(Kingside));
                send!(tx, curr_move);
            }
            if p.can_castle_now(Queenside, Black) {
                let from = Square::new(File(4),Rank(7));
                let to   = Square::new(File(2),Rank(7));
                let curr_move = Move::new(from, to).set_castle(Some(Queenside));
                send!(tx, curr_move);
            }
        }
    }

    Continue
}
<commit_msg>Fix bug in pawn move generation.<commit_after>#![allow(unused_variables)]

use std::thread::Thread;

use super::square::{Square,Rank,File};
use super::moves::Move;
use super::color::{White,Black};
use super::piece::Piece;
use super::piece::Type::{Pawn,King,Queen,Bishop,Knight,Rook};
use super::pos::Position;
use super::castle::{Kingside,Queenside};

use self::Action::{Continue,Stop};

macro_rules! send {
    ($tx: expr, $x: expr) => ({
        match $tx.send_opt($x) {
            Ok(()) => (),
            Err(_) => return Stop,
        }
    })
}

enum Action {
    Continue,
    Stop,
}
impl Action {
    fn is_stop(&self) -> bool {
        match *self {
            Continue => false,
            Stop => true,
        }
    }
}

pub fn receive_psudo_legal(p: Position) -> Receiver<Move> {
    let (tx,rx) = sync_channel(0);
    Thread::spawn(move || gen_psudo_legal(&p, tx)).detach();
    rx
}

pub fn gen_psudo_legal(p: &Position, tx: SyncSender<Move>) {
    if gen_en_passant(p, &tx).is_stop() {
        return;
    }
    if gen_castle(p, &tx).is_stop() {
        return;
    }
    for file in range(0,8) {
        for rank in range(0,8) {
            if gen_move_from(p, Square::new(File(file),Rank(rank)), &tx).is_stop() {
                return;
            }
        }
    }
}

//Functions below return Err(()) if the receiver hung up.

fn gen_move_from(p: &Position, from: Square, tx: &SyncSender<Move>) -> Action {
    let piece_id = match p.at(from) {
        None => return Continue,
        Some(val) => val,
    };
    if piece_id.color() != p.side_to_move() {
        return Continue;
    }
    match piece_id.piece_type() {
        Pawn => gen_pawn_from(p, from, tx),
        Queen|Bishop|Rook => gen_slider_from(p, from, tx),
        King|Knight => gen_fixed_from(p, from, tx),
    }
}

// (file, rank)
type Diff = (int, int);

fn shift(s: Square, dir: Diff) -> Option<Square> {
    let (dx, dy) = dir;
    let (File(file), Rank(rank)) = s.to_tuple();
    Square::from_int(file as int + dx, rank as int + dy)
}

fn gen_slider_from(p: &Position, from: Square, tx: &SyncSender<Move>) -> Action {
    let rook_slide:   &[Diff] = &[(1,0), (0,1), (-1,0), (0,-1)];
    let bishop_slide: &[Diff] = &[(1,1), (1,-1), (-1,-1), (-1,1)];
    let queen_slide:  &[Diff] = &[(1,0), (0,1), (-1,0), (0,-1), (1,1), (1,-1), (-1,-1), (-1,1)];

    let piece_id = p.at(from).unwrap();
    let piece_type = piece_id.piece_type();
    let piece_color = piece_id.color();

    let slide = match piece_type {
        Rook => rook_slide,
        Bishop => bishop_slide,
        Queen => queen_slide,
        _ => panic!(),
    };

    for dir in slide.iter() {
        let mut curr_pos = shift(from, *dir);
        //while curr_pos is valid and there is no piece there.
        while curr_pos.is_some() && p.at(curr_pos.unwrap()).is_none() {
            let curr_move = Move::new(from, curr_pos.unwrap());
            send!(tx, curr_move);
            curr_pos = shift(curr_pos.unwrap(), *dir);
        }
        //if curr_pos is valid
        if curr_pos.is_some() {
            let to = curr_pos.unwrap();
            let dest: Option<Piece> = p.at(to);
            //that square is always occupied
            let dest_piece: Piece = dest.unwrap();
            let dest_color = dest_piece.color();
            //if there is an enemy at the destination
            if dest_color == piece_color.invert() {
                let curr_move = Move::new(from, to).set_capture(true);
                send!(tx, curr_move);
            }
        }
    }

    Continue
}

fn gen_fixed_from(p: &Position, from: Square, tx: &SyncSender<Move>) -> Action {
    let king_fixed:   &[Diff] = &[(1,0), (0,1), (-1,0), (0,-1), (1,1), (1,-1), (-1,-1), (-1,1)];
    let knight_fixed: &[Diff] = &[(2,1), (2,-1), (-2,-1), (-2,1), (1,2), (1,-2), (-1,-2), (-1,2)];

    let piece_id = p.at(from).unwrap();
    let piece_type = piece_id.piece_type();
    let piece_color = piece_id.color();

    let fixed = match piece_type {
        King => king_fixed,
        Knight => knight_fixed,
        _ => panic!(),
    };

    for dir in fixed.iter() {
        let new_pos = shift(from, *dir);
        if new_pos.is_some() {
            let to = new_pos.unwrap();
            let dest: Option<Piece> = p.at(to);
            let (is_valid, is_capture) = match dest {
                Some(val) => {
                    if val.color() == piece_color { (false, false) }
                    else { (true, true) }
                },
                None => (true, false),
            };
            if is_valid {
                let curr_move = Move::new(from, to).set_capture(is_capture);
                send!(tx, curr_move);
            }
        }
    }

    Continue
}

fn gen_pawn_from(p: &Position, from: Square, tx: &SyncSender<Move>) -> Action {
    let piece_color = p.at(from).unwrap().color();
    let (File(_), Rank(from_rank)) = from.to_tuple();
    //rank_up is the 1-based rank from the piece-owner's side.
    let (dy, rank_up): (int, u8) = match piece_color {
        White => ( 1, 1u8 + from_rank ),
        Black => (-1, 8u8 - from_rank ),
    };
    let move_dir: Diff = (0, dy);
    let to: Square = shift(from, move_dir).unwrap();
    // if destination is empty
    if p.at(to).is_none() {
        match rank_up {
            7 => {
                for new_piece in [Queen, Knight, Rook, Bishop].iter() {
                    let curr_move = Move::new(from, to).set_promote(Some(*new_piece));
                    send!(tx, curr_move);
                }
            },
            2 => {
                let curr_move = Move::new(from, to);
                send!(tx, curr_move);
                let to2: Square = shift(to, move_dir).unwrap();
                if p.at(to2).is_none() {
                    let curr_move2 = Move::new(from, to2).set_pawn_double_move(true);
                    send!(tx, curr_move2);
                }
            },
            _ => {
                let curr_move = Move::new(from, to);
                send!(tx, curr_move);
            },
        }
    }

    for dx in [1,-1].iter() {
        let capture_dir: Diff = (*dx, dy);
        let capture_new_pos: Option<Square> = shift(from, capture_dir);
        let capture_to: Square = match capture_new_pos {
            Some(val) => val,
            None => continue,
        };
        let dest: Option<Piece> = p.at(capture_to);
        let dest_piece: Piece = match dest {
            Some(val) => val,
            None => continue,
        };
        let dest_color = dest_piece.color();
        if dest_color == piece_color.invert() {
            if rank_up == 7 {
                for new_piece in [Queen, Knight, Rook, Bishop].iter() {
                    let curr_move = Move::new(from, capture_to).set_capture(true);
                    let curr_move = curr_move.set_promote(Some(*new_piece));
                    send!(tx, curr_move);
                }
            } else {
                let curr_move = Move::new(from, capture_to).set_capture(true);
                send!(tx, curr_move);
            }
        }
    }

    Continue
}

fn gen_en_passant(p: &Position, tx: &SyncSender<Move>) -> Action {
    let to_file = match p.en_passant() {
        Some(f) => f,
        None => return Continue,
    };
    let (from_rank, to_rank) = match p.side_to_move() {
        White => (Rank(4), Rank(5)),
        Black => (Rank(3), Rank(2)),
    };
    let (x, y, z);
    let from_file_all: &[File] = match to_file {
        File(0) => { x = [File(1)]; &x },
        File(7) => { y = [File(6)]; &y },
        File(f) => { z = [File(f-1), File(f+1)]; &z },
    };

    let expect_piece = Piece::new(p.side_to_move(), Pawn);
    let to = Square::new(to_file, to_rank);

    for &from_file in from_file_all.iter() {
        let from = Square::new(from_file, from_rank);
        if p.at(from) == Some(expect_piece) {
            let curr_move = Move::new(from, to).set_en_passant(true);
            send!(tx, curr_move);
        }
    }

    Continue
}

fn gen_castle(p: &Position, tx: &SyncSender<Move>) -> Action {
    match p.side_to_move() {
        White => {
            if p.can_castle_now(Kingside, White) {
                let from = Square::new(File(4),Rank(0));
                let to   = Square::new(File(6),Rank(0));
                let curr_move = Move::new(from, to).set_castle(Some(Kingside));
                send!(tx, curr_move);
            }
            if p.can_castle_now(Queenside, White) {
                let from = Square::new(File(4),Rank(0));
                let to   = Square::new(File(2),Rank(0));
                let curr_move = Move::new(from, to).set_castle(Some(Queenside));
                send!(tx, curr_move);
            }
        }
        Black => {
            if p.can_castle_now(Kingside, Black) {
                let from = Square::new(File(4),Rank(7));
                let to   = Square::new(File(6),Rank(7));
                let curr_move = Move::new(from, to).set_castle(Some(Kingside));
                send!(tx, curr_move);
            }
            if p.can_castle_now(Queenside, Black) {
                let from = Square::new(File(4),Rank(7));
                let to   = Square::new(File(2),Rank(7));
                let curr_move = Move::new(from, to).set_castle(Some(Queenside));
                send!(tx, curr_move);
            }
        }
    }

    Continue
}
<|endoftext|>


<commit_before>use rustfm_scrobble::{Scrobble, Scrobbler};

// Example rustfm-scrobble client showing authentication, now playing and
// scrobbling.
// Replace credential values with your own to test.

fn main() {
    let api_key = "{{api_key}}";
    let api_secret = "{{api_secret}}";
    let username = "{{username}}";
    let password = "{{password}}";

    let mut scrobbler = Scrobbler::new(api_key, api_secret);

    match scrobbler.authenticate_with_password(username, password) {
        Ok(_) => {
            println!("Authenticated!");
        }
        Err(e) => {
            println!("{}", e);
        }
    };

    let track_one = Scrobble::new("Los Campesinos!", "As Lucerne / The Low", "No Blues");
    match scrobbler.now_playing(track_one) {
        Ok(_) => {
            println!("Sent now playing! ");
        }
        Err(e) => {
            println!("{}", e);
        }
    }

    let track_two = Scrobble::new("Los Campesinos!", "The Time Before the Last", "No Blues");
    match scrobbler.scrobble(track_two) {
        Ok(_) => {
            println!("Sent scrobble!");
        }
        Err(e) => {
            println!("{}", e);
        }
    }

    let track_three = Scrobble::new("Los Campesinos!", "Selling Rope", "No Blues");
    match scrobbler.now_playing(track_three) {
        Ok(_) => {
            println!("Sent now playing! ");
        }
        Err(e) => {
            println!("{}", e);
        }
    }
}
<commit_msg>cleanup code of example<commit_after>use rustfm_scrobble::{Scrobble, Scrobbler};
use std::error::Error;

// Example rustfm-scrobble client showing authentication, now playing and
// scrobbling.
// Replace credential values with your own to test.

fn main() -> Result<(), Box<dyn Error>> {
    let api_key = "{{api_key}}";
    let api_secret = "{{api_secret}}";
    let username = "{{username}}";
    let password = "{{password}}";

    let mut scrobbler = Scrobbler::new(api_key, api_secret);

    let response = scrobbler.authenticate_with_password(username, password)?;
    println!("Authenticated! {:#?}", response);

    let track_one = Scrobble::new("Los Campesinos!", "As Lucerne / The Low", "No Blues");
    let response = scrobbler.now_playing(track_one)?;
    println!("Sent now playing! {:#?}", response);

    let track_two = Scrobble::new("Los Campesinos!", "The Time Before the Last", "No Blues");
    let response = scrobbler.scrobble(track_two)?;
    println!("Sent scrobble! {:#?}", response);

    let track_three = Scrobble::new("Los Campesinos!", "Selling Rope", "No Blues");
    let response = scrobbler.now_playing(track_three)?;
    println!("Sent now playing! {:#?}", response);

    Ok(())
}
<|endoftext|>