<commit_before>
// https://users.rust-lang.org/t/what-am-i-doing-wrong-go-program-is-12x-faster-than-rust/5692/13
// https://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/index.html
// https://serde.rs/codegen-hybrid.html

// FIXME: Make sure that all structs above Issue are not using `String`s instead of `Enum`s.
// FIXME: Harmonize the different state enums (e.g. IssueState, MergeRequestState, Authors)
// FIXME: Move all enums here (ListingOrderBy, ListingSort, etc.)
// FIXME: Use a type for sha1
// FIXME: Use chrono crate for dates
// FIXME: Use unsigned integers where it makes sense (id, iid, etc.)
// FIXME: Verify all `match` in push_str() in build_query(): They should contain all members.
// FIXME: Get rid of build_query(), use serde's Serialize instead.

#[derive(Debug, Serialize, Deserialize)]
pub struct Version {
    pub version: String,
    pub revision: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Group {
    pub id: i64,
    pub name: String,
    pub path: String,
    pub description: String,
    pub visibility_level: i64,
    pub lfs_enabled: bool,
    pub avatar_url: Option<String>,
    pub web_url: String,
    pub request_access_enabled: bool,
}

pub type Groups = Vec<Group>;

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectOwner {
    pub name: String,
    pub username: String,
    pub id: i64,
    pub state: String,
    pub avatar_url: String,
    pub web_url: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectNamespaceAvatar {
    url: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectNamespace {
    id: i64,
    name: String,
    path: String,
    owner_id: Option<i64>,  // FIXME: Why would a project not have this?
    created_at: String,  // FIXME: Date instead?
    updated_at: String,  // FIXME: Date instead?
    description: String,
    avatar: Option<ProjectNamespaceAvatar>,
    membership_lock: Option<bool>,
    share_with_group_lock: bool,
    visibility_level: i64,
    request_access_enabled: bool,
    ldap_sync_status: Option<String>,
    ldap_sync_error: Option<String>,  // FIXME: Is String the proper type?
    ldap_sync_last_update_at: Option<String>,  // FIXME: Is String the proper type?
    ldap_sync_last_successful_update_at: Option<String>,  // FIXME: Is String the proper type?
    ldap_sync_last_sync_at: Option<String>,  // FIXME: Is String the proper type?
    deleted_at: Option<String>,  // FIXME: Is String the proper type?
    lfs_enabled: Option<String>,  // FIXME: Is String the proper type?
    repository_size_limit: Option<String>  // FIXME: Is String the proper type?
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectForkedFrom {
    id: i64,
    http_url_to_repo: String,
    web_url: String,
    name: String,
    name_with_namespace: String,
    path: String,
    path_with_namespace: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectAccess {
    access_level: i64,
    notification_level: i64,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectPermissions {
    project_access: Option<ProjectAccess>,
    group_access: Option<ProjectAccess>,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectSharedWithGroup {
    group_id: i64,
    group_name: String,
    group_access_level: i64,
}

// https://users.rust-lang.org/t/what-am-i-doing-wrong-go-program-is-12x-faster-than-rust/5692/13
// https://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/index.html
#[derive(Debug, Serialize, Deserialize)]
pub struct Project {
    id: i64,
    description: String,
    default_branch: Option<String>,
    tag_list: Vec<String>,
    public: bool,
    archived: bool,
    visibility_level: i64,
    ssh_url_to_repo: String,
    http_url_to_repo: String,
    web_url: String,
    // owner: Option<ProjectOwner>,  // FIXME: Why would a project not have an owner?
    name: String,
    name_with_namespace: String,
    path: String,
    path_with_namespace: String,
    container_registry_enabled: Option<bool>,
    issues_enabled: bool,
    merge_requests_enabled: bool,
    wiki_enabled: bool,
    builds_enabled: bool,
    snippets_enabled: bool,
    created_at: String,  // FIXME: Date instead?
    last_activity_at: String,  // FIXME: Date instead?
    shared_runners_enabled: bool,
    lfs_enabled: bool,
    creator_id: i64,
    namespace: ProjectNamespace,
    forked_from_project: Option<ProjectForkedFrom>,
    avatar_url: Option<String>,
    star_count: i64,
    forks_count: i64,
    open_issues_count: i64,
    runners_token: Option<String>,
    public_builds: bool,
    shared_with_groups: Vec<ProjectSharedWithGroup>,
    only_allow_merge_if_build_succeeds: bool,
    request_access_enabled: bool,
    only_allow_merge_if_all_discussions_are_resolved: Option<bool>,  // FIXME: Is bool the proper type?
    approvals_before_merge: Option<i64>,
    permissions: ProjectPermissions,
}

pub type Projects = Vec<Project>;

#[derive(Debug, Serialize, Deserialize)]
enum IssueState {
    #[serde(rename = "opened")]
    Opened,

    #[serde(rename = "closed")]
    Closed,
}

#[derive(Debug, Serialize, Deserialize)]
enum UserState {
    #[serde(rename = "active")]
    Active,

    #[serde(rename = "blocked")]
    Blocked,
}

#[derive(Debug, Serialize, Deserialize)]
enum MilestoneState {
    #[serde(rename = "active")]
    Active,

    #[serde(rename = "closed")]
    Closed,
}

#[derive(Debug, Serialize, Deserialize)]
struct Milestone {
    id: i64,
    iid: i64,
    project_id: i64,
    title: String,
    description: String,
    state: MilestoneState,
    created_at: String,  // FIXME: Use date type?
    updated_at: String,  // FIXME: Use date type?
    due_date: Option<String>  // FIXME: Use date type?
}

#[derive(Debug, Serialize, Deserialize)]
struct User {
    name: String,
    username: String,
    id: i64,
    state: UserState,
    avatar_url: Option<String>,
    web_url: Option<String>
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Issue {
    id: i64,
    iid: i64,
    project_id: i64,
    title: String,
    description: String,
    state: IssueState,
    created_at: String,  // FIXME: Use date type?
    updated_at: String,  // FIXME: Use date type?
    labels: Vec<String>,
    milestone: Option<Milestone>,
    assignee: Option<User>,
    author: User,
    subscribed: bool,
    user_notes_count: i64,
    upvotes: i64,
    downvotes: i64,
    due_date: Option<String>,  // FIXME: Use date type?
    confidential: bool,
    web_url: Option<String>
}

pub type Issues = Vec<Issue>;

#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub enum MergeRequestState {
    #[serde(rename = "merged")]
    Merged,
    #[serde(rename = "opened")]
    Opened,
    #[serde(rename = "closed")]
    Closed,
    #[serde(rename = "all")]
    All,
}

#[derive(Debug, Serialize, Deserialize)]
enum MergeRequestStatus {
    #[serde(rename = "can_be_merged")]
    CanBeMerged,
    #[serde(rename = "cannot_be_merged")]
    CannotBeMerged,
    #[serde(rename = "unchecked")]
    Unchecked,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct MergeRequest {
    id: i64,
    iid: i64,
    project_id: i64,
    title: String,
    description: String,
    state: MergeRequestState,
    created_at: String,  // FIXME: Use chrono crate
    updated_at: String,  // FIXME: Use chrono crate
    target_branch: String,
    source_branch: String,
    upvotes: i64,
    downvotes: i64,
    author: User,
    assignee: Option<User>,
    source_project_id: i64,
    target_project_id: i64,
    labels: Vec<String>,
    work_in_progress: bool,
    milestone: Option<Milestone>,
    merge_when_build_succeeds: bool,
    merge_status: MergeRequestStatus,
    sha: String,
    merge_commit_sha: Option<String>,
    subscribed: bool,
    user_notes_count: i64,
    should_remove_source_branch: Option<bool>,
    force_remove_source_branch: Option<bool>,
    web_url: String
}

pub type MergeRequests = Vec<MergeRequest>;
<commit_msg>More FIXMEs<commit_after>
// https://users.rust-lang.org/t/what-am-i-doing-wrong-go-program-is-12x-faster-than-rust/5692/13
// https://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/index.html
// https://serde.rs/codegen-hybrid.html

// FIXME: Use https://github.com/nox/serde_urlencoded
// FIXME: Make sure that all structs above Issue are not using `String`s instead of `Enum`s.
// FIXME: Harmonize the different state enums (e.g. IssueState, MergeRequestState, Authors)
// FIXME: Move all enums here (ListingOrderBy, ListingSort, etc.)
// FIXME: Use a type for sha1
// FIXME: Use chrono crate for dates
// FIXME: Use unsigned integers where it makes sense (id, iid, etc.)
// FIXME: Verify all `match` in push_str() in build_query(): They should contain all members.
// FIXME: Get rid of build_query(), use serde's Serialize instead.
// FIXME: Write nicer wrappers, getting rid of Listing.
// FIXME: Rename GitLab::new_https() to new() and new_http() to new_insecure()

#[derive(Debug, Serialize, Deserialize)]
pub struct Version {
    pub version: String,
    pub revision: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Group {
    pub id: i64,
    pub name: String,
    pub path: String,
    pub description: String,
    pub visibility_level: i64,
    pub lfs_enabled: bool,
    pub avatar_url: Option<String>,
    pub web_url: String,
    pub request_access_enabled: bool,
}

pub type Groups = Vec<Group>;

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectOwner {
    pub name: String,
    pub username: String,
    pub id: i64,
    pub state: String,
    pub avatar_url: String,
    pub web_url: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectNamespaceAvatar {
    url: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectNamespace {
    id: i64,
    name: String,
    path: String,
    owner_id: Option<i64>,  // FIXME: Why would a project not have this?
    created_at: String,  // FIXME: Date instead?
    updated_at: String,  // FIXME: Date instead?
    description: String,
    avatar: Option<ProjectNamespaceAvatar>,
    membership_lock: Option<bool>,
    share_with_group_lock: bool,
    visibility_level: i64,
    request_access_enabled: bool,
    ldap_sync_status: Option<String>,
    ldap_sync_error: Option<String>,  // FIXME: Is String the proper type?
    ldap_sync_last_update_at: Option<String>,  // FIXME: Is String the proper type?
    ldap_sync_last_successful_update_at: Option<String>,  // FIXME: Is String the proper type?
    ldap_sync_last_sync_at: Option<String>,  // FIXME: Is String the proper type?
    deleted_at: Option<String>,  // FIXME: Is String the proper type?
    lfs_enabled: Option<String>,  // FIXME: Is String the proper type?
    repository_size_limit: Option<String>  // FIXME: Is String the proper type?
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectForkedFrom {
    id: i64,
    http_url_to_repo: String,
    web_url: String,
    name: String,
    name_with_namespace: String,
    path: String,
    path_with_namespace: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectAccess {
    access_level: i64,
    notification_level: i64,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectPermissions {
    project_access: Option<ProjectAccess>,
    group_access: Option<ProjectAccess>,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectSharedWithGroup {
    group_id: i64,
    group_name: String,
    group_access_level: i64,
}

// https://users.rust-lang.org/t/what-am-i-doing-wrong-go-program-is-12x-faster-than-rust/5692/13
// https://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/index.html
#[derive(Debug, Serialize, Deserialize)]
pub struct Project {
    id: i64,
    description: String,
    default_branch: Option<String>,
    tag_list: Vec<String>,
    public: bool,
    archived: bool,
    visibility_level: i64,
    ssh_url_to_repo: String,
    http_url_to_repo: String,
    web_url: String,
    // owner: Option<ProjectOwner>,  // FIXME: Why would a project not have an owner?
    name: String,
    name_with_namespace: String,
    path: String,
    path_with_namespace: String,
    container_registry_enabled: Option<bool>,
    issues_enabled: bool,
    merge_requests_enabled: bool,
    wiki_enabled: bool,
    builds_enabled: bool,
    snippets_enabled: bool,
    created_at: String,  // FIXME: Date instead?
    last_activity_at: String,  // FIXME: Date instead?
    shared_runners_enabled: bool,
    lfs_enabled: bool,
    creator_id: i64,
    namespace: ProjectNamespace,
    forked_from_project: Option<ProjectForkedFrom>,
    avatar_url: Option<String>,
    star_count: i64,
    forks_count: i64,
    open_issues_count: i64,
    runners_token: Option<String>,
    public_builds: bool,
    shared_with_groups: Vec<ProjectSharedWithGroup>,
    only_allow_merge_if_build_succeeds: bool,
    request_access_enabled: bool,
    only_allow_merge_if_all_discussions_are_resolved: Option<bool>,  // FIXME: Is bool the proper type?
    approvals_before_merge: Option<i64>,
    permissions: ProjectPermissions,
}

pub type Projects = Vec<Project>;

#[derive(Debug, Serialize, Deserialize)]
enum IssueState {
    #[serde(rename = "opened")]
    Opened,

    #[serde(rename = "closed")]
    Closed,
}

#[derive(Debug, Serialize, Deserialize)]
enum UserState {
    #[serde(rename = "active")]
    Active,

    #[serde(rename = "blocked")]
    Blocked,
}

#[derive(Debug, Serialize, Deserialize)]
enum MilestoneState {
    #[serde(rename = "active")]
    Active,

    #[serde(rename = "closed")]
    Closed,
}

#[derive(Debug, Serialize, Deserialize)]
struct Milestone {
    id: i64,
    iid: i64,
    project_id: i64,
    title: String,
    description: String,
    state: MilestoneState,
    created_at: String,  // FIXME: Use date type?
    updated_at: String,  // FIXME: Use date type?
    due_date: Option<String>  // FIXME: Use date type?
}

#[derive(Debug, Serialize, Deserialize)]
struct User {
    name: String,
    username: String,
    id: i64,
    state: UserState,
    avatar_url: Option<String>,
    web_url: Option<String>
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Issue {
    id: i64,
    iid: i64,
    project_id: i64,
    title: String,
    description: String,
    state: IssueState,
    created_at: String,  // FIXME: Use date type?
    updated_at: String,  // FIXME: Use date type?
    labels: Vec<String>,
    milestone: Option<Milestone>,
    assignee: Option<User>,
    author: User,
    subscribed: bool,
    user_notes_count: i64,
    upvotes: i64,
    downvotes: i64,
    due_date: Option<String>,  // FIXME: Use date type?
    confidential: bool,
    web_url: Option<String>
}

pub type Issues = Vec<Issue>;

#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub enum MergeRequestState {
    #[serde(rename = "merged")]
    Merged,
    #[serde(rename = "opened")]
    Opened,
    #[serde(rename = "closed")]
    Closed,
    #[serde(rename = "all")]
    All,
}

#[derive(Debug, Serialize, Deserialize)]
enum MergeRequestStatus {
    #[serde(rename = "can_be_merged")]
    CanBeMerged,
    #[serde(rename = "cannot_be_merged")]
    CannotBeMerged,
    #[serde(rename = "unchecked")]
    Unchecked,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct MergeRequest {
    id: i64,
    iid: i64,
    project_id: i64,
    title: String,
    description: String,
    state: MergeRequestState,
    created_at: String,  // FIXME: Use chrono crate
    updated_at: String,  // FIXME: Use chrono crate
    target_branch: String,
    source_branch: String,
    upvotes: i64,
    downvotes: i64,
    author: User,
    assignee: Option<User>,
    source_project_id: i64,
    target_project_id: i64,
    labels: Vec<String>,
    work_in_progress: bool,
    milestone: Option<Milestone>,
    merge_when_build_succeeds: bool,
    merge_status: MergeRequestStatus,
    sha: String,
    merge_commit_sha: Option<String>,
    subscribed: bool,
    user_notes_count: i64,
    should_remove_source_branch: Option<bool>,
    force_remove_source_branch: Option<bool>,
    web_url: String
}

pub type MergeRequests = Vec<MergeRequest>;
<|endoftext|>


<commit_before>// "Tifflin" Kernel
// - By John Hodge (thePowersGang)
//
// Core/gui/windows/winbuf.rs
// - Backing buffer for a window
use prelude::*;
use super::super::{Dims,Pos,Rect,Colour};
use core::cell::UnsafeCell;

/// Window backing buffer.
///
/// Interior mutable to allow rendering without holding a spinlock (safe, can at worst
/// cause partial updates to be rendered)
///
/// Usecase: Rendering from the logging thread.
pub struct WinBuf
{
	/// Window dimensions
	dims: Dims,
	/// Window backing buffer
	data: UnsafeCell< Vec<u32> >,
}
// SAFE: Multiple &-ptrs are valid (and quite possible)
unsafe impl Sync for WinBuf {}
// SEND: Maintains no external references (Vec is Send)
unsafe impl Send for WinBuf {}
assert_trait!(Vec<u32> : Send);

impl Clone for WinBuf
{
	fn clone(&self) -> WinBuf {
		WinBuf {
			dims: self.dims,
			// SAFE: &ptr means that window will not resize
			data: UnsafeCell::new( unsafe { (*self.data.get()).clone() } ),
		}
	}
}
impl Default for WinBuf
{
	fn default() -> WinBuf {
		WinBuf {
			dims: Default::default(),
			data: UnsafeCell::new( Default::default() ),
		}
	}
}

impl WinBuf
{
	pub fn dims(&self) -> Dims { self.dims }

	pub fn resize(&mut self, newsize: Dims)
	{
		let px_count = newsize.width() as usize * newsize.height() as usize;
		log_trace!("WinBuf::resize({:?}) px_count = {}", newsize, px_count);
		self.dims = newsize;

		//let val = (self as *const _ as usize & 0xFFFF) as u32 * (256+9);
		let val = 0;

		// SAFE: This is the only place where a resize can happen, and self is &mut
		unsafe {
			(*self.data.get()).resize(px_count, val);
		}
	}

	fn slice(&self) -> &[u32] {
		// SAFE: Buffer will not resize, and multiple writers is allowed
		unsafe { &(*self.data.get())[..] }
	}
	fn slice_mut(&self) -> &mut [u32] {
		// SAFE: Buffer will not resize, and multiple writers is allowed
		unsafe { &mut (*self.data.get())[..] }
	}

	/// Obtain a Range<usize> given a scanline reference
	fn scanline_range(&self, line: usize, ofs: usize, len: usize) -> ::core::ops::Range<usize>
	{
		assert!(ofs < self.dims.width() as usize);
		assert!(line < self.dims.h as usize, "Requested scanline is out of range");

		let pitch_32 = self.dims.width() as usize;
		let len = ::core::cmp::max(len, pitch_32 - ofs);

		let l_ofs = line * pitch_32;

		l_ofs + ofs .. l_ofs + ofs + len
	}

	fn scanline_rgn(&self, line: usize, ofs: usize, len: usize) -> &[u32]
	{
		&self.slice()[ self.scanline_range(line, ofs, len) ]
	}
	fn scanline_rgn_mut(&self, line: usize, ofs: usize, len: usize) -> &mut [u32]
	{
		&mut self.slice_mut()[ self.scanline_range(line, ofs, len) ]
	}

	/// Render this window buffer at the provided position
	pub fn blit(&self, winpos: Pos, rgn: Rect)
	{
		log_trace!("WinBuf::blit(winpos={:?},rgn={:?})", winpos, rgn);
		// TODO: Call a block blit instead?
		for row in rgn.top() .. rgn.bottom()
		{
			self.blit_scanline(
				winpos,
				row as usize,
				rgn.left() as usize,
				rgn.dims().width() as usize
				);
		}
	}
	fn blit_scanline(&self, winpos: Pos, line: usize, ofs: usize, len: usize)
	{
		// TODO: Assert that current thread is from/controlled-by the compositor
		// TODO: Should this be an unsafe operation? It isn't memory unsafe, but
		//       care should be taken to not call this outside the compositor thread.
		unsafe {
			let pos = Pos::new(
				winpos.x + ofs as u32,
				winpos.y + line as u32
				);
			::metadevs::video::write_line(pos, self.scanline_rgn(line, ofs, len));
		}
	}

	pub fn fill_scanline(&self, line: usize, ofs: usize, len: usize, value: Colour)
	{
		if line >= self.dims.height() as usize || ofs >= self.dims.width() as usize {
			return ;
		}
		let rgn = self.scanline_rgn_mut(line, ofs, len);
		//log_debug!("fill_scanline: rgn = {:p}", &rgn[0]);
		for v in rgn.iter_mut()
		{
			*v = value.as_argb32();
		}
	}

	pub fn set_scanline(&self, line: usize, ofs: usize, len: usize, data: &[u32])
	{
		if line >= self.dims.height() as usize || ofs >= self.dims.width() as usize {
			return ;
		}
		let rgn = self.scanline_rgn_mut(line, ofs, len);

		for (d,s) in rgn.iter_mut().zip( data.iter() )
		{
			*d = *s;
		}
	}
}

<commit_msg>Core/GUI - Fix incorrect bounding in scanline slice<commit_after>// "Tifflin" Kernel
// - By John Hodge (thePowersGang)
//
// Core/gui/windows/winbuf.rs
// - Backing buffer for a window
use prelude::*;
use super::super::{Dims,Pos,Rect,Colour};
use core::cell::UnsafeCell;

/// Window backing buffer.
///
/// Interior mutable to allow rendering without holding a spinlock (safe, can at worst
/// cause partial updates to be rendered)
///
/// Usecase: Rendering from the logging thread.
pub struct WinBuf
{
	/// Window dimensions
	dims: Dims,
	/// Window backing buffer
	data: UnsafeCell< Vec<u32> >,
}
// SAFE: Multiple &-ptrs are valid (and quite possible)
unsafe impl Sync for WinBuf {}
// SEND: Maintains no external references (Vec is Send)
unsafe impl Send for WinBuf {}
assert_trait!(Vec<u32> : Send);

impl Clone for WinBuf
{
	fn clone(&self) -> WinBuf {
		WinBuf {
			dims: self.dims,
			// SAFE: &ptr means that window will not resize
			data: UnsafeCell::new( unsafe { (*self.data.get()).clone() } ),
		}
	}
}
impl Default for WinBuf
{
	fn default() -> WinBuf {
		WinBuf {
			dims: Default::default(),
			data: UnsafeCell::new( Default::default() ),
		}
	}
}

impl WinBuf
{
	pub fn dims(&self) -> Dims { self.dims }

	pub fn resize(&mut self, newsize: Dims)
	{
		let px_count = newsize.width() as usize * newsize.height() as usize;
		log_trace!("WinBuf::resize({:?}) px_count = {}", newsize, px_count);
		self.dims = newsize;

		//let val = (self as *const _ as usize & 0xFFFF) as u32 * (256+9);
		let val = 0;

		// SAFE: This is the only place where a resize can happen, and self is &mut
		unsafe {
			(*self.data.get()).resize(px_count, val);
		}
	}

	fn slice(&self) -> &[u32] {
		// SAFE: Buffer will not resize, and multiple writers is allowed
		unsafe { &(*self.data.get())[..] }
	}
	fn slice_mut(&self) -> &mut [u32] {
		// SAFE: Buffer will not resize, and multiple writers is allowed
		unsafe { &mut (*self.data.get())[..] }
	}

	/// Obtain a Range<usize> given a scanline reference
	fn scanline_range(&self, line: usize, ofs: usize, len: usize) -> ::core::ops::Range<usize>
	{
		assert!(ofs < self.dims.width() as usize);
		assert!(line < self.dims.h as usize, "Requested scanline is out of range");

		let pitch_32 = self.dims.width() as usize;
		let len = ::core::cmp::min(len, pitch_32 - ofs);

		let l_ofs = line * pitch_32;

		l_ofs + ofs .. l_ofs + ofs + len
	}

	fn scanline_rgn(&self, line: usize, ofs: usize, len: usize) -> &[u32]
	{
		&self.slice()[ self.scanline_range(line, ofs, len) ]
	}
	fn scanline_rgn_mut(&self, line: usize, ofs: usize, len: usize) -> &mut [u32]
	{
		&mut self.slice_mut()[ self.scanline_range(line, ofs, len) ]
	}

	/// Render this window buffer at the provided position
	pub fn blit(&self, winpos: Pos, rgn: Rect)
	{
		log_trace!("WinBuf::blit(winpos={:?},rgn={:?})", winpos, rgn);
		// TODO: Call a block blit instead?
		for row in rgn.top() .. rgn.bottom()
		{
			self.blit_scanline(
				winpos,
				row as usize,
				rgn.left() as usize,
				rgn.dims().width() as usize
				);
		}
	}
	fn blit_scanline(&self, winpos: Pos, line: usize, ofs: usize, len: usize)
	{
		// TODO: Assert that current thread is from/controlled-by the compositor
		// TODO: Should this be an unsafe operation? It isn't memory unsafe, but
		//       care should be taken to not call this outside the compositor thread.
		unsafe {
			let pos = Pos::new(
				winpos.x + ofs as u32,
				winpos.y + line as u32
				);
			::metadevs::video::write_line(pos, self.scanline_rgn(line, ofs, len));
		}
	}

	pub fn fill_scanline(&self, line: usize, ofs: usize, len: usize, value: Colour)
	{
		if line >= self.dims.height() as usize || ofs >= self.dims.width() as usize {
			return ;
		}
		let rgn = self.scanline_rgn_mut(line, ofs, len);
		//log_debug!("fill_scanline: rgn = {:p}", &rgn[0]);
		for v in rgn.iter_mut()
		{
			*v = value.as_argb32();
		}
	}

	pub fn set_scanline(&self, line: usize, ofs: usize, len: usize, data: &[u32])
	{
		if line >= self.dims.height() as usize || ofs >= self.dims.width() as usize {
			return ;
		}
		let rgn = self.scanline_rgn_mut(line, ofs, len);

		for (d,s) in rgn.iter_mut().zip( data.iter() )
		{
			*d = *s;
		}
	}
}

<|endoftext|>


<commit_before>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Handling log-probabilities.

use std::mem;
use std::f64;
use std::iter;

pub use stats::{Prob, LogProb};

/// A factor to convert log-probabilities to PHRED-scale (phred = p * LOG_TO_PHRED_FACTOR).
const LOG_TO_PHRED_FACTOR: f64 = -4.3429448190325175; // -10 * 1 / ln(10)

/// A factor to convert PHRED-scale to log-probabilities (p = phred * PHRED_TO_LOG_FACTOR).
const PHRED_TO_LOG_FACTOR: f64 = -0.23025850929940456; // 1 / (-10 * log10(e))

/// Calculate log(1 - p) with p given in log space without loss of precision as described in
/// http://cran.r-project.org/web/packages/Rmpfr/vignettes/log1mexp-note.pdf.
pub fn ln_1m_exp(p: LogProb) -> LogProb {
    if p < -0.693 {
        (-p.exp()).ln_1p()
    } else {
        (-p.exp_m1()).ln()
    }
}

/// Convert log scale probability to PHRED scale.
pub fn log_to_phred(p: LogProb) -> f64 {
    p * LOG_TO_PHRED_FACTOR
}

/// Convert PHRED scale probability to log scale.
pub fn phred_to_log(p: f64) -> LogProb {
    p * PHRED_TO_LOG_FACTOR
}

/// Calculate the sum of the given probabilities in a numerically stable way (Durbin 1998).
pub fn sum(probs: &[LogProb]) -> LogProb {
    if probs.is_empty() {
        f64::NEG_INFINITY
    } else {
        let mut pmax = probs[0];
        let mut imax = 0;
        for (i, &p) in probs.iter().enumerate().skip(1) {
            if p > pmax {
                pmax = p;
                imax = i;
            }
        }
        if pmax == f64::NEG_INFINITY {
            f64::NEG_INFINITY
        } else if pmax == f64::INFINITY {
            f64::INFINITY
        } else {
            // TODO use sum() once it has been stabilized: .sum::<usize>()
            pmax +
            (probs.iter()
                  .enumerate()
                  .filter_map(|(i, p)| {
                      if i == imax {
                          None
                      } else {
                          Some((p - pmax).exp())
                      }
                  })
                  .fold(0.0, |s, e| s + e))
                .ln_1p()
        }
    }
}

/// Add the given probabilities in a numerically stable way (Durbin 1998).
pub fn add(mut p0: LogProb, mut p1: LogProb) -> LogProb {
    if p1 > p0 {
        mem::swap(&mut p0, &mut p1);
    }
    if p0 == f64::NEG_INFINITY {
        f64::NEG_INFINITY
    } else if p0 == f64::INFINITY {
        f64::INFINITY
    } else {
        p0 + (p1 - p0).exp().ln_1p()
    }
}

/// Subtract the given probabilities in a numerically stable way (Durbin 1998).
pub fn sub(p0: LogProb, p1: LogProb) -> LogProb {
    if p1 > p0 {
        panic!("Subtraction would lead to negative probability, which is undefined in log space.");
    }
    if p0 == p1 || p0 == f64::NEG_INFINITY {
        // the first case leads to zero,
        // in the second case p0 and p1 are -inf, which is fine
        f64::NEG_INFINITY
    } else if p0 == f64::INFINITY {
        f64::INFINITY
    } else {
        p0 + ln_1m_exp(p1 - p0)
    }
}

fn scan_add(s: &mut LogProb, p: LogProb) -> Option<LogProb> {
    *s = add(*s, p);
    Some(*s)
}

/// Iterator returned by scans over logprobs.
pub type ScanIter<I> = iter::Scan<I, LogProb, fn(&mut LogProb, LogProb) -> Option<LogProb>>;

/// Calculate the cumulative sum of the given probabilities in a numerically stable way (Durbin 1998).
pub fn cumsum<I: Iterator<Item = LogProb>>(probs: I) -> ScanIter<I> {
    probs.scan(f64::NEG_INFINITY, scan_add)
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::f64;
    use itertools::Itertools;

    #[test]
    fn test_sum() {
        let probs = [f64::NEG_INFINITY, 0.0, f64::NEG_INFINITY];
        assert_eq!(sum(&probs), 0.0);
    }

    #[test]
    fn test_empty_sum() {
        assert_eq!(sum(&[]), f64::NEG_INFINITY);
    }

    #[test]
    fn test_cumsum() {
        let probs = vec![0.0f64.ln(), 0.01f64.ln(), 0.001f64.ln()];
        assert_eq!(cumsum(probs.into_iter()).collect_vec(),
                   [0.0f64.ln(), 0.01f64.ln(), 0.011f64.ln()]);
    }

    #[test]
    fn test_sub() {
        assert_eq!(sub(0.0f64.ln(), 0.0f64.ln()), f64::NEG_INFINITY);
        assert_relative_eq!(sub(1.0f64.ln(), 0.5f64.ln()), 0.5f64.ln());
    }
}
<commit_msg>Added tests and assertion.<commit_after>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Handling log-probabilities.

use std::mem;
use std::f64;
use std::iter;

pub use stats::{Prob, LogProb};

/// A factor to convert log-probabilities to PHRED-scale (phred = p * LOG_TO_PHRED_FACTOR).
const LOG_TO_PHRED_FACTOR: f64 = -4.3429448190325175; // -10 * 1 / ln(10)

/// A factor to convert PHRED-scale to log-probabilities (p = phred * PHRED_TO_LOG_FACTOR).
const PHRED_TO_LOG_FACTOR: f64 = -0.23025850929940456; // 1 / (-10 * log10(e))

/// Calculate log(1 - p) with p given in log space without loss of precision as described in
/// http://cran.r-project.org/web/packages/Rmpfr/vignettes/log1mexp-note.pdf.
pub fn ln_1m_exp(p: LogProb) -> LogProb {
    assert!(p <= 0.0);
    if p < -0.693 {
        (-p.exp()).ln_1p()
    } else {
        (-p.exp_m1()).ln()
    }
}

/// Convert log scale probability to PHRED scale.
pub fn log_to_phred(p: LogProb) -> f64 {
    p * LOG_TO_PHRED_FACTOR
}

/// Convert PHRED scale probability to log scale.
pub fn phred_to_log(p: f64) -> LogProb {
    p * PHRED_TO_LOG_FACTOR
}

/// Calculate the sum of the given probabilities in a numerically stable way (Durbin 1998).
pub fn sum(probs: &[LogProb]) -> LogProb {
    if probs.is_empty() {
        f64::NEG_INFINITY
    } else {
        let mut pmax = probs[0];
        let mut imax = 0;
        for (i, &p) in probs.iter().enumerate().skip(1) {
            if p > pmax {
                pmax = p;
                imax = i;
            }
        }
        if pmax == f64::NEG_INFINITY {
            f64::NEG_INFINITY
        } else if pmax == f64::INFINITY {
            f64::INFINITY
        } else {
            // TODO use sum() once it has been stabilized: .sum::<usize>()
            pmax +
            (probs.iter()
                  .enumerate()
                  .filter_map(|(i, p)| {
                      if i == imax {
                          None
                      } else {
                          Some((p - pmax).exp())
                      }
                  })
                  .fold(0.0, |s, e| s + e))
                .ln_1p()
        }
    }
}

/// Add the given probabilities in a numerically stable way (Durbin 1998).
pub fn add(mut p0: LogProb, mut p1: LogProb) -> LogProb {
    if p1 > p0 {
        mem::swap(&mut p0, &mut p1);
    }
    if p0 == f64::NEG_INFINITY {
        f64::NEG_INFINITY
    } else if p0 == f64::INFINITY {
        f64::INFINITY
    } else {
        p0 + (p1 - p0).exp().ln_1p()
    }
}

/// Subtract the given probabilities in a numerically stable way (Durbin 1998).
pub fn sub(p0: LogProb, p1: LogProb) -> LogProb {
    if p1 > p0 {
        panic!("Subtraction would lead to negative probability, which is undefined in log space.");
    }
    if p0 == p1 || p0 == f64::NEG_INFINITY {
        // the first case leads to zero,
        // in the second case p0 and p1 are -inf, which is fine
        f64::NEG_INFINITY
    } else if p0 == f64::INFINITY {
        f64::INFINITY
    } else {
        p0 + ln_1m_exp(p1 - p0)
    }
}

fn scan_add(s: &mut LogProb, p: LogProb) -> Option<LogProb> {
    *s = add(*s, p);
    Some(*s)
}

/// Iterator returned by scans over logprobs.
pub type ScanIter<I> = iter::Scan<I, LogProb, fn(&mut LogProb, LogProb) -> Option<LogProb>>;

/// Calculate the cumulative sum of the given probabilities in a numerically stable way (Durbin 1998).
pub fn cumsum<I: Iterator<Item = LogProb>>(probs: I) -> ScanIter<I> {
    probs.scan(f64::NEG_INFINITY, scan_add)
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::f64;
    use itertools::Itertools;

    #[test]
    fn test_sum() {
        let probs = [f64::NEG_INFINITY, 0.0, f64::NEG_INFINITY];
        assert_eq!(sum(&probs), 0.0);
    }

    #[test]
    fn test_empty_sum() {
        assert_eq!(sum(&[]), f64::NEG_INFINITY);
    }

    #[test]
    fn test_cumsum() {
        let probs = vec![0.0f64.ln(), 0.01f64.ln(), 0.001f64.ln()];
        assert_eq!(cumsum(probs.into_iter()).collect_vec(),
                   [0.0f64.ln(), 0.01f64.ln(), 0.011f64.ln()]);
    }

    #[test]
    fn test_sub() {
        assert_eq!(sub(0.0f64.ln(), 0.0f64.ln()), f64::NEG_INFINITY);
        assert_relative_eq!(sub(1.0f64.ln(), 0.5f64.ln()), 0.5f64.ln());
    }

    #[test]
    fn test_ln_1m_exp() {
        assert_eq!(ln_1m_exp(f64::NEG_INFINITY), 0.0);
        assert_eq!(ln_1m_exp(0.0001), f64::NEG_INFINITY);
    }
}
<|endoftext|>


<commit_before>use libimagstore::store::EntryHeader;

use error::{LinkError, LinkErrorKind};
use link::{Link, Links};
use result::Result;

use toml::Value;
use toml::Table;

pub fn get_link(header: &EntryHeader) -> Result<Option<Link>> {
    let uri = header.read("imag.content.uri");

    if uri.is_err() {
        let kind = LinkErrorKind::EntryHeaderReadError;
        let lerr = LinkError::new(kind, Some(Box::new(uri.err().unwrap())));
        return Err(lerr);
    }
    let uri = uri.unwrap();

    match uri {
        Some(Value::String(s)) => Ok(Some(Link::new(s))),
        _ => Err(LinkError::new(LinkErrorKind::ExistingLinkTypeWrong, None)),
    }
}

/// Set an external link in the header
///
/// Return the previous set link if there was any
pub fn set_link(header: &mut EntryHeader, l: Link) -> Result<Option<Link>> {
    let old_link = header.set("imag.content.uri", Value::String(l.into()));

    if old_link.is_err() {
        let kind = LinkErrorKind::EntryHeaderWriteError;
        let lerr = LinkError::new(kind, Some(Box::new(old_link.err().unwrap())));
        return Err(lerr);
    }
    let old_link = old_link.unwrap();

    if old_link.is_none() {
        return Ok(None);
    }

    match old_link.unwrap() {
        Value::String(s) => Ok(Some(Link::new(s))),

        // We don't do anything in this case and be glad we corrected the type error with this set()
        _ => Ok(None),
    }
}

<commit_msg>Refactor external linking into trait<commit_after>use libimagstore::store::EntryHeader;

use error::{LinkError, LinkErrorKind};
use link::{Link, Links};
use result::Result;

use toml::Value;
use toml::Table;

pub trait ExternalLinker {

    /// get the external link from the implementor object
    fn get_external_link(&self) -> Result<Option<Link>>;

    /// set the external link for the implementor object and return the current link from the entry,
    /// if any.
    fn set_external_link(&mut self, l: Link) -> Result<Option<Link>>;
}

impl ExternalLinker for EntryHeader {

    fn get_external_link(&self) -> Result<Option<Link>> {
        let uri = self.read("imag.content.uri");

        if uri.is_err() {
            let kind = LinkErrorKind::EntryHeaderReadError;
            let lerr = LinkError::new(kind, Some(Box::new(uri.err().unwrap())));
            return Err(lerr);
        }
        let uri = uri.unwrap();

        match uri {
            Some(Value::String(s)) => Ok(Some(Link::new(s))),
            _ => Err(LinkError::new(LinkErrorKind::ExistingLinkTypeWrong, None)),
        }
    }

    /// Set an external link in the header
    ///
    /// Return the previous set link if there was any
    fn set_external_link(&mut self, l: Link) -> Result<Option<Link>> {
        let old_link = self.set("imag.content.uri", Value::String(l.into()));

        if old_link.is_err() {
            let kind = LinkErrorKind::EntryHeaderWriteError;
            let lerr = LinkError::new(kind, Some(Box::new(old_link.err().unwrap())));
            return Err(lerr);
        }
        let old_link = old_link.unwrap();

        if old_link.is_none() {
            return Ok(None);
        }

        match old_link.unwrap() {
            Value::String(s) => Ok(Some(Link::new(s))),

            // We don't do anything in this case and be glad we corrected the type error with this set()
            _ => Ok(None),
        }
    }

}

<|endoftext|>


<commit_before>use std::fmt;

use liquid_error::{Error, Result};
use liquid_value::Path;
use liquid_value::Scalar;
use liquid_value::{ValueCow, ValueView};

use super::Expression;
use super::Runtime;

/// A `Value` reference.
#[derive(Clone, Debug, PartialEq)]
pub struct Variable {
    variable: Scalar,
    indexes: Vec<Expression>,
}

impl Variable {
    /// Create a `Value` reference.
    pub fn with_literal<S: Into<Scalar>>(value: S) -> Self {
        Self {
            variable: value.into(),
            indexes: Default::default(),
        }
    }

    /// Append a literal.
    pub fn push_literal<S: Into<Scalar>>(mut self, value: S) -> Self {
        self.indexes.push(Expression::with_literal(value));
        self
    }

    /// Convert to a `Path`.
    pub fn try_evaluate<'c>(&'c self, runtime: &'c Runtime<'_>) -> Option<Path<'c>> {
        let mut path = Path::with_index(self.variable.as_ref());
        path.reserve(self.indexes.len());
        for expr in &self.indexes {
            let v = expr.try_evaluate(runtime)?;
            let s = match v {
                ValueCow::Owned(v) => v.into_scalar(),
                ValueCow::Borrowed(v) => v.as_scalar(),
            }?;
            path.push(s);
        }
        Some(path)
    }

    /// Convert to a `Path`.
    pub fn evaluate<'c>(&'c self, runtime: &'c Runtime<'_>) -> Result<Path<'c>> {
        let mut path = Path::with_index(self.variable.as_ref());
        path.reserve(self.indexes.len());
        for expr in &self.indexes {
            let v = expr.evaluate(runtime)?;
            let s = match v {
                ValueCow::Owned(v) => v.into_scalar(),
                ValueCow::Borrowed(v) => v.as_scalar(),
            }
            .ok_or_else(|| {
                let v = expr.evaluate(runtime).expect("lookup already verified");
                Error::with_msg(format!("Expected scalar, found `{}`", v.source()))
            })?;
            path.push(s);
        }
        Ok(path)
    }
}

impl Extend<Scalar> for Variable {
    fn extend<T: IntoIterator<Item = Scalar>>(&mut self, iter: T) {
        let path = iter.into_iter().map(Expression::with_literal);
        self.indexes.extend(path);
    }
}

impl Extend<Expression> for Variable {
    fn extend<T: IntoIterator<Item = Expression>>(&mut self, iter: T) {
        let path = iter.into_iter();
        self.indexes.extend(path);
    }
}

impl fmt::Display for Variable {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.variable.render())?;
        for index in self.indexes.iter() {
            write!(f, "[{}]", index)?;
        }
        Ok(())
    }
}

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

    use liquid_value::Object;
    use liquid_value::ValueViewCmp;
    use serde_yaml;

    use super::super::RuntimeBuilder;

    #[test]
    fn identifier_path_array_index() {
        let globals: Object = serde_yaml::from_str(
            r#"
test_a: ["test"]
"#,
        )
        .unwrap();
        let mut var = Variable::with_literal("test_a");
        let index = vec![Scalar::new(0)];
        var.extend(index);

        let runtime = RuntimeBuilder::new().set_globals(&globals).build();
        let actual = var.evaluate(&runtime).unwrap();
        let actual = runtime.stack().get(&actual).unwrap();
        assert_eq!(actual, ValueViewCmp::new(&"test"));
    }

    #[test]
    fn identifier_path_array_index_negative() {
        let globals: Object = serde_yaml::from_str(
            r#"
test_a: ["test1", "test2"]
"#,
        )
        .unwrap();
        let mut var = Variable::with_literal("test_a");
        let index = vec![Scalar::new(-1)];
        var.extend(index);

        let runtime = RuntimeBuilder::new().set_globals(&globals).build();
        let actual = var.evaluate(&runtime).unwrap();
        let actual = runtime.stack().get(&actual).unwrap();
        assert_eq!(actual, ValueViewCmp::new(&"test2"));
    }

    #[test]
    fn identifier_path_object() {
        let globals: Object = serde_yaml::from_str(
            r#"
test_a:
  - test_h: 5
"#,
        )
        .unwrap();
        let mut var = Variable::with_literal("test_a");
        let index = vec![Scalar::new(0), Scalar::new("test_h")];
        var.extend(index);

        let runtime = RuntimeBuilder::new().set_globals(&globals).build();
        let actual = var.evaluate(&runtime).unwrap();
        let actual = runtime.stack().get(&actual).unwrap();
        assert_eq!(actual, ValueViewCmp::new(&5));
    }
}
<commit_msg>fix: Try to make Rust 1.37 happy<commit_after>use std::fmt;

use liquid_error::{Error, Result};
use liquid_value::Path;
use liquid_value::Scalar;
use liquid_value::{ValueCow, ValueView};

use super::Expression;
use super::Runtime;

/// A `Value` reference.
#[derive(Clone, Debug, PartialEq)]
pub struct Variable {
    variable: Scalar,
    indexes: Vec<Expression>,
}

impl Variable {
    /// Create a `Value` reference.
    pub fn with_literal<S: Into<Scalar>>(value: S) -> Self {
        Self {
            variable: value.into(),
            indexes: Default::default(),
        }
    }

    /// Append a literal.
    pub fn push_literal<S: Into<Scalar>>(mut self, value: S) -> Self {
        self.indexes.push(Expression::with_literal(value));
        self
    }

    /// Convert to a `Path`.
    pub fn try_evaluate<'c>(&'c self, runtime: &'c Runtime<'_>) -> Option<Path<'c>> {
        let mut path = Path::with_index(self.variable.as_ref());
        path.reserve(self.indexes.len());
        for expr in &self.indexes {
            let v = expr.try_evaluate(runtime)?;
            let s = match v {
                ValueCow::Owned(v) => v.into_scalar(),
                ValueCow::Borrowed(v) => v.as_scalar(),
            }?;
            path.push(s);
        }
        Some(path)
    }

    /// Convert to a `Path`.
    pub fn evaluate<'c>(&'c self, runtime: &'c Runtime<'_>) -> Result<Path<'c>> {
        let mut path = Path::with_index(self.variable.as_ref());
        path.reserve(self.indexes.len());
        for expr in &self.indexes {
            let v = expr.evaluate(runtime)?;
            let s = match v {
                ValueCow::Owned(v) => v.into_scalar(),
                ValueCow::Borrowed(v) => v.as_scalar(),
            }
            .ok_or_else(|| {
                let v = expr.evaluate(runtime).expect("lookup already verified");
                let v = v.source();
                let msg = format!("Expected scalar, found `{}`", v);
                Error::with_msg(msg)
            })?;
            path.push(s);
        }
        Ok(path)
    }
}

impl Extend<Scalar> for Variable {
    fn extend<T: IntoIterator<Item = Scalar>>(&mut self, iter: T) {
        let path = iter.into_iter().map(Expression::with_literal);
        self.indexes.extend(path);
    }
}

impl Extend<Expression> for Variable {
    fn extend<T: IntoIterator<Item = Expression>>(&mut self, iter: T) {
        let path = iter.into_iter();
        self.indexes.extend(path);
    }
}

impl fmt::Display for Variable {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.variable.render())?;
        for index in self.indexes.iter() {
            write!(f, "[{}]", index)?;
        }
        Ok(())
    }
}

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

    use liquid_value::Object;
    use liquid_value::ValueViewCmp;
    use serde_yaml;

    use super::super::RuntimeBuilder;

    #[test]
    fn identifier_path_array_index() {
        let globals: Object = serde_yaml::from_str(
            r#"
test_a: ["test"]
"#,
        )
        .unwrap();
        let mut var = Variable::with_literal("test_a");
        let index = vec![Scalar::new(0)];
        var.extend(index);

        let runtime = RuntimeBuilder::new().set_globals(&globals).build();
        let actual = var.evaluate(&runtime).unwrap();
        let actual = runtime.stack().get(&actual).unwrap();
        assert_eq!(actual, ValueViewCmp::new(&"test"));
    }

    #[test]
    fn identifier_path_array_index_negative() {
        let globals: Object = serde_yaml::from_str(
            r#"
test_a: ["test1", "test2"]
"#,
        )
        .unwrap();
        let mut var = Variable::with_literal("test_a");
        let index = vec![Scalar::new(-1)];
        var.extend(index);

        let runtime = RuntimeBuilder::new().set_globals(&globals).build();
        let actual = var.evaluate(&runtime).unwrap();
        let actual = runtime.stack().get(&actual).unwrap();
        assert_eq!(actual, ValueViewCmp::new(&"test2"));
    }

    #[test]
    fn identifier_path_object() {
        let globals: Object = serde_yaml::from_str(
            r#"
test_a:
  - test_h: 5
"#,
        )
        .unwrap();
        let mut var = Variable::with_literal("test_a");
        let index = vec![Scalar::new(0), Scalar::new("test_h")];
        var.extend(index);

        let runtime = RuntimeBuilder::new().set_globals(&globals).build();
        let actual = var.evaluate(&runtime).unwrap();
        let actual = runtime.stack().get(&actual).unwrap();
        assert_eq!(actual, ValueViewCmp::new(&5));
    }
}
<|endoftext|>


<commit_before>#![allow(non_snake_case)]

mod counter;

use counter::Counter;
use std::mem::transmute;

/// Allocate a new counter on the heap and return its pointer.
///
/// Dereferencing is preferred over transmute here since it's generally slightly more restrictive.
#[no_mangle]
pub extern fn createCounter(val: u32) -> *mut Counter {
    let _counter = unsafe { transmute(Box::new(Counter::new(val))) };
    _counter
}

#[no_mangle]
pub extern fn getCounterValue(ptr: *mut Counter) -> u32 {
    let mut _counter = unsafe { &mut *ptr };
    _counter.get()
}

#[no_mangle]
pub extern fn incrementCounterBy(ptr: *mut Counter, by: u32) -> u32 {
    let mut _counter = unsafe { &mut *ptr };
    _counter.incr(by)
}

#[no_mangle]
pub extern fn decrementCounterBy(ptr: *mut Counter, by: u32) -> u32 {
    let mut _counter = unsafe { &mut *ptr };
    _counter.decr(by)
}

/// Transmute the ptr back into its box so it can be dropped.
///
/// We could use Box::from_raw but it's currently unstable.
#[no_mangle]
pub extern fn destroyCounter(ptr: *mut Counter) {
    let _counter: Box<Counter> = unsafe{ transmute(ptr) };
    // Drop
}
<commit_msg>Removing outdated comments<commit_after>#![allow(non_snake_case)]

mod counter;

use counter::Counter;
use std::mem::transmute;

#[no_mangle]
pub extern fn createCounter(val: u32) -> *mut Counter {
    let _counter = unsafe { transmute(Box::new(Counter::new(val))) };
    _counter
}

#[no_mangle]
pub extern fn getCounterValue(ptr: *mut Counter) -> u32 {
    let mut _counter = unsafe { &mut *ptr };
    _counter.get()
}

#[no_mangle]
pub extern fn incrementCounterBy(ptr: *mut Counter, by: u32) -> u32 {
    let mut _counter = unsafe { &mut *ptr };
    _counter.incr(by)
}

#[no_mangle]
pub extern fn decrementCounterBy(ptr: *mut Counter, by: u32) -> u32 {
    let mut _counter = unsafe { &mut *ptr };
    _counter.decr(by)
}

#[no_mangle]
pub extern fn destroyCounter(ptr: *mut Counter) {
    let _counter: Box<Counter> = unsafe{ transmute(ptr) };
    // Drop
}
<|endoftext|>


<commit_before>// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

use serde_generate::{dart, test_utils, CodeGeneratorConfig, Encoding, SourceInstaller};
use std::{io::Result, path::PathBuf, process::Command};
use tempfile::tempdir;

fn install_test_dependency(path: PathBuf) -> Result<()> {
    Command::new("dart")
        .current_dir(path)
        .args(["pub", "add", "-d", "test"])
        .status()?;

    Ok(())
}

fn test_dart_code_compiles_with_config(
    source_path: PathBuf,
    config: &CodeGeneratorConfig,
) -> PathBuf {
    let registry = test_utils::get_registry().unwrap();

    let installer = dart::Installer::new(source_path.to_path_buf());
    installer.install_module(&config, &registry).unwrap();
    installer.install_serde_runtime().unwrap();
    installer.install_bincode_runtime().unwrap();
    installer.install_bcs_runtime().unwrap();

    install_test_dependency(source_path.to_path_buf()).unwrap();

    let dart_analyze = Command::new("dart")
        .current_dir(source_path.to_path_buf())
        .args(["analyze"])
        .status()
        .unwrap();

    assert!(
        dart_analyze.success(),
        "Generated Dart source code did not pass `dart analyze`"
    );

    source_path
}

#[test]
fn test_dart_code_compiles() {
    let tempdir = tempdir().unwrap();
    let source_path = tempdir.path().join("dart_project");

    let config = CodeGeneratorConfig::new("example".to_string())
        .with_encodings(vec![Encoding::Bcs, Encoding::Bincode])
        .with_c_style_enums(true);

    test_dart_code_compiles_with_config(source_path, &config);
    tempdir.close().unwrap();
}

#[test]
fn test_dart_code_compiles_with_comments() {
    let tempdir = tempdir().unwrap();
    let source_path = tempdir.path().join("dart_project");

    let comments = vec![(
        vec!["example".to_string(), "SerdeData".to_string()],
        "Some\ncomments".to_string(),
    )]
    .into_iter()
    .collect();

    let config = CodeGeneratorConfig::new("example".to_string())
        .with_encodings(vec![Encoding::Bincode])
        .with_c_style_enums(true)
        .with_comments(comments);

    let path = test_dart_code_compiles_with_config(source_path, &config);

    // Comment was correctly generated.
    let content = std::fs::read_to_string(
        path.join("lib")
            .join("src")
            .join(config.module_name())
            .join("serde_data.dart"),
    )
    .unwrap();

    assert!(content.contains(
        r#"
/// Some
/// comments
"#
    ));

    tempdir.close().unwrap();
}

#[test]
fn test_dart_code_compiles_with_class_enums() {
    let tempdir = tempdir().unwrap();
    let source_path = tempdir.path().join("dart_project");

    let config = CodeGeneratorConfig::new("example".to_string())
        .with_encodings(vec![Encoding::Bcs, Encoding::Bincode])
        .with_c_style_enums(false);

    test_dart_code_compiles_with_config(source_path, &config);

    tempdir.close().unwrap();
}
<commit_msg>Clean up tempdir usage in Dart generation tests<commit_after>// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

use serde_generate::{dart, test_utils, CodeGeneratorConfig, Encoding, SourceInstaller};
use std::{io::Result, path::PathBuf, process::Command};
use tempfile::tempdir;

fn install_test_dependencies(path: PathBuf) -> Result<()> {
    Command::new("dart")
        .current_dir(path.to_path_buf())
        .args(["pub", "add", "-d", "test"])
        .status()?;

    Ok(())
}

fn generate_with_config(source_path: PathBuf, config: &CodeGeneratorConfig) -> PathBuf {
    let registry = test_utils::get_registry().unwrap();

    let installer = dart::Installer::new(source_path.to_path_buf());
    installer.install_module(&config, &registry).unwrap();
    installer.install_serde_runtime().unwrap();
    installer.install_bincode_runtime().unwrap();
    installer.install_bcs_runtime().unwrap();

    install_test_dependencies(source_path.to_path_buf()).unwrap();

    let dart_analyze = Command::new("dart")
        .current_dir(source_path.to_path_buf())
        .args(["analyze"])
        .status()
        .unwrap();

    assert!(
        dart_analyze.success(),
        "Generated Dart source code did not pass `dart analyze`"
    );

    source_path
}

#[test]
fn test_dart_code_compiles() {
    let source_path = tempdir().unwrap().path().join("dart_basic_project");

    let config = CodeGeneratorConfig::new("example".to_string())
        .with_encodings(vec![Encoding::Bcs, Encoding::Bincode])
        .with_c_style_enums(true);

    generate_with_config(source_path, &config);
}

#[test]
fn test_dart_code_compiles_with_comments() {
    let source_path = tempdir().unwrap().path().join("dart_comment_project");

    let comments = vec![(
        vec!["example".to_string(), "SerdeData".to_string()],
        "Some\ncomments".to_string(),
    )]
    .into_iter()
    .collect();

    let config = CodeGeneratorConfig::new("example".to_string())
        .with_encodings(vec![Encoding::Bincode])
        .with_c_style_enums(true)
        .with_comments(comments);

    let path = generate_with_config(source_path, &config);

    // Comment was correctly generated.
    let content = std::fs::read_to_string(
        path.join("lib")
            .join("src")
            .join(config.module_name())
            .join("serde_data.dart"),
    )
    .unwrap();

    assert!(content.contains(
        r#"
/// Some
/// comments
"#
    ));
}

#[test]
fn test_dart_code_compiles_with_class_enums() {
    let source_path = tempdir().unwrap().path().join("dart_enum_project");

    let config = CodeGeneratorConfig::new("example".to_string())
        .with_encodings(vec![Encoding::Bcs, Encoding::Bincode])
        .with_c_style_enums(false);

    generate_with_config(source_path, &config);
}
<|endoftext|>


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

use std::mem;
use std::str::FromStr;

use bevy::ecs::component::Component;
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use serde::{Deserialize, Serialize};

use crate::config::scoring::ScoringConfig;
use crate::model::{Scenario, World};
use crate::storage::sqlite::SqliteStorage;
use crate::storage::Storage;
use crate::world::Planet;
use crate::SaverState;

use self::scoring_function::Expression;

mod scoring_function;

pub struct ScoringPlugin;

impl Plugin for ScoringPlugin {
    fn build(&self, app: &mut AppBuilder) {
        app.init_resource::<ActiveWorld>()
            .add_startup_system(setup.system())
            .add_system_set(
                SystemSet::on_update(SaverState::Run)
                    .with_system(score.system().label("compute-score"))
                    .with_system(score_text.system().after("compute-score")),
            )
            .add_system_set(
                SystemSet::on_exit(SaverState::Run)
                    .with_system(store_result::<SqliteStorage>.system()),
            );
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(transparent)]
pub struct ScoringFunction(Expression);

impl ScoringFunction {
    /// Evaluate the expression given the scoring function inputs.
    pub fn eval(&self, elapsed_fract: f64, total_mass: f64, mass_count: f64) -> f64 {
        self.0.eval(elapsed_fract, total_mass, mass_count)
    }
}

impl FromStr for ScoringFunction {
    type Err = String;

    fn from_str(source: &str) -> Result<ScoringFunction, String> {
        source.parse().map(ScoringFunction)
    }
}

/// Resource for tracking the status of the currently active scene.
pub struct ActiveWorld {
    /// The world being scored.
    pub world: World,
    /// The parent of the world being scored.
    pub parent: Option<Scenario>,
    /// The score the world has received so far.
    pub cumulative_score: f64,
    /// The number of physics ticks that the world has been scored on so far.
    pub timer: Timer,
}

impl ActiveWorld {
    /// Reset the active world for a new scenario.
    pub fn start(&mut self, world: World, parent: Option<Scenario>) {
        self.world = world;
        self.parent = parent;
        self.cumulative_score = 0.0;
        self.timer.reset();
    }
}

impl FromWorld for ActiveWorld {
    fn from_world(world: &mut bevy::ecs::world::World) -> Self {
        let config = world.get_resource::<ScoringConfig>().unwrap();
        ActiveWorld {
            world: World { planets: vec![] },
            parent: None,
            cumulative_score: 0.,
            timer: Timer::new(config.scored_time, false),
        }
    }
}

/// Marker component for the score text entity.
struct ScoreText;

/// Adds a ui camera and score keeper text.
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn_bundle(UiCameraBundle::default());
    commands
        .spawn_bundle(TextBundle {
            style: Style {
                align_self: AlignSelf::FlexEnd,
                ..Default::default()
            },
            text: Text {
                sections: vec![
                    TextSection {
                        value: "Score: ".to_string(),
                        style: TextStyle {
                            font: asset_server.load("fonts/FiraSans-Book.ttf"),
                            font_size: 60.0,
                            color: Color::WHITE,
                        },
                    },
                    TextSection {
                        value: "".to_string(),
                        style: TextStyle {
                            font: asset_server.load("fonts/FiraMono-Regular.ttf"),
                            font_size: 60.0,
                            color: Color::GOLD,
                        },
                    },
                ],
                ..Default::default()
            },
            ..Default::default()
        })
        .insert(ScoreText);
}

/// Compute the scenario score for each frame.
fn score(
    time: Res<Time>,
    mut world: ResMut<ActiveWorld>,
    config: Res<ScoringConfig>,
    query: Query<&RigidBodyMassProps, With<Planet>>,
    mut state: ResMut<State<SaverState>>,
) {
    world.timer.tick(time.delta());

    let scenario_time = world.timer.percent() as f64;
    let mut mass_count = 0.0;
    let mut total_mass = 0.0;

    let maxx = config.scored_area.width / 2.0;
    let maxy = config.scored_area.height / 2.0;
    let maxz = config.scored_area.depth / 2.0;

    for rb in query.iter() {
        if rb.world_com.x.abs() > maxx || rb.world_com.y.abs() > maxy || rb.world_com.z.abs() > maxz
        {
            continue;
        }
        mass_count += 1.0;
        total_mass += rb.mass() as f64;
    }

    world.cumulative_score += config
        .score_per_second
        .eval(scenario_time, total_mass, mass_count)
        * time.delta_seconds_f64();

    if world.timer.just_finished() {
        state
            .set(SaverState::Generate)
            .expect("Unable to switch to scenario generation");
    }
}

/// Put the score in the score text.
fn score_text(world: Res<ActiveWorld>, mut query: Query<&mut Text, With<ScoreText>>) {
    for mut text in query.iter_mut() {
        text.sections[1].value = format!("{:.2}", world.cumulative_score);
    }
}

/// Store scenario results.
fn store_result<S: Storage + Component>(mut tracker: ResMut<ActiveWorld>, mut storage: ResMut<S>) {
    info!("Storing scored world");
    let world = mem::replace(&mut tracker.world, World::default());
    let parent = mem::replace(&mut tracker.parent, None);
    let score = if tracker.cumulative_score.is_nan() {
        warn!("Score was NaN, replacing with -inf");
        f64::NEG_INFINITY
    } else {
        tracker.cumulative_score
    };
    let store_result = match parent {
        Some(parent) => storage.add_child_scenario(world, score, &parent),
        None => storage.add_root_scenario(world, score),
    };
    match store_result {
        Err(error) => error!("Error while storing finished scenario: {}", error),
        Ok(scenario) => info!(
            "Saved scenario {} (parent: {:?}, family: {}, generation: {}) with score {}",
            scenario.id, scenario.parent, scenario.family, scenario.generation, scenario.score,
        ),
    }
}

// #[derive(Default)]
// pub struct ScoreKeeper<T>(PhantomData<T>);
//
// impl<'a, T> System<'a> for ScoreKeeper<T> where T: Storage + Default + Send + Sync + 'static {
//     type SystemData = (
//         Read<'a, ScoringConfig>,
//         Write<'a, ActiveWorld>,
//         Write<'a, T>,
//         Write<'a, SceneChange>,
//         ReadStorage<'a, Position>,
//         ReadStorage<'a, Mass>,
//         ReadStorage<'a, Deleted>,
//         area_scaling::AreaScalingData<'a>,
//     );
//
//     fn run(
//         &mut self,
//         (
//             scoring,
//             mut world_track,
//             mut storage,
//             mut scene_change,
//             positions,
//             masses,
//             deleted,
//             scaling_data,
//         ): Self::SystemData,
//     ) {
//         if world_track.ticks_completed < scoring.scored_ticks {
//             let vertical_half_extent = scoring.scored_area.height / 2.;
//             let horizontal_half_extent = if scoring.scored_area.scale_width_by_aspect {
//                 let aspect = area_scaling::get_aspect(&scaling_data);
//                 scoring.scored_area.width * aspect
//             } else {
//                 scoring.scored_area.width
//             } / 2.;
//
//             let mut mass_count = 0f64;
//             let mut total_mass = 0f64;
//             for (position, mass, _) in (&positions, &masses, !&deleted).join() {
//                 let pos = position.pos();
//                 if pos.x.abs() <= horizontal_half_extent && pos.y.abs() <= vertical_half_extent {
//                     mass_count += 1.;
//                     total_mass += mass.linear as f64
//                 }
//             }
//             world_track.cumulative_score += scoring.per_frame_scoring
//                 .eval(world_track.ticks_completed as f64, total_mass, mass_count);
//             world_track.ticks_completed += 1;
//         } else {
//             info!("Storing scored world");
//             let world = mem::replace(&mut world_track.world, World::default());
//             let parent = mem::replace(&mut world_track.parent, None);
//             let score = match mem::replace(&mut world_track.cumulative_score, 0.) {
//                 score if score.is_nan() => {
//                     warn!("Score was NaN, replacing with -inf");
//                     ::std::f64::NEG_INFINITY
//                 },
//                 score => score,
//             };
//             world_track.ticks_completed = 0;
//             let store_result = match parent {
//                 Some(parent) => storage.add_child_scenario(world, score, &parent),
//                 None => storage.add_root_scenario(world, score),
//             };
//             match store_result {
//                 Err(error) => error!("Error while storing finished scenario: {}", error),
//                 Ok(scenario) => info!(
//                     "Saved scenario {} (parent: {:?}, family: {}, generation: {}) with score {}",
//                     scenario.id,
//                     scenario.parent,
//                     scenario.family,
//                     scenario.generation,
//                     scenario.score,
//                 ),
//             }
//             scene_change.change_scene(WorldGenerator::<T>::default());
//         }
//     }
// }
<commit_msg>remove commented code from statustracker<commit_after>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::mem;
use std::str::FromStr;

use bevy::ecs::component::Component;
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use serde::{Deserialize, Serialize};

use crate::config::scoring::ScoringConfig;
use crate::model::{Scenario, World};
use crate::storage::sqlite::SqliteStorage;
use crate::storage::Storage;
use crate::world::Planet;
use crate::SaverState;

use self::scoring_function::Expression;

mod scoring_function;

pub struct ScoringPlugin;

impl Plugin for ScoringPlugin {
    fn build(&self, app: &mut AppBuilder) {
        app.init_resource::<ActiveWorld>()
            .add_startup_system(setup.system())
            .add_system_set(
                SystemSet::on_update(SaverState::Run)
                    .with_system(score.system().label("compute-score"))
                    .with_system(score_text.system().after("compute-score")),
            )
            .add_system_set(
                SystemSet::on_exit(SaverState::Run)
                    .with_system(store_result::<SqliteStorage>.system()),
            );
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(transparent)]
pub struct ScoringFunction(Expression);

impl ScoringFunction {
    /// Evaluate the expression given the scoring function inputs.
    pub fn eval(&self, elapsed_fract: f64, total_mass: f64, mass_count: f64) -> f64 {
        self.0.eval(elapsed_fract, total_mass, mass_count)
    }
}

impl FromStr for ScoringFunction {
    type Err = String;

    fn from_str(source: &str) -> Result<ScoringFunction, String> {
        source.parse().map(ScoringFunction)
    }
}

/// Resource for tracking the status of the currently active scene.
pub struct ActiveWorld {
    /// The world being scored.
    pub world: World,
    /// The parent of the world being scored.
    pub parent: Option<Scenario>,
    /// The score the world has received so far.
    pub cumulative_score: f64,
    /// The number of physics ticks that the world has been scored on so far.
    pub timer: Timer,
}

impl ActiveWorld {
    /// Reset the active world for a new scenario.
    pub fn start(&mut self, world: World, parent: Option<Scenario>) {
        self.world = world;
        self.parent = parent;
        self.cumulative_score = 0.0;
        self.timer.reset();
    }
}

impl FromWorld for ActiveWorld {
    fn from_world(world: &mut bevy::ecs::world::World) -> Self {
        let config = world.get_resource::<ScoringConfig>().unwrap();
        ActiveWorld {
            world: World { planets: vec![] },
            parent: None,
            cumulative_score: 0.,
            timer: Timer::new(config.scored_time, false),
        }
    }
}

/// Marker component for the score text entity.
struct ScoreText;

/// Adds a ui camera and score keeper text.
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn_bundle(UiCameraBundle::default());
    commands
        .spawn_bundle(TextBundle {
            style: Style {
                align_self: AlignSelf::FlexEnd,
                ..Default::default()
            },
            text: Text {
                sections: vec![
                    TextSection {
                        value: "Score: ".to_string(),
                        style: TextStyle {
                            font: asset_server.load("fonts/FiraSans-Book.ttf"),
                            font_size: 60.0,
                            color: Color::WHITE,
                        },
                    },
                    TextSection {
                        value: "".to_string(),
                        style: TextStyle {
                            font: asset_server.load("fonts/FiraMono-Regular.ttf"),
                            font_size: 60.0,
                            color: Color::GOLD,
                        },
                    },
                ],
                ..Default::default()
            },
            ..Default::default()
        })
        .insert(ScoreText);
}

/// Compute the scenario score for each frame.
fn score(
    time: Res<Time>,
    mut world: ResMut<ActiveWorld>,
    config: Res<ScoringConfig>,
    query: Query<&RigidBodyMassProps, With<Planet>>,
    mut state: ResMut<State<SaverState>>,
) {
    world.timer.tick(time.delta());

    let scenario_time = world.timer.percent() as f64;
    let mut mass_count = 0.0;
    let mut total_mass = 0.0;

    let maxx = config.scored_area.width / 2.0;
    let maxy = config.scored_area.height / 2.0;
    let maxz = config.scored_area.depth / 2.0;

    for rb in query.iter() {
        if rb.world_com.x.abs() > maxx || rb.world_com.y.abs() > maxy || rb.world_com.z.abs() > maxz
        {
            continue;
        }
        mass_count += 1.0;
        total_mass += rb.mass() as f64;
    }

    world.cumulative_score += config
        .score_per_second
        .eval(scenario_time, total_mass, mass_count)
        * time.delta_seconds_f64();

    if world.timer.just_finished() {
        state
            .set(SaverState::Generate)
            .expect("Unable to switch to scenario generation");
    }
}

/// Put the score in the score text.
fn score_text(world: Res<ActiveWorld>, mut query: Query<&mut Text, With<ScoreText>>) {
    for mut text in query.iter_mut() {
        text.sections[1].value = format!("{:.2}", world.cumulative_score);
    }
}

/// Store scenario results.
fn store_result<S: Storage + Component>(mut tracker: ResMut<ActiveWorld>, mut storage: ResMut<S>) {
    info!("Storing scored world");
    let world = mem::replace(&mut tracker.world, World::default());
    let parent = mem::replace(&mut tracker.parent, None);
    let score = if tracker.cumulative_score.is_nan() {
        warn!("Score was NaN, replacing with -inf");
        f64::NEG_INFINITY
    } else {
        tracker.cumulative_score
    };
    let store_result = match parent {
        Some(parent) => storage.add_child_scenario(world, score, &parent),
        None => storage.add_root_scenario(world, score),
    };
    match store_result {
        Err(error) => error!("Error while storing finished scenario: {}", error),
        Ok(scenario) => info!(
            "Saved scenario {} (parent: {:?}, family: {}, generation: {}) with score {}",
            scenario.id, scenario.parent, scenario.family, scenario.generation, scenario.score,
        ),
    }
}
<|endoftext|>


<commit_before>//! Lazily compute the reverse control-flow graph for the MIR.

use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{Lock, Lrc};
use rustc_index::vec::IndexVec;
use rustc_serialize as serialize;
use smallvec::SmallVec;

use crate::mir::{BasicBlock, BasicBlockData};

// Typically 95%+ of basic blocks have 4 or fewer predecessors.
pub type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;

#[derive(Clone, Debug)]
pub(super) struct PredecessorCache {
    cache: Lock<Option<Lrc<Predecessors>>>,
}

impl PredecessorCache {
    #[inline]
    pub(super) fn new() -> Self {
        PredecessorCache { cache: Lock::new(None) }
    }

    /// Invalidates the predecessor cache.
    ///
    /// Invalidating the predecessor cache requires mutating the MIR, which in turn requires a
    /// unique reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all
    /// callers of `invalidate` have a unique reference to the MIR and thus to the predecessor
    /// cache. This means we don't actually need to take a lock when `invalidate` is called.
    #[inline]
    pub(super) fn invalidate(&mut self) {
        *self.cache.get_mut() = None;
    }

    /// Returns a ref-counted smart pointer containing the predecessor graph for this MIR.
    ///
    /// We use ref-counting instead of a mapped `LockGuard` here to ensure that the lock for
    /// `cache` is only held inside this function. As long as no other locks are taken while
    /// computing the predecessor graph, deadlock is impossible.
    #[inline]
    pub(super) fn compute(
        &self,
        basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
    ) -> Lrc<Predecessors> {
        Lrc::clone(self.cache.lock().get_or_insert_with(|| {
            let mut preds = IndexVec::from_elem(SmallVec::new(), basic_blocks);
            for (bb, data) in basic_blocks.iter_enumerated() {
                if let Some(term) = &data.terminator {
                    for &succ in term.successors() {
                        preds[succ].push(bb);
                    }
                }
            }

            Lrc::new(preds)
        }))
    }
}

impl serialize::Encodable for PredecessorCache {
    #[inline]
    fn encode<S: serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        serialize::Encodable::encode(&(), s)
    }
}

impl serialize::Decodable for PredecessorCache {
    #[inline]
    fn decode<D: serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
        serialize::Decodable::decode(d).map(|_v: ()| Self::new())
    }
}

impl<CTX> HashStable<CTX> for PredecessorCache {
    #[inline]
    fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
        // do nothing
    }
}

CloneTypeFoldableAndLiftImpls! {
    PredecessorCache,
}
<commit_msg>Use `OnceCell` for predecessor cache<commit_after>//! Lazily compute the reverse control-flow graph for the MIR.

use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::OnceCell;
use rustc_index::vec::IndexVec;
use rustc_serialize as serialize;
use smallvec::SmallVec;

use crate::mir::{BasicBlock, BasicBlockData};

// Typically 95%+ of basic blocks have 4 or fewer predecessors.
pub type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;

#[derive(Clone, Debug)]
pub(super) struct PredecessorCache {
    cache: OnceCell<Predecessors>,
}

impl PredecessorCache {
    #[inline]
    pub(super) fn new() -> Self {
        PredecessorCache { cache: OnceCell::new() }
    }

    /// Invalidates the predecessor cache.
    ///
    /// Invalidating the predecessor cache requires mutating the MIR, which in turn requires a
    /// unique reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all
    /// callers of `invalidate` have a unique reference to the MIR and thus to the predecessor
    /// cache. This means we never need to do synchronization when `invalidate` is called.
    #[inline]
    pub(super) fn invalidate(&mut self) {
        self.cache = OnceCell::new();
    }

    /// Returns the the predecessor graph for this MIR.
    #[inline]
    pub(super) fn compute(
        &self,
        basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
    ) -> &Predecessors {
        self.cache.get_or_init(|| {
            let mut preds = IndexVec::from_elem(SmallVec::new(), basic_blocks);
            for (bb, data) in basic_blocks.iter_enumerated() {
                if let Some(term) = &data.terminator {
                    for &succ in term.successors() {
                        preds[succ].push(bb);
                    }
                }
            }

            preds
        })
    }
}

impl serialize::Encodable for PredecessorCache {
    #[inline]
    fn encode<S: serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        serialize::Encodable::encode(&(), s)
    }
}

impl serialize::Decodable for PredecessorCache {
    #[inline]
    fn decode<D: serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
        serialize::Decodable::decode(d).map(|_v: ()| Self::new())
    }
}

impl<CTX> HashStable<CTX> for PredecessorCache {
    #[inline]
    fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
        // do nothing
    }
}

CloneTypeFoldableAndLiftImpls! {
    PredecessorCache,
}
<|endoftext|>


<commit_before>//! See docs in build/expr/mod.rs

use crate::build::expr::category::Category;
use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
use crate::build::{BlockAnd, BlockAndExtension, Builder};
use crate::hair::*;
use rustc::mir::interpret::{PanicInfo::BoundsCheck};
use rustc::mir::*;
use rustc::ty::{CanonicalUserTypeAnnotation, Variance};

use rustc_index::vec::Idx;

impl<'a, 'tcx> Builder<'a, 'tcx> {
    /// Compile `expr`, yielding a place that we can move from etc.
    pub fn as_place<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
    where
        M: Mirror<'tcx, Output = Expr<'tcx>>,
    {
        let expr = self.hir.mirror(expr);
        self.expr_as_place(block, expr, Mutability::Mut)
    }

    /// Compile `expr`, yielding a place that we can move from etc.
    /// Mutability note: The caller of this method promises only to read from the resulting
    /// place. The place itself may or may not be mutable:
    /// * If this expr is a place expr like a.b, then we will return that place.
    /// * Otherwise, a temporary is created: in that event, it will be an immutable temporary.
    pub fn as_read_only_place<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
    where
        M: Mirror<'tcx, Output = Expr<'tcx>>,
    {
        let expr = self.hir.mirror(expr);
        self.expr_as_place(block, expr, Mutability::Not)
    }

    fn expr_as_place(
        &mut self,
        mut block: BasicBlock,
        expr: Expr<'tcx>,
        mutability: Mutability,
    ) -> BlockAnd<Place<'tcx>> {
        debug!(
            "expr_as_place(block={:?}, expr={:?}, mutability={:?})",
            block, expr, mutability
        );

        let this = self;
        let expr_span = expr.span;
        let source_info = this.source_info(expr_span);
        match expr.kind {
            ExprKind::Scope {
                region_scope,
                lint_level,
                value,
            } => this.in_scope((region_scope, source_info), lint_level, |this| {
                if mutability == Mutability::Not {
                    this.as_read_only_place(block, value)
                } else {
                    this.as_place(block, value)
                }
            }),
            ExprKind::Field { lhs, name } => {
                let place = unpack!(block = this.as_place(block, lhs));
                let place = place.field(name, expr.ty);
                block.and(place)
            }
            ExprKind::Deref { arg } => {
                let place = unpack!(block = this.as_place(block, arg));
                let place = place.deref();
                block.and(place)
            }
            ExprKind::Index { lhs, index } => {
                let (usize_ty, bool_ty) = (this.hir.usize_ty(), this.hir.bool_ty());

                let slice = unpack!(block = this.as_place(block, lhs));
                // Making this a *fresh* temporary also means we do not have to worry about
                // the index changing later: Nothing will ever change this temporary.
                // The "retagging" transformation (for Stacked Borrows) relies on this.
                let idx = unpack!(block = this.as_temp(
                    block,
                    expr.temp_lifetime,
                    index,
                    Mutability::Not,
                ));

                // bounds check:
                let (len, lt) = (
                    this.temp(usize_ty.clone(), expr_span),
                    this.temp(bool_ty, expr_span),
                );
                this.cfg.push_assign(
                    block,
                    source_info, // len = len(slice)
                    &len,
                    Rvalue::Len(slice.clone()),
                );
                this.cfg.push_assign(
                    block,
                    source_info, // lt = idx < len
                    &lt,
                    Rvalue::BinaryOp(
                        BinOp::Lt,
                        Operand::Copy(Place::from(idx)),
                        Operand::Copy(len.clone()),
                    ),
                );

                let msg = BoundsCheck {
                    len: Operand::Move(len),
                    index: Operand::Copy(Place::from(idx)),
                };
                let success = this.assert(block, Operand::Move(lt), true, msg, expr_span);
                success.and(slice.index(idx))
            }
            ExprKind::SelfRef => block.and(Place::from(Local::new(1))),
            ExprKind::VarRef { id } => {
                let place = if this.is_bound_var_in_guard(id) {
                    let index = this.var_local_id(id, RefWithinGuard);
                    Place::from(index).deref()
                } else {
                    let index = this.var_local_id(id, OutsideGuard);
                    Place::from(index)
                };
                block.and(place)
            }
            ExprKind::StaticRef { id } => block.and(Place {
                base: PlaceBase::Static(Box::new(Static {
                    ty: expr.ty,
                    kind: StaticKind::Static,
                    def_id: id,
                })),
                projection: box [],
            }),

            ExprKind::PlaceTypeAscription { source, user_ty } => {
                let place = unpack!(block = this.as_place(block, source));
                if let Some(user_ty) = user_ty {
                    let annotation_index = this.canonical_user_type_annotations.push(
                        CanonicalUserTypeAnnotation {
                            span: source_info.span,
                            user_ty,
                            inferred_ty: expr.ty,
                        }
                    );
                    this.cfg.push(
                        block,
                        Statement {
                            source_info,
                            kind: StatementKind::AscribeUserType(
                                box(
                                    place.clone(),
                                    UserTypeProjection { base: annotation_index, projs: vec![], }
                                ),
                                Variance::Invariant,
                            ),
                        },
                    );
                }
                block.and(place)
            }
            ExprKind::ValueTypeAscription { source, user_ty } => {
                let source = this.hir.mirror(source);
                let temp = unpack!(
                    block = this.as_temp(block, source.temp_lifetime, source, mutability)
                );
                if let Some(user_ty) = user_ty {
                    let annotation_index = this.canonical_user_type_annotations.push(
                        CanonicalUserTypeAnnotation {
                            span: source_info.span,
                            user_ty,
                            inferred_ty: expr.ty,
                        }
                    );
                    this.cfg.push(
                        block,
                        Statement {
                            source_info,
                            kind: StatementKind::AscribeUserType(
                                box(
                                    Place::from(temp.clone()),
                                    UserTypeProjection { base: annotation_index, projs: vec![], },
                                ),
                                Variance::Invariant,
                            ),
                        },
                    );
                }
                block.and(Place::from(temp))
            }

            ExprKind::Array { .. }
            | ExprKind::Tuple { .. }
            | ExprKind::Adt { .. }
            | ExprKind::Closure { .. }
            | ExprKind::Unary { .. }
            | ExprKind::Binary { .. }
            | ExprKind::LogicalOp { .. }
            | ExprKind::Box { .. }
            | ExprKind::Cast { .. }
            | ExprKind::Use { .. }
            | ExprKind::NeverToAny { .. }
            | ExprKind::Pointer { .. }
            | ExprKind::Repeat { .. }
            | ExprKind::Borrow { .. }
            | ExprKind::Match { .. }
            | ExprKind::Loop { .. }
            | ExprKind::Block { .. }
            | ExprKind::Assign { .. }
            | ExprKind::AssignOp { .. }
            | ExprKind::Break { .. }
            | ExprKind::Continue { .. }
            | ExprKind::Return { .. }
            | ExprKind::Literal { .. }
            | ExprKind::InlineAsm { .. }
            | ExprKind::Yield { .. }
            | ExprKind::Call { .. } => {
                // these are not places, so we need to make a temporary.
                debug_assert!(match Category::of(&expr.kind) {
                    Some(Category::Place) => false,
                    _ => true,
                });
                let temp =
                    unpack!(block = this.as_temp(block, expr.temp_lifetime, expr, mutability));
                block.and(Place::from(temp))
            }
        }
    }
}
<commit_msg>Rollup merge of #64922 - spastorino:make-place-builder, r=nikomatsakis<commit_after>//! See docs in build/expr/mod.rs

use crate::build::expr::category::Category;
use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
use crate::build::{BlockAnd, BlockAndExtension, Builder};
use crate::hair::*;
use rustc::mir::interpret::{PanicInfo::BoundsCheck};
use rustc::mir::*;
use rustc::ty::{CanonicalUserTypeAnnotation, Ty, Variance};

use rustc_index::vec::Idx;

/// `PlaceBuilder` is used to create places during MIR construction. It allows you to "build up" a
/// place by pushing more and more projections onto the end, and then convert the final set into a
/// place using the `into_place` method.
///
/// This is used internally when building a place for an expression like `a.b.c`. The fields `b`
/// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
#[derive(Clone)]
struct PlaceBuilder<'tcx> {
    base: PlaceBase<'tcx>,
    projection: Vec<PlaceElem<'tcx>>,
}

impl PlaceBuilder<'tcx> {
    fn into_place(self) -> Place<'tcx> {
        Place {
            base: self.base,
            projection: self.projection.into_boxed_slice(),
        }
    }

    fn field(self, f: Field, ty: Ty<'tcx>) -> Self {
        self.project(PlaceElem::Field(f, ty))
    }

    fn deref(self) -> Self {
        self.project(PlaceElem::Deref)
    }

    fn index(self, index: Local) -> Self {
        self.project(PlaceElem::Index(index))
    }

    fn project(mut self, elem: PlaceElem<'tcx>) -> Self {
        self.projection.push(elem);
        self
    }
}

impl From<Local> for PlaceBuilder<'tcx> {
    fn from(local: Local) -> Self {
        Self {
            base: local.into(),
            projection: Vec::new(),
        }
    }
}

impl From<PlaceBase<'tcx>> for PlaceBuilder<'tcx> {
    fn from(base: PlaceBase<'tcx>) -> Self {
        Self {
            base,
            projection: Vec::new(),
        }
    }
}

impl<'a, 'tcx> Builder<'a, 'tcx> {
    /// Compile `expr`, yielding a place that we can move from etc.
    pub fn as_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
    where
        M: Mirror<'tcx, Output = Expr<'tcx>>,
    {
        let place_builder = unpack!(block = self.as_place_builder(block, expr));
        block.and(place_builder.into_place())
    }

    /// This is used when constructing a compound `Place`, so that we can avoid creating
    /// intermediate `Place` values until we know the full set of projections.
    fn as_place_builder<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<PlaceBuilder<'tcx>>
    where
        M: Mirror<'tcx, Output = Expr<'tcx>>,
    {
        let expr = self.hir.mirror(expr);
        self.expr_as_place(block, expr, Mutability::Mut)
    }

    /// Compile `expr`, yielding a place that we can move from etc.
    /// Mutability note: The caller of this method promises only to read from the resulting
    /// place. The place itself may or may not be mutable:
    /// * If this expr is a place expr like a.b, then we will return that place.
    /// * Otherwise, a temporary is created: in that event, it will be an immutable temporary.
    pub fn as_read_only_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
    where
        M: Mirror<'tcx, Output = Expr<'tcx>>,
    {
        let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
        block.and(place_builder.into_place())
    }

    /// This is used when constructing a compound `Place`, so that we can avoid creating
    /// intermediate `Place` values until we know the full set of projections.
    /// Mutability note: The caller of this method promises only to read from the resulting
    /// place. The place itself may or may not be mutable:
    /// * If this expr is a place expr like a.b, then we will return that place.
    /// * Otherwise, a temporary is created: in that event, it will be an immutable temporary.
    fn as_read_only_place_builder<M>(
        &mut self,
        block: BasicBlock,
        expr: M,
    ) -> BlockAnd<PlaceBuilder<'tcx>>
    where
        M: Mirror<'tcx, Output = Expr<'tcx>>,
    {
        let expr = self.hir.mirror(expr);
        self.expr_as_place(block, expr, Mutability::Not)
    }

    fn expr_as_place(
        &mut self,
        mut block: BasicBlock,
        expr: Expr<'tcx>,
        mutability: Mutability,
    ) -> BlockAnd<PlaceBuilder<'tcx>> {
        debug!(
            "expr_as_place(block={:?}, expr={:?}, mutability={:?})",
            block, expr, mutability
        );

        let this = self;
        let expr_span = expr.span;
        let source_info = this.source_info(expr_span);
        match expr.kind {
            ExprKind::Scope {
                region_scope,
                lint_level,
                value,
            } => this.in_scope((region_scope, source_info), lint_level, |this| {
                if mutability == Mutability::Not {
                    this.as_read_only_place_builder(block, value)
                } else {
                    this.as_place_builder(block, value)
                }
            }),
            ExprKind::Field { lhs, name } => {
                let place_builder = unpack!(block = this.as_place_builder(block, lhs));
                block.and(place_builder.field(name, expr.ty))
            }
            ExprKind::Deref { arg } => {
                let place_builder = unpack!(block = this.as_place_builder(block, arg));
                block.and(place_builder.deref())
            }
            ExprKind::Index { lhs, index } => {
                let (usize_ty, bool_ty) = (this.hir.usize_ty(), this.hir.bool_ty());

                let place_builder = unpack!(block = this.as_place_builder(block, lhs));
                // Making this a *fresh* temporary also means we do not have to worry about
                // the index changing later: Nothing will ever change this temporary.
                // The "retagging" transformation (for Stacked Borrows) relies on this.
                let idx = unpack!(block = this.as_temp(
                    block,
                    expr.temp_lifetime,
                    index,
                    Mutability::Not,
                ));

                let slice = place_builder.clone().into_place();
                // bounds check:
                let (len, lt) = (
                    this.temp(usize_ty.clone(), expr_span),
                    this.temp(bool_ty, expr_span),
                );
                this.cfg.push_assign(
                    block,
                    source_info, // len = len(slice)
                    &len,
                    Rvalue::Len(slice),
                );
                this.cfg.push_assign(
                    block,
                    source_info, // lt = idx < len
                    &lt,
                    Rvalue::BinaryOp(
                        BinOp::Lt,
                        Operand::Copy(Place::from(idx)),
                        Operand::Copy(len.clone()),
                    ),
                );

                let msg = BoundsCheck {
                    len: Operand::Move(len),
                    index: Operand::Copy(Place::from(idx)),
                };
                let success = this.assert(block, Operand::Move(lt), true, msg, expr_span);
                success.and(place_builder.index(idx))
            }
            ExprKind::SelfRef => block.and(PlaceBuilder::from(Local::new(1))),
            ExprKind::VarRef { id } => {
                let place_builder = if this.is_bound_var_in_guard(id) {
                    let index = this.var_local_id(id, RefWithinGuard);
                    PlaceBuilder::from(index).deref()
                } else {
                    let index = this.var_local_id(id, OutsideGuard);
                    PlaceBuilder::from(index)
                };
                block.and(place_builder)
            }
            ExprKind::StaticRef { id } => block.and(PlaceBuilder::from(
                PlaceBase::Static(Box::new(Static {
                    ty: expr.ty,
                    kind: StaticKind::Static,
                    def_id: id,
                }))
            )),

            ExprKind::PlaceTypeAscription { source, user_ty } => {
                let place_builder = unpack!(block = this.as_place_builder(block, source));
                if let Some(user_ty) = user_ty {
                    let annotation_index = this.canonical_user_type_annotations.push(
                        CanonicalUserTypeAnnotation {
                            span: source_info.span,
                            user_ty,
                            inferred_ty: expr.ty,
                        }
                    );

                    let place = place_builder.clone().into_place();
                    this.cfg.push(
                        block,
                        Statement {
                            source_info,
                            kind: StatementKind::AscribeUserType(
                                box(
                                    place,
                                    UserTypeProjection { base: annotation_index, projs: vec![], }
                                ),
                                Variance::Invariant,
                            ),
                        },
                    );
                }
                block.and(place_builder)
            }
            ExprKind::ValueTypeAscription { source, user_ty } => {
                let source = this.hir.mirror(source);
                let temp = unpack!(
                    block = this.as_temp(block, source.temp_lifetime, source, mutability)
                );
                if let Some(user_ty) = user_ty {
                    let annotation_index = this.canonical_user_type_annotations.push(
                        CanonicalUserTypeAnnotation {
                            span: source_info.span,
                            user_ty,
                            inferred_ty: expr.ty,
                        }
                    );
                    this.cfg.push(
                        block,
                        Statement {
                            source_info,
                            kind: StatementKind::AscribeUserType(
                                box(
                                    Place::from(temp.clone()),
                                    UserTypeProjection { base: annotation_index, projs: vec![], },
                                ),
                                Variance::Invariant,
                            ),
                        },
                    );
                }
                block.and(PlaceBuilder::from(temp))
            }

            ExprKind::Array { .. }
            | ExprKind::Tuple { .. }
            | ExprKind::Adt { .. }
            | ExprKind::Closure { .. }
            | ExprKind::Unary { .. }
            | ExprKind::Binary { .. }
            | ExprKind::LogicalOp { .. }
            | ExprKind::Box { .. }
            | ExprKind::Cast { .. }
            | ExprKind::Use { .. }
            | ExprKind::NeverToAny { .. }
            | ExprKind::Pointer { .. }
            | ExprKind::Repeat { .. }
            | ExprKind::Borrow { .. }
            | ExprKind::Match { .. }
            | ExprKind::Loop { .. }
            | ExprKind::Block { .. }
            | ExprKind::Assign { .. }
            | ExprKind::AssignOp { .. }
            | ExprKind::Break { .. }
            | ExprKind::Continue { .. }
            | ExprKind::Return { .. }
            | ExprKind::Literal { .. }
            | ExprKind::InlineAsm { .. }
            | ExprKind::Yield { .. }
            | ExprKind::Call { .. } => {
                // these are not places, so we need to make a temporary.
                debug_assert!(match Category::of(&expr.kind) {
                    Some(Category::Place) => false,
                    _ => true,
                });
                let temp =
                    unpack!(block = this.as_temp(block, expr.temp_lifetime, expr, mutability));
                block.and(PlaceBuilder::from(temp))
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::ops::Index;

//#![feature(macro_rules)]

macro_rules! obvious_signal_impl {
    (impl $type_: ident) => {

      impl <T> Signal<$type_<T>> for $type_<T> {}

      //impl <T> Index<<$type_<T> as abs::Signal>::pointType> for $type_<T> {
      //  type Output = T;
      //  fn index<'a>(&'a self, _index: <$type_<T> as abs::Signal>::pointType) -> &'a T {
      //    &self.arr[_index.x]
      //  }
      //}
    }
}

macro_rules! signal_point_type {
  ($var:ident from $type_:ty) => (
    let mut $var : <$type_ as abs::Signal>::pointType;
  )
}

enum DIM
{
  ONE,
  TWO,
  THREE
}

trait Point
{
  type IndexingType;
  //type DIM;
}

struct Point1D
{
  x: usize,
}

impl Point for Point1D
{
  type IndexingType = usize;
}
impl Point1D
{
  //fn new(x_:usize) -> Point1D
  //{
  //  Point1D{x:x_}
  //}
  fn new() -> Point1D
  {
    Point1D{x:0}
  }
}

mod abs
{
  pub trait Signal
  {
    type valueType;
    type pointType;
    //type DIM;
  }
}

trait Signal<T: abs::Signal> : Index<T::pointType>
{}

struct Signal1D<T>
{
  arr: Box<[T]>,
}

impl <T: Copy> Signal1D<T>
{
  fn new( init_value: T, size: usize) -> Signal1D<T>
  {
    let mut vec: Vec<T> = Vec::with_capacity(size);
    for _ in 0 .. size
    {
      vec.push(init_value);
    };
    Signal1D {arr: vec.into_boxed_slice()}
  }
}

impl <T> abs::Signal for Signal1D<T>
{
  type valueType = T;
  type pointType = Point1D;
}
obvious_signal_impl! {impl Signal1D }

impl <T> Index<Point1D> for Signal1D<T> {
  type Output = T;
  fn index<'a>(&'a self, _index: <Signal1D<T> as abs::Signal>::pointType) -> &'a T {
    &self.arr[_index.x]
  }
}

fn main()
{
  let a :Signal1D<i32> = Signal1D::new(0, 10);
  //let b :<Signal1D<i32> as abs::Signal>::pointType = <Signal1D<i32> as abs::Signal>::pointType::new(0);
  signal_point_type!(b from Signal1D<i32>);

  println!("{}", a[b]);

}
<commit_msg>Seperate struc into different files<commit_after>#[macro_use]
mod Signal1D;

fn main()
{
  let a :Signal1D<i32> = Signal1D::new(0, 10);
  //let b :<Signal1D<i32> as abs::Signal>::pointType = <Signal1D<i32> as abs::Signal>::pointType::new(0);
  signal_point_type!(b from Signal1D<i32>);

  println!("{}", a[b]);

}
<|endoftext|>