<commit_before>/// Unittest for parsing module

use std::iter::Iterator;
use super::ast::*;
use super::token:: {TokenSpan, Lit};
use super::lex::Lexer;
use std::mem::swap;
use super::token::Token;
use super::Span;
use super::super::storage::SqlType;
use super::parser;
use std::collections::HashMap;

// ============================================================================
// Result::Ok unittest
// ============================================================================

#[test]
fn test_create_table_empty() {
    let mut p = parser::Parser::create("cReAtE table
        foo");

    assert_eq!(p.parse(), Ok(Query::DefStmt(DefStmt::Create(
        CreateStmt::Table(CreateTableStmt {tid: "foo".to_string(),
            cols: Vec::<ColumnInfo>::new()
        })))));
}

#[test]
fn test_create_table_content() {
    let mut p = parser::Parser::create(
        "create table foo (FirstName char(255), LastName char(255))");

    let vec = vec![ColumnInfo  {
            cid: "FirstName".to_string(),
            datatype: SqlType::Char(255),
            primary: false,
        },  ColumnInfo  {
            cid: "LastName".to_string(),
            datatype: SqlType::Char(255),
            primary: false,
        }
    ];

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Create(
        CreateStmt::Table(CreateTableStmt {
            tid: "foo".to_string(), cols: vec }))))
}

#[test]
fn test_create_table_content_primary() {
    let mut p = parser::Parser::create(
        "create table foo (FirstName char(255), LastName char(255) primary key)");

    let vec = vec![ColumnInfo  {
            cid: "FirstName".to_string(),
            datatype: SqlType::Char(255),
            primary: false,
        },  ColumnInfo  {
            cid: "LastName".to_string(),
            datatype: SqlType::Char(255),
            primary: true,
        }
    ];

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Create(
        CreateStmt::Table(CreateTableStmt {
            tid: "foo".to_string(), cols: vec }))))
}

#[test]
fn test_create_database() {
    let mut p = parser::Parser::create("create database Database");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Create(
        CreateStmt::Database("Database".to_string()))));
}

#[test]
fn test_alter_table_add_column() {
    let mut p = parser::Parser::create("alter table foo add bar int");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Add(ColumnInfo {
            cid: "bar".to_string(),
            datatype: SqlType::Int,
            primary: false,
        })
    }))));
}

#[test]
fn test_alter_table_add_column_primary() {
    let mut p = parser::Parser::create("alter table foo add bar int primary key");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Add(ColumnInfo {
            cid: "bar".to_string(),
            datatype: SqlType::Int,
            primary: true,
        })
    }))));
}

#[test]
fn test_alter_table_drop_column() {
    let mut p = parser::Parser::create("alter table foo drop column bar");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Drop("bar".to_string())
        })
    )));
}

#[test]
fn test_alter_table_modify() {
    let mut p = parser::Parser::create("alter table foo modify
        column bar bool");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Modify(ColumnInfo {
            cid: "bar".to_string(),
            datatype: SqlType::Bool,
            primary: false,
        })
    }))));
}

#[test]
fn test_drop_table() {
    let mut p = parser::Parser::create("drop table foo");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Drop(
        DropStmt::Table("foo".to_string()))));
}

#[test]
fn test_drop_database() {
    let mut p = parser::Parser::create("drop database foo");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Drop(
        DropStmt::Database("foo".to_string()))));
}

#[test]
fn test_use_database() {
    let mut p = parser::Parser::create("use database foo");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Use(UseStmt::Database("foo".to_string()))));
}

#[test]
fn test_describe_column() {
    let mut p = parser::Parser::create("describe foo");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Describe("foo".to_string())));
}

#[test]
fn test_insert_1() {
    let mut p = parser::Parser::create("insert into foo values
        ('peter', 'pan', 3) ");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Insert(InsertStmt {
            tid: "foo".to_string(),
            col: Vec::<String>::new(),
            val: vec![Lit::Str("peter".to_string()),
                Lit::Str("pan".to_string()),
                Lit::Int(3)],
    })));
}

#[test]
fn test_insert_2() {
    let mut p = parser::Parser::create("insert into foo () values
        ('peter', 'pan', 4)");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Insert(InsertStmt {
            tid: "foo".to_string(),
            col: Vec::<String>::new(),
            val: vec![Lit::Str("peter".to_string()),
                Lit::Str("pan".to_string()),
                Lit::Int(4)],
    })));
}

#[test]
fn test_insert_3() {
    let mut p = parser::Parser::create("insert into foo (eins, zwei, drei)
        values ('peter', 'pan', 5)");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Insert(InsertStmt {
            tid: "foo".to_string(),
            col: vec!["eins".to_string(), "zwei".to_string(), "drei".to_string()],
            val: vec![Lit::Str("peter".to_string()),
                Lit::Str("pan".to_string()),
                Lit::Int(5)],
    })));
}

#[test]
fn test_delete_row() {
    let mut p = parser::Parser::create("delete from foo where name = 'peter'");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Delete(DeleteStmt {
            tid: "foo".to_string(),
            alias: HashMap::new(),
            cond: Some(Conditions::Leaf(Condition {
                aliascol: None,
                col: "name".to_string(),
                op: CompType::Equ,
                aliasrhs: None,
                rhs: CondType::Literal(Lit::Str("peter".to_string())),
            })),
    })));
}
#[test]
fn test_delete_full_with_alias() {
    let mut p = parser::Parser::create("delete from foo bar");
    let mut aliashm = HashMap::new();
    aliashm.insert("bar".to_string(), "foo".to_string());

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Delete(DeleteStmt {
            tid: "foo".to_string(),
            alias: aliashm,
            cond: None,
    })));
}
#[test]
fn test_mult_where_blocks() {
    let mut p = parser::Parser::create("delete from foo where lname = 'peng' or
        fname = 'peter' and lname = 'pan'");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Delete(DeleteStmt {
            tid: "foo".to_string(),
            alias: HashMap::new(),
            cond: Some(
                    Conditions::Or(Box::new(
                        Conditions::Leaf(Condition {
                            aliascol: None,
                            col: "lname".to_string(),
                            op: CompType::Equ,
                            aliasrhs: None,
                            rhs: CondType::Literal(Lit::Str("peng".to_string())),
                            }
                        )
                    ),
                        Box::new(
                            Conditions::And(Box::new(
                                Conditions::Leaf(Condition {
                                    aliascol: None,
                                    col: "fname".to_string(),
                                    op: CompType::Equ,
                                    aliasrhs: None,
                                    rhs: CondType::Literal(Lit::Str("peter".to_string())),
                                    }
                                )
                            ),
                                Box::new(Conditions::Leaf(Condition{
                                        aliascol: None,
                                        col: "lname".to_string(),
                                        op: CompType::Equ,
                                        aliasrhs: None,
                                        rhs: CondType::Literal(Lit::Str("pan".to_string())),
                                        }
                                    )
                                )
                            )
                        )
                    )
                )
            }
        ))
    );
}

// ============================================================================
// Result::Err unittest
// ============================================================================

#[test]
fn test_create_table_error1() {
    let mut p = parser::Parser::create("cReAtE table");
    let sol = parser::ParseError::UnexpectedEoq;
    assert_eq!(p.parse(), Err(sol));
}

#[test]
fn test_create_keyword1() {
    let mut p = parser::Parser::create("   table create");
    let sol = parser::ParseError::WrongKeyword(Span {
        lo : 5,
        hi : 10,
    });

    assert_eq!(p.parse(), Err(sol));
}

//Missing parentheses in front
#[test]
fn test_create_missing_p_front() {
    let mut p = parser::Parser::create("create table Studenten )");
    let sol = parser::ParseError::WrongToken(Span {
        lo : 24,
        hi : 24,
    });

    assert_eq!(p.parse(), Err(sol));
}<commit_msg>Added trailing newline<commit_after>/// Unittest for parsing module

use std::iter::Iterator;
use super::ast::*;
use super::token:: {TokenSpan, Lit};
use super::lex::Lexer;
use std::mem::swap;
use super::token::Token;
use super::Span;
use super::super::storage::SqlType;
use super::parser;
use std::collections::HashMap;

// ============================================================================
// Result::Ok unittest
// ============================================================================

#[test]
fn test_create_table_empty() {
    let mut p = parser::Parser::create("cReAtE table
        foo");

    assert_eq!(p.parse(), Ok(Query::DefStmt(DefStmt::Create(
        CreateStmt::Table(CreateTableStmt {tid: "foo".to_string(),
            cols: Vec::<ColumnInfo>::new()
        })))));
}

#[test]
fn test_create_table_content() {
    let mut p = parser::Parser::create(
        "create table foo (FirstName char(255), LastName char(255))");

    let vec = vec![ColumnInfo  {
            cid: "FirstName".to_string(),
            datatype: SqlType::Char(255),
            primary: false,
        },  ColumnInfo  {
            cid: "LastName".to_string(),
            datatype: SqlType::Char(255),
            primary: false,
        }
    ];

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Create(
        CreateStmt::Table(CreateTableStmt {
            tid: "foo".to_string(), cols: vec }))))
}

#[test]
fn test_create_table_content_primary() {
    let mut p = parser::Parser::create(
        "create table foo (FirstName char(255), LastName char(255) primary key)");

    let vec = vec![ColumnInfo  {
            cid: "FirstName".to_string(),
            datatype: SqlType::Char(255),
            primary: false,
        },  ColumnInfo  {
            cid: "LastName".to_string(),
            datatype: SqlType::Char(255),
            primary: true,
        }
    ];

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Create(
        CreateStmt::Table(CreateTableStmt {
            tid: "foo".to_string(), cols: vec }))))
}

#[test]
fn test_create_database() {
    let mut p = parser::Parser::create("create database Database");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Create(
        CreateStmt::Database("Database".to_string()))));
}

#[test]
fn test_alter_table_add_column() {
    let mut p = parser::Parser::create("alter table foo add bar int");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Add(ColumnInfo {
            cid: "bar".to_string(),
            datatype: SqlType::Int,
            primary: false,
        })
    }))));
}

#[test]
fn test_alter_table_add_column_primary() {
    let mut p = parser::Parser::create("alter table foo add bar int primary key");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Add(ColumnInfo {
            cid: "bar".to_string(),
            datatype: SqlType::Int,
            primary: true,
        })
    }))));
}

#[test]
fn test_alter_table_drop_column() {
    let mut p = parser::Parser::create("alter table foo drop column bar");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Drop("bar".to_string())
        })
    )));
}

#[test]
fn test_alter_table_modify() {
    let mut p = parser::Parser::create("alter table foo modify
        column bar bool");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Modify(ColumnInfo {
            cid: "bar".to_string(),
            datatype: SqlType::Bool,
            primary: false,
        })
    }))));
}

#[test]
fn test_drop_table() {
    let mut p = parser::Parser::create("drop table foo");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Drop(
        DropStmt::Table("foo".to_string()))));
}

#[test]
fn test_drop_database() {
    let mut p = parser::Parser::create("drop database foo");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Drop(
        DropStmt::Database("foo".to_string()))));
}

#[test]
fn test_use_database() {
    let mut p = parser::Parser::create("use database foo");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Use(UseStmt::Database("foo".to_string()))));
}

#[test]
fn test_describe_column() {
    let mut p = parser::Parser::create("describe foo");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Describe("foo".to_string())));
}

#[test]
fn test_insert_1() {
    let mut p = parser::Parser::create("insert into foo values
        ('peter', 'pan', 3) ");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Insert(InsertStmt {
            tid: "foo".to_string(),
            col: Vec::<String>::new(),
            val: vec![Lit::Str("peter".to_string()),
                Lit::Str("pan".to_string()),
                Lit::Int(3)],
    })));
}

#[test]
fn test_insert_2() {
    let mut p = parser::Parser::create("insert into foo () values
        ('peter', 'pan', 4)");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Insert(InsertStmt {
            tid: "foo".to_string(),
            col: Vec::<String>::new(),
            val: vec![Lit::Str("peter".to_string()),
                Lit::Str("pan".to_string()),
                Lit::Int(4)],
    })));
}

#[test]
fn test_insert_3() {
    let mut p = parser::Parser::create("insert into foo (eins, zwei, drei)
        values ('peter', 'pan', 5)");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Insert(InsertStmt {
            tid: "foo".to_string(),
            col: vec!["eins".to_string(), "zwei".to_string(), "drei".to_string()],
            val: vec![Lit::Str("peter".to_string()),
                Lit::Str("pan".to_string()),
                Lit::Int(5)],
    })));
}

#[test]
fn test_delete_row() {
    let mut p = parser::Parser::create("delete from foo where name = 'peter'");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Delete(DeleteStmt {
            tid: "foo".to_string(),
            alias: HashMap::new(),
            cond: Some(Conditions::Leaf(Condition {
                aliascol: None,
                col: "name".to_string(),
                op: CompType::Equ,
                aliasrhs: None,
                rhs: CondType::Literal(Lit::Str("peter".to_string())),
            })),
    })));
}
#[test]
fn test_delete_full_with_alias() {
    let mut p = parser::Parser::create("delete from foo bar");
    let mut aliashm = HashMap::new();
    aliashm.insert("bar".to_string(), "foo".to_string());

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Delete(DeleteStmt {
            tid: "foo".to_string(),
            alias: aliashm,
            cond: None,
    })));
}
#[test]
fn test_mult_where_blocks() {
    let mut p = parser::Parser::create("delete from foo where lname = 'peng' or
        fname = 'peter' and lname = 'pan'");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Delete(DeleteStmt {
            tid: "foo".to_string(),
            alias: HashMap::new(),
            cond: Some(
                    Conditions::Or(Box::new(
                        Conditions::Leaf(Condition {
                            aliascol: None,
                            col: "lname".to_string(),
                            op: CompType::Equ,
                            aliasrhs: None,
                            rhs: CondType::Literal(Lit::Str("peng".to_string())),
                            }
                        )
                    ),
                        Box::new(
                            Conditions::And(Box::new(
                                Conditions::Leaf(Condition {
                                    aliascol: None,
                                    col: "fname".to_string(),
                                    op: CompType::Equ,
                                    aliasrhs: None,
                                    rhs: CondType::Literal(Lit::Str("peter".to_string())),
                                    }
                                )
                            ),
                                Box::new(Conditions::Leaf(Condition{
                                        aliascol: None,
                                        col: "lname".to_string(),
                                        op: CompType::Equ,
                                        aliasrhs: None,
                                        rhs: CondType::Literal(Lit::Str("pan".to_string())),
                                        }
                                    )
                                )
                            )
                        )
                    )
                )
            }
        ))
    );
}

// ============================================================================
// Result::Err unittest
// ============================================================================

#[test]
fn test_create_table_error1() {
    let mut p = parser::Parser::create("cReAtE table");
    let sol = parser::ParseError::UnexpectedEoq;
    assert_eq!(p.parse(), Err(sol));
}

#[test]
fn test_create_keyword1() {
    let mut p = parser::Parser::create("   table create");
    let sol = parser::ParseError::WrongKeyword(Span {
        lo : 5,
        hi : 10,
    });

    assert_eq!(p.parse(), Err(sol));
}

//Missing parentheses in front
#[test]
fn test_create_missing_p_front() {
    let mut p = parser::Parser::create("create table Studenten )");
    let sol = parser::ParseError::WrongToken(Span {
        lo : 24,
        hi : 24,
    });

    assert_eq!(p.parse(), Err(sol));
}
<|endoftext|>


<commit_before>/// An executor, which is run when idling on network I/O.
use crate::net::network_delay;
use async_task::{Runnable, Task};
use concurrent_queue::ConcurrentQueue;
use futures_lite::pin;
use smoltcp::time::{Duration, Instant};
use std::sync::atomic::Ordering;
use std::{
	future::Future,
	sync::{atomic::AtomicBool, Arc},
	task::{Context, Poll, Wake},
};

/// A thread handle type
type Tid = u32;

extern "C" {
	fn sys_getpid() -> Tid;
	fn sys_yield();
	fn sys_wakeup_task(tid: Tid);
	fn sys_set_network_polling_mode(value: bool);
	fn sys_block_current_task_with_timeout(timeout: u64);
	fn sys_block_current_task();
}

lazy_static! {
	static ref QUEUE: ConcurrentQueue<Runnable> = ConcurrentQueue::unbounded();
}

fn run_executor() {
	while let Ok(runnable) = QUEUE.pop() {
		runnable.run();
	}
}

/// Spawns a future on the executor.
pub fn spawn<F, T>(future: F) -> Task<T>
where
	F: Future<Output = T> + Send + 'static,
	T: Send + 'static,
{
	let schedule = |runnable| QUEUE.push(runnable).unwrap();
	let (runnable, task) = async_task::spawn(future, schedule);
	runnable.schedule();
	task
}

struct ThreadNotify {
	/// The (single) executor thread.
	thread: Tid,
	/// A flag to ensure a wakeup is not "forgotten" before the next `block_current_task`
	unparked: AtomicBool,
}

impl ThreadNotify {
	pub fn new() -> Self {
		Self {
			thread: unsafe { sys_getpid() },
			unparked: AtomicBool::new(false),
		}
	}
}

impl Drop for ThreadNotify {
	fn drop(&mut self) {
		println!("Dropping ThreadNotify!");
	}
}

impl Wake for ThreadNotify {
	fn wake(self: Arc<Self>) {
		self.wake_by_ref()
	}

	fn wake_by_ref(self: &Arc<Self>) {
		// Make sure the wakeup is remembered until the next `park()`.
		let unparked = self.unparked.swap(true, Ordering::Relaxed);
		if !unparked {
			unsafe {
				sys_wakeup_task(self.thread);
			}
		}
	}
}

thread_local! {
	static CURRENT_THREAD_NOTIFY: Arc<ThreadNotify> = Arc::new(ThreadNotify::new());
}

pub fn poll_on<F, T>(future: F, timeout: Option<Duration>) -> Result<T, ()>
where
	F: Future<Output = T>,
{
	info!("II");
	CURRENT_THREAD_NOTIFY.with(|thread_notify| {
		unsafe {
			sys_set_network_polling_mode(true);
		}

		let start = Instant::now();
		let waker = thread_notify.clone().into();
		let mut cx = Context::from_waker(&waker);
		pin!(future);

		loop {
			if let Poll::Ready(t) = future.as_mut().poll(&mut cx) {
				unsafe {
					sys_set_network_polling_mode(false);
				}
				info!("JJ");
				return Ok(t);
			}

			if let Some(duration) = timeout {
				if Instant::now() >= start + duration {
					unsafe {
						sys_set_network_polling_mode(false);
					}
					return Err(());
				}
			}

			run_executor()
		}
	})
}

/// Blocks the current thread on `f`, running the executor when idling.
pub fn block_on<F, T>(future: F, timeout: Option<Duration>) -> Result<T, ()>
where
	F: Future<Output = T>,
{
	CURRENT_THREAD_NOTIFY.with(|thread_notify| {
		let start = Instant::now();
		let waker = thread_notify.clone().into();
		let mut cx = Context::from_waker(&waker);
		pin!(future);

		loop {
			if let Poll::Ready(t) = future.as_mut().poll(&mut cx) {
				return Ok(t);
			}

			if let Some(duration) = timeout {
				if Instant::now() >= start + duration {
					return Err(());
				}
			}

			let delay = network_delay(Instant::now()).map(|d| d.total_millis());

			if delay.is_none() || delay.unwrap() > 100 {
				let unparked = thread_notify.unparked.swap(false, Ordering::Acquire);
				if !unparked {
					unsafe {
						match delay {
							Some(d) => sys_block_current_task_with_timeout(d),
							None => sys_block_current_task(),
						};
						sys_yield();
					}
					thread_notify.unparked.store(false, Ordering::Release);
					run_executor()
				}
			} else {
				run_executor()
			}
		}
	})
}
<commit_msg>remove obsolete debug messages<commit_after>/// An executor, which is run when idling on network I/O.
use crate::net::network_delay;
use async_task::{Runnable, Task};
use concurrent_queue::ConcurrentQueue;
use futures_lite::pin;
use smoltcp::time::{Duration, Instant};
use std::sync::atomic::Ordering;
use std::{
	future::Future,
	sync::{atomic::AtomicBool, Arc},
	task::{Context, Poll, Wake},
};

/// A thread handle type
type Tid = u32;

extern "C" {
	fn sys_getpid() -> Tid;
	fn sys_yield();
	fn sys_wakeup_task(tid: Tid);
	fn sys_set_network_polling_mode(value: bool);
	fn sys_block_current_task_with_timeout(timeout: u64);
	fn sys_block_current_task();
}

lazy_static! {
	static ref QUEUE: ConcurrentQueue<Runnable> = ConcurrentQueue::unbounded();
}

fn run_executor() {
	while let Ok(runnable) = QUEUE.pop() {
		runnable.run();
	}
}

/// Spawns a future on the executor.
pub fn spawn<F, T>(future: F) -> Task<T>
where
	F: Future<Output = T> + Send + 'static,
	T: Send + 'static,
{
	let schedule = |runnable| QUEUE.push(runnable).unwrap();
	let (runnable, task) = async_task::spawn(future, schedule);
	runnable.schedule();
	task
}

struct ThreadNotify {
	/// The (single) executor thread.
	thread: Tid,
	/// A flag to ensure a wakeup is not "forgotten" before the next `block_current_task`
	unparked: AtomicBool,
}

impl ThreadNotify {
	pub fn new() -> Self {
		Self {
			thread: unsafe { sys_getpid() },
			unparked: AtomicBool::new(false),
		}
	}
}

impl Drop for ThreadNotify {
	fn drop(&mut self) {
		println!("Dropping ThreadNotify!");
	}
}

impl Wake for ThreadNotify {
	fn wake(self: Arc<Self>) {
		self.wake_by_ref()
	}

	fn wake_by_ref(self: &Arc<Self>) {
		// Make sure the wakeup is remembered until the next `park()`.
		let unparked = self.unparked.swap(true, Ordering::Relaxed);
		if !unparked {
			unsafe {
				sys_wakeup_task(self.thread);
			}
		}
	}
}

thread_local! {
	static CURRENT_THREAD_NOTIFY: Arc<ThreadNotify> = Arc::new(ThreadNotify::new());
}

pub fn poll_on<F, T>(future: F, timeout: Option<Duration>) -> Result<T, ()>
where
	F: Future<Output = T>,
{
	CURRENT_THREAD_NOTIFY.with(|thread_notify| {
		unsafe {
			sys_set_network_polling_mode(true);
		}

		let start = Instant::now();
		let waker = thread_notify.clone().into();
		let mut cx = Context::from_waker(&waker);
		pin!(future);

		loop {
			if let Poll::Ready(t) = future.as_mut().poll(&mut cx) {
				unsafe {
					sys_set_network_polling_mode(false);
				}
				return Ok(t);
			}

			if let Some(duration) = timeout {
				if Instant::now() >= start + duration {
					unsafe {
						sys_set_network_polling_mode(false);
					}
					return Err(());
				}
			}

			run_executor()
		}
	})
}

/// Blocks the current thread on `f`, running the executor when idling.
pub fn block_on<F, T>(future: F, timeout: Option<Duration>) -> Result<T, ()>
where
	F: Future<Output = T>,
{
	CURRENT_THREAD_NOTIFY.with(|thread_notify| {
		let start = Instant::now();
		let waker = thread_notify.clone().into();
		let mut cx = Context::from_waker(&waker);
		pin!(future);

		loop {
			if let Poll::Ready(t) = future.as_mut().poll(&mut cx) {
				return Ok(t);
			}

			if let Some(duration) = timeout {
				if Instant::now() >= start + duration {
					return Err(());
				}
			}

			let delay = network_delay(Instant::now()).map(|d| d.total_millis());

			if delay.is_none() || delay.unwrap() > 100 {
				let unparked = thread_notify.unparked.swap(false, Ordering::Acquire);
				if !unparked {
					unsafe {
						match delay {
							Some(d) => sys_block_current_task_with_timeout(d),
							None => sys_block_current_task(),
						};
						sys_yield();
					}
					thread_notify.unparked.store(false, Ordering::Release);
					run_executor()
				}
			} else {
				run_executor()
			}
		}
	})
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::replaced::IntrinsicSizes;
use euclid::{Size2D, Vector2D};
use style::computed_values::background_clip::single_value::T as Clip;
use style::computed_values::background_origin::single_value::T as Origin;
use style::properties::ComputedValues;
use style::values::computed::background::BackgroundSize as Size;
use style::values::computed::{Length, LengthPercentage};
use style::values::specified::background::BackgroundRepeat as RepeatXY;
use style::values::specified::background::BackgroundRepeatKeyword as Repeat;
use webrender_api::{self as wr, units};

pub(super) struct BackgroundLayer {
    pub common: wr::CommonItemProperties,
    pub bounds: units::LayoutRect,
    pub tile_size: units::LayoutSize,
    pub tile_spacing: units::LayoutSize,
    pub repeat: bool,
}

struct Layout1DResult {
    repeat: bool,
    bounds_origin: f32,
    bounds_size: f32,
    tile_spacing: f32,
}

fn get_cyclic<T>(values: &[T], layer_index: usize) -> &T {
    &values[layer_index % values.len()]
}

pub(super) enum Source<'a> {
    Fragment,
    Canvas {
        style: &'a ComputedValues,

        // Theoretically the painting area is the infinite 2D plane,
        // but WebRender doesn’t really do infinite so this is the part of it that can be visible.
        painting_area: units::LayoutRect,
    },
}

pub(super) fn painting_area<'a>(
    fragment_builder: &'a super::BuilderForBoxFragment,
    source: &'a Source,
    builder: &mut super::DisplayListBuilder,
    layer_index: usize,
) -> (&'a units::LayoutRect, wr::CommonItemProperties) {
    let (painting_area, clip) = match source {
        Source::Canvas { painting_area, .. } => (painting_area, None),
        Source::Fragment => {
            let fb = fragment_builder;
            let b = fb.fragment.style.get_background();
            match get_cyclic(&b.background_clip.0, layer_index) {
                Clip::ContentBox => (fb.content_rect(), fb.content_edge_clip(builder)),
                Clip::PaddingBox => (fb.padding_rect(), fb.padding_edge_clip(builder)),
                Clip::BorderBox => (&fb.border_rect, fb.border_edge_clip(builder)),
            }
        },
    };
    // The 'backgound-clip' property maps directly to `clip_rect` in `CommonItemProperties`:
    let mut common = builder.common_properties(*painting_area);
    if let Some(clip_id) = clip {
        common.clip_id = clip_id
    }
    (painting_area, common)
}

pub(super) fn layout_layer(
    fragment_builder: &mut super::BuilderForBoxFragment,
    source: &Source,
    builder: &mut super::DisplayListBuilder,
    layer_index: usize,
    intrinsic: IntrinsicSizes,
) -> Option<BackgroundLayer> {
    let style = match *source {
        Source::Canvas { style, .. } => style,
        Source::Fragment => &fragment_builder.fragment.style,
    };
    let b = style.get_background();
    let (painting_area, common) = painting_area(fragment_builder, source, builder, layer_index);

    let positioning_area = match get_cyclic(&b.background_origin.0, layer_index) {
        Origin::ContentBox => fragment_builder.content_rect(),
        Origin::PaddingBox => fragment_builder.padding_rect(),
        Origin::BorderBox => &fragment_builder.border_rect,
    };

    // https://drafts.csswg.org/css-backgrounds/#background-size
    enum ContainOrCover {
        Contain,
        Cover,
    }
    let size_contain_or_cover = |background_size| {
        let mut tile_size = positioning_area.size;
        if let Some(intrinsic_ratio) = intrinsic.ratio {
            let positioning_ratio = positioning_area.size.width / positioning_area.size.height;
            // Whether the tile width (as opposed to height)
            // is scaled to that of the positioning area
            let fit_width = match background_size {
                ContainOrCover::Contain => positioning_ratio <= intrinsic_ratio,
                ContainOrCover::Cover => positioning_ratio > intrinsic_ratio,
            };
            // The other dimension needs to be adjusted
            if fit_width {
                tile_size.height = tile_size.width / intrinsic_ratio
            } else {
                tile_size.width = tile_size.height * intrinsic_ratio
            }
        }
        tile_size
    };
    let mut tile_size = match get_cyclic(&b.background_size.0, layer_index) {
        Size::Contain => size_contain_or_cover(ContainOrCover::Contain),
        Size::Cover => size_contain_or_cover(ContainOrCover::Cover),
        Size::ExplicitSize { width, height } => {
            let mut width = width.non_auto().map(|lp| {
                lp.0.percentage_relative_to(Length::new(positioning_area.size.width))
            });
            let mut height = height.non_auto().map(|lp| {
                lp.0.percentage_relative_to(Length::new(positioning_area.size.height))
            });

            if width.is_none() && height.is_none() {
                // Both computed values are 'auto':
                // use intrinsic sizes, treating missing width or height as 'auto'
                width = intrinsic.width;
                height = intrinsic.height;
            }

            match (width, height) {
                (Some(w), Some(h)) => units::LayoutSize::new(w.px(), h.px()),
                (Some(w), None) => {
                    let h = if let Some(intrinsic_ratio) = intrinsic.ratio {
                        w / intrinsic_ratio
                    } else if let Some(intrinsic_height) = intrinsic.height {
                        intrinsic_height
                    } else {
                        // Treated as 100%
                        Length::new(positioning_area.size.height)
                    };
                    units::LayoutSize::new(w.px(), h.px())
                },
                (None, Some(h)) => {
                    let w = if let Some(intrinsic_ratio) = intrinsic.ratio {
                        h * intrinsic_ratio
                    } else if let Some(intrinsic_width) = intrinsic.width {
                        intrinsic_width
                    } else {
                        // Treated as 100%
                        Length::new(positioning_area.size.width)
                    };
                    units::LayoutSize::new(w.px(), h.px())
                },
                // Both comptued values were 'auto', and neither intrinsic size is present
                (None, None) => size_contain_or_cover(ContainOrCover::Contain),
            }
        },
    };

    if tile_size.width == 0.0 || tile_size.height == 0.0 {
        return None;
    }

    let RepeatXY(repeat_x, repeat_y) = *get_cyclic(&b.background_repeat.0, layer_index);
    let result_x = layout_1d(
        &mut tile_size.width,
        repeat_x,
        get_cyclic(&b.background_position_x.0, layer_index),
        painting_area.origin.x - positioning_area.origin.x,
        painting_area.size.width,
        positioning_area.size.width,
    );
    let result_y = layout_1d(
        &mut tile_size.height,
        repeat_y,
        get_cyclic(&b.background_position_y.0, layer_index),
        painting_area.origin.y - positioning_area.origin.y,
        painting_area.size.height,
        positioning_area.size.height,
    );
    let bounds = units::LayoutRect::new(
        positioning_area.origin + Vector2D::new(result_x.bounds_origin, result_y.bounds_origin),
        Size2D::new(result_x.bounds_size, result_y.bounds_size),
    );
    let tile_spacing = units::LayoutSize::new(result_x.tile_spacing, result_y.tile_spacing);

    Some(BackgroundLayer {
        common,
        bounds,
        tile_size,
        tile_spacing,
        repeat: result_x.repeat || result_y.repeat,
    })
}

/// Abstract over the horizontal or vertical dimension
/// Coordinates (0, 0) for the purpose of this function are the positioning area’s origin.
fn layout_1d(
    tile_size: &mut f32,
    mut repeat: Repeat,
    position: &LengthPercentage,
    painting_area_origin: f32,
    painting_area_size: f32,
    positioning_area_size: f32,
) -> Layout1DResult {
    // https://drafts.csswg.org/css-backgrounds/#background-repeat
    if let Repeat::Round = repeat {
        *tile_size = positioning_area_size / (positioning_area_size / *tile_size).round();
    }
    // https://drafts.csswg.org/css-backgrounds/#background-position
    let mut position = position
        .percentage_relative_to(Length::new(positioning_area_size - *tile_size))
        .px();
    let mut tile_spacing = 0.0;
    // https://drafts.csswg.org/css-backgrounds/#background-repeat
    if let Repeat::Space = repeat {
        // The most entire tiles we can fit
        let tile_count = (positioning_area_size / *tile_size).floor();
        if tile_count >= 2.0 {
            position = 0.0;
            // Make the outsides of the first and last of that many tiles
            // touch the edges of the positioning area:
            let total_space = positioning_area_size - *tile_size * tile_count;
            let spaces_count = tile_count - 1.0;
            tile_spacing = total_space / spaces_count;
        } else {
            repeat = Repeat::NoRepeat
        }
    }
    match repeat {
        Repeat::Repeat | Repeat::Round | Repeat::Space => {
            // WebRender’s `RepeatingImageDisplayItem` contains a `bounds` rectangle and:
            //
            // * The tiling is clipped to the intersection of `clip_rect` and `bounds`
            // * The origin (top-left corner) of `bounds` is the position
            //   of the “first” (top-left-most) tile.
            //
            // In the general case that first tile is not the one that is positioned by
            // `background-position`.
            // We want it to be the top-left-most tile that intersects with `clip_rect`.
            // We find it by offsetting by a whole number of strides,
            // then compute `bounds` such that:
            //
            // * Its bottom-right is the bottom-right of `clip_rect`
            // * Its top-left is the top-left of first tile.
            let tile_stride = *tile_size + tile_spacing;
            let offset = position - painting_area_origin;
            let bounds_origin = position - tile_stride * (offset / tile_stride).ceil();
            let bounds_size = painting_area_size - bounds_origin - painting_area_origin;
            Layout1DResult {
                repeat: true,
                bounds_origin,
                bounds_size,
                tile_spacing,
            }
        },
        Repeat::NoRepeat => {
            // `RepeatingImageDisplayItem` always repeats in both dimension.
            // When we want only one of the dimensions to repeat,
            // we use the `bounds` rectangle to clip the tiling to one tile
            // in that dimension.
            Layout1DResult {
                repeat: false,
                bounds_origin: position,
                bounds_size: *tile_size,
                tile_spacing: 0.0,
            }
        },
    }
}
<commit_msg>Fix incorrect sign background-image rectangle computation<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::replaced::IntrinsicSizes;
use euclid::{Size2D, Vector2D};
use style::computed_values::background_clip::single_value::T as Clip;
use style::computed_values::background_origin::single_value::T as Origin;
use style::properties::ComputedValues;
use style::values::computed::background::BackgroundSize as Size;
use style::values::computed::{Length, LengthPercentage};
use style::values::specified::background::BackgroundRepeat as RepeatXY;
use style::values::specified::background::BackgroundRepeatKeyword as Repeat;
use webrender_api::{self as wr, units};

pub(super) struct BackgroundLayer {
    pub common: wr::CommonItemProperties,
    pub bounds: units::LayoutRect,
    pub tile_size: units::LayoutSize,
    pub tile_spacing: units::LayoutSize,
    pub repeat: bool,
}

#[derive(Debug)]
struct Layout1DResult {
    repeat: bool,
    bounds_origin: f32,
    bounds_size: f32,
    tile_spacing: f32,
}

fn get_cyclic<T>(values: &[T], layer_index: usize) -> &T {
    &values[layer_index % values.len()]
}

pub(super) enum Source<'a> {
    Fragment,
    Canvas {
        style: &'a ComputedValues,

        // Theoretically the painting area is the infinite 2D plane,
        // but WebRender doesn’t really do infinite so this is the part of it that can be visible.
        painting_area: units::LayoutRect,
    },
}

pub(super) fn painting_area<'a>(
    fragment_builder: &'a super::BuilderForBoxFragment,
    source: &'a Source,
    builder: &mut super::DisplayListBuilder,
    layer_index: usize,
) -> (&'a units::LayoutRect, wr::CommonItemProperties) {
    let (painting_area, clip) = match source {
        Source::Canvas { painting_area, .. } => (painting_area, None),
        Source::Fragment => {
            let fb = fragment_builder;
            let b = fb.fragment.style.get_background();
            match get_cyclic(&b.background_clip.0, layer_index) {
                Clip::ContentBox => (fb.content_rect(), fb.content_edge_clip(builder)),
                Clip::PaddingBox => (fb.padding_rect(), fb.padding_edge_clip(builder)),
                Clip::BorderBox => (&fb.border_rect, fb.border_edge_clip(builder)),
            }
        },
    };
    // The 'backgound-clip' property maps directly to `clip_rect` in `CommonItemProperties`:
    let mut common = builder.common_properties(*painting_area);
    if let Some(clip_id) = clip {
        common.clip_id = clip_id
    }
    (painting_area, common)
}

pub(super) fn layout_layer(
    fragment_builder: &mut super::BuilderForBoxFragment,
    source: &Source,
    builder: &mut super::DisplayListBuilder,
    layer_index: usize,
    intrinsic: IntrinsicSizes,
) -> Option<BackgroundLayer> {
    let style = match *source {
        Source::Canvas { style, .. } => style,
        Source::Fragment => &fragment_builder.fragment.style,
    };
    let b = style.get_background();
    let (painting_area, common) = painting_area(fragment_builder, source, builder, layer_index);

    let positioning_area = match get_cyclic(&b.background_origin.0, layer_index) {
        Origin::ContentBox => fragment_builder.content_rect(),
        Origin::PaddingBox => fragment_builder.padding_rect(),
        Origin::BorderBox => &fragment_builder.border_rect,
    };

    // https://drafts.csswg.org/css-backgrounds/#background-size
    enum ContainOrCover {
        Contain,
        Cover,
    }
    let size_contain_or_cover = |background_size| {
        let mut tile_size = positioning_area.size;
        if let Some(intrinsic_ratio) = intrinsic.ratio {
            let positioning_ratio = positioning_area.size.width / positioning_area.size.height;
            // Whether the tile width (as opposed to height)
            // is scaled to that of the positioning area
            let fit_width = match background_size {
                ContainOrCover::Contain => positioning_ratio <= intrinsic_ratio,
                ContainOrCover::Cover => positioning_ratio > intrinsic_ratio,
            };
            // The other dimension needs to be adjusted
            if fit_width {
                tile_size.height = tile_size.width / intrinsic_ratio
            } else {
                tile_size.width = tile_size.height * intrinsic_ratio
            }
        }
        tile_size
    };
    let mut tile_size = match get_cyclic(&b.background_size.0, layer_index) {
        Size::Contain => size_contain_or_cover(ContainOrCover::Contain),
        Size::Cover => size_contain_or_cover(ContainOrCover::Cover),
        Size::ExplicitSize { width, height } => {
            let mut width = width.non_auto().map(|lp| {
                lp.0.percentage_relative_to(Length::new(positioning_area.size.width))
            });
            let mut height = height.non_auto().map(|lp| {
                lp.0.percentage_relative_to(Length::new(positioning_area.size.height))
            });

            if width.is_none() && height.is_none() {
                // Both computed values are 'auto':
                // use intrinsic sizes, treating missing width or height as 'auto'
                width = intrinsic.width;
                height = intrinsic.height;
            }

            match (width, height) {
                (Some(w), Some(h)) => units::LayoutSize::new(w.px(), h.px()),
                (Some(w), None) => {
                    let h = if let Some(intrinsic_ratio) = intrinsic.ratio {
                        w / intrinsic_ratio
                    } else if let Some(intrinsic_height) = intrinsic.height {
                        intrinsic_height
                    } else {
                        // Treated as 100%
                        Length::new(positioning_area.size.height)
                    };
                    units::LayoutSize::new(w.px(), h.px())
                },
                (None, Some(h)) => {
                    let w = if let Some(intrinsic_ratio) = intrinsic.ratio {
                        h * intrinsic_ratio
                    } else if let Some(intrinsic_width) = intrinsic.width {
                        intrinsic_width
                    } else {
                        // Treated as 100%
                        Length::new(positioning_area.size.width)
                    };
                    units::LayoutSize::new(w.px(), h.px())
                },
                // Both comptued values were 'auto', and neither intrinsic size is present
                (None, None) => size_contain_or_cover(ContainOrCover::Contain),
            }
        },
    };

    if tile_size.width == 0.0 || tile_size.height == 0.0 {
        return None;
    }

    let RepeatXY(repeat_x, repeat_y) = *get_cyclic(&b.background_repeat.0, layer_index);
    let result_x = layout_1d(
        &mut tile_size.width,
        repeat_x,
        get_cyclic(&b.background_position_x.0, layer_index),
        painting_area.origin.x - positioning_area.origin.x,
        painting_area.size.width,
        positioning_area.size.width,
    );
    let result_y = layout_1d(
        &mut tile_size.height,
        repeat_y,
        get_cyclic(&b.background_position_y.0, layer_index),
        painting_area.origin.y - positioning_area.origin.y,
        painting_area.size.height,
        positioning_area.size.height,
    );
    let bounds = units::LayoutRect::new(
        positioning_area.origin + Vector2D::new(result_x.bounds_origin, result_y.bounds_origin),
        Size2D::new(result_x.bounds_size, result_y.bounds_size),
    );
    let tile_spacing = units::LayoutSize::new(result_x.tile_spacing, result_y.tile_spacing);

    Some(BackgroundLayer {
        common,
        bounds,
        tile_size,
        tile_spacing,
        repeat: result_x.repeat || result_y.repeat,
    })
}

/// Abstract over the horizontal or vertical dimension
/// Coordinates (0, 0) for the purpose of this function are the positioning area’s origin.
fn layout_1d(
    tile_size: &mut f32,
    mut repeat: Repeat,
    position: &LengthPercentage,
    painting_area_origin: f32,
    painting_area_size: f32,
    positioning_area_size: f32,
) -> Layout1DResult {
    // https://drafts.csswg.org/css-backgrounds/#background-repeat
    if let Repeat::Round = repeat {
        *tile_size = positioning_area_size / (positioning_area_size / *tile_size).round();
    }
    // https://drafts.csswg.org/css-backgrounds/#background-position
    let mut position = position
        .percentage_relative_to(Length::new(positioning_area_size - *tile_size))
        .px();
    let mut tile_spacing = 0.0;
    // https://drafts.csswg.org/css-backgrounds/#background-repeat
    if let Repeat::Space = repeat {
        // The most entire tiles we can fit
        let tile_count = (positioning_area_size / *tile_size).floor();
        if tile_count >= 2.0 {
            position = 0.0;
            // Make the outsides of the first and last of that many tiles
            // touch the edges of the positioning area:
            let total_space = positioning_area_size - *tile_size * tile_count;
            let spaces_count = tile_count - 1.0;
            tile_spacing = total_space / spaces_count;
        } else {
            repeat = Repeat::NoRepeat
        }
    }
    match repeat {
        Repeat::Repeat | Repeat::Round | Repeat::Space => {
            // WebRender’s `RepeatingImageDisplayItem` contains a `bounds` rectangle and:
            //
            // * The tiling is clipped to the intersection of `clip_rect` and `bounds`
            // * The origin (top-left corner) of `bounds` is the position
            //   of the “first” (top-left-most) tile.
            //
            // In the general case that first tile is not the one that is positioned by
            // `background-position`.
            // We want it to be the top-left-most tile that intersects with `clip_rect`.
            // We find it by offsetting by a whole number of strides,
            // then compute `bounds` such that:
            //
            // * Its bottom-right is the bottom-right of `clip_rect`
            // * Its top-left is the top-left of first tile.
            let tile_stride = *tile_size + tile_spacing;
            let offset = position - painting_area_origin;
            let bounds_origin = position - tile_stride * (offset / tile_stride).ceil();
            let bounds_end = painting_area_origin + painting_area_size;
            let bounds_size = bounds_end - bounds_origin;
            Layout1DResult {
                repeat: true,
                bounds_origin,
                bounds_size,
                tile_spacing,
            }
        },
        Repeat::NoRepeat => {
            // `RepeatingImageDisplayItem` always repeats in both dimension.
            // When we want only one of the dimensions to repeat,
            // we use the `bounds` rectangle to clip the tiling to one tile
            // in that dimension.
            Layout1DResult {
                repeat: false,
                bounds_origin: position,
                bounds_size: *tile_size,
                tile_spacing: 0.0,
            }
        },
    }
}
<|endoftext|>


<commit_before>//
// Copyright 2020 The Project Oak Authors
//
// 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::collections::{HashMap, VecDeque};
use std::sync::atomic::AtomicU64;
use std::sync::atomic::Ordering::SeqCst;
use std::sync::{Arc, Mutex, RwLock, Weak};
use std::thread::{Thread, ThreadId};

use log::debug;
use rand::RngCore;

use oak_abi::OakStatus;

use crate::Message;

type Messages = VecDeque<Message>;

/// We use a `HashMap` keyed by `ThreadId` to prevent build up of stale `Weak<Thread>`s.
///
/// That is: If a thread waiting/blocked on a channel is woken by a different channel, its
/// `Weak<Thread>` will remain in the first channel's waiting_thread member. If a thread keeps
/// waiting on this first channel, and keeps being woken by other channels, it will keep re-adding
/// itself. We use a `HashMap` and insert at the current `ThreadId` so that we replace any stale
/// `Weak<Thread>`s which will have gone out of scope. (`wait_on_channels` drops the underlying arc
/// as soon as it is resumed.)
type WaitingThreads = Mutex<HashMap<ThreadId, Weak<Thread>>>;

/// The internal implementation of a channel representation backed by a `VecDeque<Message>`.
/// Readers and writers to this channel must increment the reader/writer count. This is implemented
/// for `ChannelWriter`/`ChannelReader`, which will increment/decrement readers/writers when
/// cloning/dropping.
#[derive(Debug)]
pub struct Channel {
    pub messages: RwLock<Messages>,

    pub writers: AtomicU64,
    pub readers: AtomicU64,

    /// A HashMap of `ThreadId`s to `Weak<Thread>`s. This allows threads to insert a weak reference
    /// to themselves to be woken when a new message is available. Weak references are used so that
    /// if the thread is woken by a different channel, it can deallocate the underlying `Arc`
    /// instead of removing itself from all the `Channel`s it subscribed to.
    /// Threads can be woken up spuriously without issue.
    pub waiting_threads: WaitingThreads,

    /// The Label associated with this channel.
    ///
    /// This is set at channel creation time and does not change after that.
    ///
    /// See https://github.com/project-oak/oak/blob/master/docs/concepts.md#labels
    pub label: oak_abi::label::Label,
}

/// A reference to a [`Channel`]. Each [`Handle`] has an implicit direction such that it is only
/// possible to read or write to a [`Handle`] (exclusive or).
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub struct Handle(oak_abi::Handle);

/// The direction of a [`Handle`] can be discovered by querying the associated
/// [`Runtime`] [`Runtime::channel_get_direction`].
///
/// [`Runtime`]: crate::runtime::Runtime
/// [`Runtime::channel_get_direction`]: crate::runtime::Runtime::channel_get_direction
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub enum HandleDirection {
    Read,
    Write,
}

/// An internal identifier to track a [`Channel`]. This is implementation specific and should not
/// be visible outside the internals of [`Runtime`].
type ChannelId = u64;

/// Ownership and mapping of [`Channel`]s to [`Handle`]s.
#[derive(Debug)]
pub struct ChannelMapping {
    pub channels: RwLock<HashMap<ChannelId, Channel>>,

    pub next_channel_id: AtomicU64,

    pub readers: RwLock<HashMap<Handle, ChannelId>>,
    pub writers: RwLock<HashMap<Handle, ChannelId>>,
}

impl Channel {
    /// Create a new channel with the assumption there is currently one active reader and one active
    /// writer references.
    pub fn new(label: &oak_abi::label::Label) -> Channel {
        Channel {
            messages: RwLock::new(Messages::new()),
            writers: AtomicU64::new(1),
            readers: AtomicU64::new(1),
            waiting_threads: Mutex::new(HashMap::new()),
            label: label.clone(),
        }
    }

    /// Thread safe method that returns true when there is no longer at least one reader and one
    /// writer.
    pub fn is_orphan(&self) -> bool {
        self.readers.load(SeqCst) == 0 || self.writers.load(SeqCst) == 0
    }

    /// Thread safe method that returns true when there is no longer at least one reader or
    /// writer.
    pub fn has_no_reference(&self) -> bool {
        self.readers.load(SeqCst) == 0 && self.writers.load(SeqCst) == 0
    }

    /// Insert the given `thread` reference into `thread_id` slot of the HashMap of waiting
    /// channels attached to an underlying channel. This allows the channel to wake up any waiting
    /// channels by calling `thread::unpark` on all the threads it knows about.
    pub fn add_waiter(&self, thread_id: ThreadId, thread: &Arc<Thread>) {
        self.waiting_threads
            .lock()
            .unwrap()
            .insert(thread_id, Arc::downgrade(thread));
    }

    /// Decrement the [`Channel`] writer counter.
    pub fn dec_writer_count(&self) {
        if self.writers.fetch_sub(1, SeqCst) == 0 {
            panic!("remove_reader: Writer count was already 0, something is very wrong!")
        }
    }

    /// Decrement the [`Channel`] reader counter.
    pub fn dec_reader_count(&self) {
        if self.readers.fetch_sub(1, SeqCst) == 0 {
            panic!("remove_reader: Reader count was already 0, something is very wrong!")
        }
    }

    /// Increment the [`Channel`] writer counter.
    pub fn inc_writer_count(&self) -> u64 {
        self.writers.fetch_add(1, SeqCst)
    }

    /// Increment the [`Channel`] reader counter.
    pub fn inc_reader_count(&self) -> u64 {
        self.readers.fetch_add(1, SeqCst)
    }
}

impl ChannelMapping {
    /// Create a new empty [`ChannelMapping`].
    pub fn new() -> ChannelMapping {
        ChannelMapping {
            channels: RwLock::new(HashMap::new()),

            next_channel_id: AtomicU64::new(0),

            readers: RwLock::new(HashMap::new()),
            writers: RwLock::new(HashMap::new()),
        }
    }

    /// Creates a new [`Channel`] and returns a `(writer handle, reader handle)` pair.
    pub fn new_channel(&self, label: &oak_abi::label::Label) -> (Handle, Handle) {
        let channel_id = self.next_channel_id.fetch_add(1, SeqCst);
        self.channels
            .write()
            .unwrap()
            .insert(channel_id, Channel::new(label));
        (self.new_writer(channel_id), self.new_reader(channel_id))
    }

    /// Get a new free random [`Handle`] that is not used by any readers or writers.
    fn new_reference(&self) -> Handle {
        loop {
            let handle = Handle(rand::thread_rng().next_u64());

            let exists_reader = self.readers.read().unwrap().get(&handle).is_some();
            let exists_writer = self.writers.read().unwrap().get(&handle).is_some();

            if exists_reader || exists_writer {
                continue;
            }

            return handle;
        }
    }

    /// Create a new writer reference.
    fn new_writer(&self, channel: ChannelId) -> Handle {
        let reference = self.new_reference();
        self.writers.write().unwrap().insert(reference, channel);
        reference
    }

    /// Create a new reader reference.
    fn new_reader(&self, channel: ChannelId) -> Handle {
        let reference = self.new_reference();
        self.readers.write().unwrap().insert(reference, channel);
        reference
    }

    /// Attempt to retrieve the [`ChannelId`] associated with a reader [`Handle`].
    pub fn get_reader_channel(&self, reference: Handle) -> Result<ChannelId, OakStatus> {
        self.readers
            .read()
            .unwrap()
            .get(&reference)
            .map_or(Err(OakStatus::ErrBadHandle), |id| Ok(*id))
    }

    /// Attempt to retrieve the [`ChannelId`] associated with a writer [`Handle`].
    pub fn get_writer_channel(&self, reference: Handle) -> Result<ChannelId, OakStatus> {
        self.writers
            .read()
            .unwrap()
            .get(&reference)
            .map_or(Err(OakStatus::ErrBadHandle), |id| Ok(*id))
    }

    /// Perform an operation on a [`Channel`] associated with some [`ChannelId`].
    /// The channels read lock is held while the operation is performed.
    pub fn with_channel<U, F: FnOnce(&Channel) -> Result<U, OakStatus>>(
        &self,
        channel_id: ChannelId,
        f: F,
    ) -> Result<U, OakStatus> {
        let channels = self.channels.read().unwrap();
        let channel = channels.get(&channel_id).ok_or(OakStatus::ErrBadHandle)?;
        f(channel)
    }

    /// Deallocate a [`Handle`] reference. The reference will no longer be usable in
    /// operations, and the underlying [`Channel`] may become orphaned.
    pub fn remove_reference(&self, reference: Handle) -> Result<(), OakStatus> {
        if let Ok(channel_id) = self.get_writer_channel(reference) {
            {
                let mut channels = self.channels.write().unwrap();
                let channel = channels
                    .get(&channel_id)
                    .expect("remove_reference: Handle is invalid!");
                channel.dec_writer_count();
                if channel.has_no_reference() {
                    channels.remove(&channel_id);
                    debug!("remove_reference: deallocating channel {:?}", channel_id);
                }
            }

            self.writers.write().unwrap().remove(&reference);
        }

        if let Ok(channel_id) = self.get_reader_channel(reference) {
            {
                let mut channels = self.channels.write().unwrap();
                let channel = channels
                    .get(&channel_id)
                    .expect("remove_reference: Handle is invalid!");
                channel.dec_reader_count();
                if channel.has_no_reference() {
                    channels.remove(&channel_id);
                    debug!("remove_reference: deallocating channel {:?}", channel_id);
                }
            }

            self.readers.write().unwrap().remove(&reference);
        }

        Ok(())
    }

    /// Duplicate a [`Handle`] reference. This new reference and when it is closed will be
    /// tracked separately from the first [`Handle`]. For instance this is used by the
    /// [`oak_runtime::Runtime`] to encode [`Channel`]s in messages.
    pub fn duplicate_reference(&self, reference: Handle) -> Result<Handle, OakStatus> {
        if let Ok(channel_id) = self.get_writer_channel(reference) {
            self.with_channel(channel_id, |channel| Ok(channel.inc_writer_count()))?;

            return Ok(self.new_writer(channel_id));
        }

        if let Ok(channel_id) = self.get_reader_channel(reference) {
            self.with_channel(channel_id, |channel| Ok(channel.inc_reader_count()))?;

            return Ok(self.new_reader(channel_id));
        }

        Err(OakStatus::ErrBadHandle)
    }
}
<commit_msg>runtime/rust: use consistent naming for channel IDs<commit_after>//
// Copyright 2020 The Project Oak Authors
//
// 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::collections::{HashMap, VecDeque};
use std::sync::atomic::AtomicU64;
use std::sync::atomic::Ordering::SeqCst;
use std::sync::{Arc, Mutex, RwLock, Weak};
use std::thread::{Thread, ThreadId};

use log::debug;
use rand::RngCore;

use oak_abi::OakStatus;

use crate::Message;

type Messages = VecDeque<Message>;

/// We use a `HashMap` keyed by `ThreadId` to prevent build up of stale `Weak<Thread>`s.
///
/// That is: If a thread waiting/blocked on a channel is woken by a different channel, its
/// `Weak<Thread>` will remain in the first channel's waiting_thread member. If a thread keeps
/// waiting on this first channel, and keeps being woken by other channels, it will keep re-adding
/// itself. We use a `HashMap` and insert at the current `ThreadId` so that we replace any stale
/// `Weak<Thread>`s which will have gone out of scope. (`wait_on_channels` drops the underlying arc
/// as soon as it is resumed.)
type WaitingThreads = Mutex<HashMap<ThreadId, Weak<Thread>>>;

/// The internal implementation of a channel representation backed by a `VecDeque<Message>`.
/// Readers and writers to this channel must increment the reader/writer count. This is implemented
/// for `ChannelWriter`/`ChannelReader`, which will increment/decrement readers/writers when
/// cloning/dropping.
#[derive(Debug)]
pub struct Channel {
    pub messages: RwLock<Messages>,

    pub writers: AtomicU64,
    pub readers: AtomicU64,

    /// A HashMap of `ThreadId`s to `Weak<Thread>`s. This allows threads to insert a weak reference
    /// to themselves to be woken when a new message is available. Weak references are used so that
    /// if the thread is woken by a different channel, it can deallocate the underlying `Arc`
    /// instead of removing itself from all the `Channel`s it subscribed to.
    /// Threads can be woken up spuriously without issue.
    pub waiting_threads: WaitingThreads,

    /// The Label associated with this channel.
    ///
    /// This is set at channel creation time and does not change after that.
    ///
    /// See https://github.com/project-oak/oak/blob/master/docs/concepts.md#labels
    pub label: oak_abi::label::Label,
}

/// A reference to a [`Channel`]. Each [`Handle`] has an implicit direction such that it is only
/// possible to read or write to a [`Handle`] (exclusive or).
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub struct Handle(oak_abi::Handle);

/// The direction of a [`Handle`] can be discovered by querying the associated
/// [`Runtime`] [`Runtime::channel_get_direction`].
///
/// [`Runtime`]: crate::runtime::Runtime
/// [`Runtime::channel_get_direction`]: crate::runtime::Runtime::channel_get_direction
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub enum HandleDirection {
    Read,
    Write,
}

/// An internal identifier to track a [`Channel`]. This is implementation specific and should not
/// be visible outside the internals of [`Runtime`].
type ChannelId = u64;

/// Ownership and mapping of [`Channel`]s to [`Handle`]s.
#[derive(Debug)]
pub struct ChannelMapping {
    pub channels: RwLock<HashMap<ChannelId, Channel>>,

    pub next_channel_id: AtomicU64,

    pub readers: RwLock<HashMap<Handle, ChannelId>>,
    pub writers: RwLock<HashMap<Handle, ChannelId>>,
}

impl Channel {
    /// Create a new channel with the assumption there is currently one active reader and one active
    /// writer references.
    pub fn new(label: &oak_abi::label::Label) -> Channel {
        Channel {
            messages: RwLock::new(Messages::new()),
            writers: AtomicU64::new(1),
            readers: AtomicU64::new(1),
            waiting_threads: Mutex::new(HashMap::new()),
            label: label.clone(),
        }
    }

    /// Thread safe method that returns true when there is no longer at least one reader and one
    /// writer.
    pub fn is_orphan(&self) -> bool {
        self.readers.load(SeqCst) == 0 || self.writers.load(SeqCst) == 0
    }

    /// Thread safe method that returns true when there is no longer at least one reader or
    /// writer.
    pub fn has_no_reference(&self) -> bool {
        self.readers.load(SeqCst) == 0 && self.writers.load(SeqCst) == 0
    }

    /// Insert the given `thread` reference into `thread_id` slot of the HashMap of waiting
    /// channels attached to an underlying channel. This allows the channel to wake up any waiting
    /// channels by calling `thread::unpark` on all the threads it knows about.
    pub fn add_waiter(&self, thread_id: ThreadId, thread: &Arc<Thread>) {
        self.waiting_threads
            .lock()
            .unwrap()
            .insert(thread_id, Arc::downgrade(thread));
    }

    /// Decrement the [`Channel`] writer counter.
    pub fn dec_writer_count(&self) {
        if self.writers.fetch_sub(1, SeqCst) == 0 {
            panic!("remove_reader: Writer count was already 0, something is very wrong!")
        }
    }

    /// Decrement the [`Channel`] reader counter.
    pub fn dec_reader_count(&self) {
        if self.readers.fetch_sub(1, SeqCst) == 0 {
            panic!("remove_reader: Reader count was already 0, something is very wrong!")
        }
    }

    /// Increment the [`Channel`] writer counter.
    pub fn inc_writer_count(&self) -> u64 {
        self.writers.fetch_add(1, SeqCst)
    }

    /// Increment the [`Channel`] reader counter.
    pub fn inc_reader_count(&self) -> u64 {
        self.readers.fetch_add(1, SeqCst)
    }
}

impl ChannelMapping {
    /// Create a new empty [`ChannelMapping`].
    pub fn new() -> ChannelMapping {
        ChannelMapping {
            channels: RwLock::new(HashMap::new()),

            next_channel_id: AtomicU64::new(0),

            readers: RwLock::new(HashMap::new()),
            writers: RwLock::new(HashMap::new()),
        }
    }

    /// Creates a new [`Channel`] and returns a `(writer handle, reader handle)` pair.
    pub fn new_channel(&self, label: &oak_abi::label::Label) -> (Handle, Handle) {
        let channel_id = self.next_channel_id.fetch_add(1, SeqCst);
        self.channels
            .write()
            .unwrap()
            .insert(channel_id, Channel::new(label));
        (self.new_writer(channel_id), self.new_reader(channel_id))
    }

    /// Get a new free random [`Handle`] that is not used by any readers or writers.
    fn new_reference(&self) -> Handle {
        loop {
            let handle = Handle(rand::thread_rng().next_u64());

            let exists_reader = self.readers.read().unwrap().get(&handle).is_some();
            let exists_writer = self.writers.read().unwrap().get(&handle).is_some();

            if exists_reader || exists_writer {
                continue;
            }

            return handle;
        }
    }

    /// Create a new writer reference.
    fn new_writer(&self, channel_id: ChannelId) -> Handle {
        let reference = self.new_reference();
        self.writers.write().unwrap().insert(reference, channel_id);
        reference
    }

    /// Create a new reader reference.
    fn new_reader(&self, channel_id: ChannelId) -> Handle {
        let reference = self.new_reference();
        self.readers.write().unwrap().insert(reference, channel_id);
        reference
    }

    /// Attempt to retrieve the [`ChannelId`] associated with a reader [`Handle`].
    pub fn get_reader_channel(&self, reference: Handle) -> Result<ChannelId, OakStatus> {
        self.readers
            .read()
            .unwrap()
            .get(&reference)
            .map_or(Err(OakStatus::ErrBadHandle), |id| Ok(*id))
    }

    /// Attempt to retrieve the [`ChannelId`] associated with a writer [`Handle`].
    pub fn get_writer_channel(&self, reference: Handle) -> Result<ChannelId, OakStatus> {
        self.writers
            .read()
            .unwrap()
            .get(&reference)
            .map_or(Err(OakStatus::ErrBadHandle), |id| Ok(*id))
    }

    /// Perform an operation on a [`Channel`] associated with some [`ChannelId`].
    /// The channels read lock is held while the operation is performed.
    pub fn with_channel<U, F: FnOnce(&Channel) -> Result<U, OakStatus>>(
        &self,
        channel_id: ChannelId,
        f: F,
    ) -> Result<U, OakStatus> {
        let channels = self.channels.read().unwrap();
        let channel = channels.get(&channel_id).ok_or(OakStatus::ErrBadHandle)?;
        f(channel)
    }

    /// Deallocate a [`Handle`] reference. The reference will no longer be usable in
    /// operations, and the underlying [`Channel`] may become orphaned.
    pub fn remove_reference(&self, reference: Handle) -> Result<(), OakStatus> {
        if let Ok(channel_id) = self.get_writer_channel(reference) {
            {
                let mut channels = self.channels.write().unwrap();
                let channel = channels
                    .get(&channel_id)
                    .expect("remove_reference: Handle is invalid!");
                channel.dec_writer_count();
                if channel.has_no_reference() {
                    channels.remove(&channel_id);
                    debug!("remove_reference: deallocating channel {:?}", channel_id);
                }
            }

            self.writers.write().unwrap().remove(&reference);
        }

        if let Ok(channel_id) = self.get_reader_channel(reference) {
            {
                let mut channels = self.channels.write().unwrap();
                let channel = channels
                    .get(&channel_id)
                    .expect("remove_reference: Handle is invalid!");
                channel.dec_reader_count();
                if channel.has_no_reference() {
                    channels.remove(&channel_id);
                    debug!("remove_reference: deallocating channel {:?}", channel_id);
                }
            }

            self.readers.write().unwrap().remove(&reference);
        }

        Ok(())
    }

    /// Duplicate a [`Handle`] reference. This new reference and when it is closed will be
    /// tracked separately from the first [`Handle`]. For instance this is used by the
    /// [`oak_runtime::Runtime`] to encode [`Channel`]s in messages.
    pub fn duplicate_reference(&self, reference: Handle) -> Result<Handle, OakStatus> {
        if let Ok(channel_id) = self.get_writer_channel(reference) {
            self.with_channel(channel_id, |channel| Ok(channel.inc_writer_count()))?;

            return Ok(self.new_writer(channel_id));
        }

        if let Ok(channel_id) = self.get_reader_channel(reference) {
            self.with_channel(channel_id, |channel| Ok(channel.inc_reader_count()))?;

            return Ok(self.new_reader(channel_id));
        }

        Err(OakStatus::ErrBadHandle)
    }
}
<|endoftext|>


<commit_before>/* kernel::filesystem.rs */
use core::*;
use core::str::*;
use core::option::{Some, Option, None}; // Match statement
use core::iter::Iterator;
use kernel::vec::Vec;
use super::super::platform::*;
use kernel::sgash;
use core::iter::Iterator;

pub struct DirNode {
    name: sgash::cstr,
    parent: *mut DirNode,
    dchildren: *mut Vec<*mut DirNode>,
    fchildren : *mut Vec<*mut FileNode>,
}

impl DirNode {
    pub unsafe fn new(file_name: sgash::cstr, dad: *mut DirNode) -> DirNode {
        let this = DirNode {
            name: file_name,
            parent: dad,

            dchildren: &mut Vec::new() as *mut Vec<*mut DirNode>,
            fchildren : &mut Vec::new() as *mut Vec<*mut FileNode>,
        };
        this
    }

    pub unsafe fn list_directory (&mut self) -> Vec<sgash::cstr>{
        let mut ls = &mut Vec::new() as *mut Vec<*mut sgash::cstr>;
        for d in iter((*self.dchildren).as_mut_slice()){
        	ls.push(d);
        }

    }

    pub unsafe fn create_directory(&mut self, d : sgash::cstr) {
        let newNode : *mut DirNode = &mut DirNode::new(d, self);
       (*self.dchildren).push(newNode);
    }

    pub unsafe fn create_file(&mut self, d : sgash::cstr) {
    	let empty = sgash::cstr::new(0);
        let newNode : *mut FileNode = &mut FileNode::new(d, self, empty);
       (*self.fchildren).push(newNode);
    }

    pub unsafe fn write_file(&mut self, d : sgash::cstr, contents : sgash::cstr) {
        let newNode : *mut FileNode = &mut FileNode::new(d, self, contents);
       (*self.fchildren).push(newNode);
    }

    // pub unsafe fn get_file(&mut self, name : sgash::cstr){

    // }
}

pub struct FileNode {
    name: sgash::cstr,
    parent: *mut DirNode,
    contents: sgash::cstr,
}

impl FileNode {
    pub unsafe fn new (file_name: sgash::cstr, dad: *mut DirNode, words: sgash::cstr) -> FileNode {
        let this = FileNode {
            name: file_name,
            parent: dad,
            contents: words,
        };
        this
    }

    pub unsafe fn getName(&self) -> sgash::cstr {
        self.name
    }

    //cat <file>
    pub fn read_file(&self) -> sgash::cstr {
        self.contents
    }
}

// // rm
// pub fn delete_file(directory, name){}

// // ???
// pub fn get_file(directory, name){}

// // ls
// pub fn list_directory(directory){}

// // mkdir
// pub fn create_directory(parent, name){}

// // rm
// pub fn delete_directory(directory){}

// // pwd
// pub fn get_directory(parent, name){}

<commit_msg>simplified code using imports<commit_after>/* kernel::filesystem.rs */
use core::*;
use core::str::*;
use core::option::{Some, Option, None}; // Match statement
use core::iter::Iterator;
use kernel::vec::Vec;
use super::super::platform::*;
use kernel::sgash::cstr;
use kernel::sgash::drawcstr;
use kernel::sgash::putcstr;
use core::iter::Iterator;
use core::slice::iter;

pub struct DirNode {
    name: cstr,
    parent: *mut DirNode,
    dchildren: *mut Vec<*mut DirNode>,
    fchildren : *mut Vec<*mut FileNode>,
}

impl DirNode {
    pub unsafe fn new(file_name: cstr, dad: *mut DirNode) -> DirNode {
        let this = DirNode {
            name: file_name,
            parent: dad,

            dchildren: &mut Vec::new() as *mut Vec<*mut DirNode>,
            fchildren : &mut Vec::new() as *mut Vec<*mut FileNode>,
        };
        this
    }

    pub unsafe fn list_directory (&mut self){
        for d in iter((self.dchildren).as_mut_slice()){
        	putcstr(d.name);
        	drawcstr(d.name);
        }

    }

    pub unsafe fn create_directory(&mut self, d : cstr) {
        let newNode : *mut DirNode = &mut DirNode::new(d, self);
       (*self.dchildren).push(newNode);
    }

    pub unsafe fn create_file(&mut self, d : cstr) {
    	let empty = cstr::new(0);
        let newNode : *mut FileNode = &mut FileNode::new(d, self, empty);
       (*self.fchildren).push(newNode);
    }

    pub unsafe fn write_file(&mut self, d : cstr, contents : cstr) {
        let newNode : *mut FileNode = &mut FileNode::new(d, self, contents);
       (*self.fchildren).push(newNode);
    }

    // pub unsafe fn get_file(&mut self, name : cstr){

    // }
}

pub struct FileNode {
    name: cstr,
    parent: *mut DirNode,
    contents: cstr,
}

impl FileNode {
    pub unsafe fn new (file_name: cstr, dad: *mut DirNode, words: cstr) -> FileNode {
        let this = FileNode {
            name: file_name,
            parent: dad,
            contents: words,
        };
        this
    }

    pub unsafe fn getName(&self) -> cstr {
        self.name
    }

    //cat <file>
    pub fn read_file(&self) -> cstr {
        self.contents
    }
}

// // rm
// pub fn delete_file(directory, name){}

// // ???
// pub fn get_file(directory, name){}

// // ls
// pub fn list_directory(directory){}

// // mkdir
// pub fn create_directory(parent, name){}

// // rm
// pub fn delete_directory(directory){}

// // pwd
// pub fn get_directory(parent, name){}

<|endoftext|>


<commit_before>use crate::grammar::ast::eq::AstEq;
use crate::grammar::ast::{Expression, FuncCallExpression};
use crate::grammar::model::{Fragment, HasFragment};
use crate::grammar::parsers::expression::ToExpression;
use crate::grammar::parsers::whitespace::token_delimiter;
use crate::grammar::parsers::with_input;
use nom::character::complete::char as ch;
use nom::combinator::map;
use nom::multi::separated_list;
use nom::sequence::{delimited, pair, terminated};
use nom::IResult;

impl<'s> FuncCallExpression<'s> {
    /// Left parenthesis delimiting argument list. Probably should never change.
    pub const DELIMITER_LEFT: char = '(';

    /// Left parenthesis delimiting argument list. Probably should never change.
    pub const DELIMITER_RIGHT: char = ')';

    /// Comma separating arguments. Probably should never change.
    pub const ARG_SEPARATOR: char = ',';

    /// Parse an index expression in wright source code.
    pub fn parse(input: Fragment<'s>) -> IResult<Fragment<'s>, Self> {
        map(
            with_input(pair(
                terminated(
                    Expression::parse,
                    pair(token_delimiter, ch(Self::DELIMITER_LEFT)),
                ),
                terminated(
                    separated_list(ch(Self::ARG_SEPARATOR), Expression::parse),
                    delimited(token_delimiter, ch(Self::DELIMITER_RIGHT), token_delimiter),
                ),
            )),
            move |(consumed, (func, args))| Self {
                frag: consumed,
                func: Box::new(func),
                args,
            },
        )(input)
    }
}

impl<'s> HasFragment<'s> for FuncCallExpression<'s> {
    fn get_fragment(&self) -> Fragment<'s> {
        self.frag
    }
}

impl<'s> AstEq for FuncCallExpression<'s> {
    fn ast_eq(fst: &Self, snd: &Self) -> bool {
        AstEq::ast_eq(&fst.func, &snd.func) && AstEq::ast_eq(&fst.args, &snd.args)
    }
}

impl<'s> ToExpression<'s> for FuncCallExpression<'s> {
    fn create_expr(self) -> Expression<'s> {
        Expression::FuncCall(self)
    }
}
<commit_msg>func call parser: rearrange calls to make easier to understand<commit_after>use crate::grammar::ast::eq::AstEq;
use crate::grammar::ast::{Expression, FuncCallExpression};
use crate::grammar::model::{Fragment, HasFragment};
use crate::grammar::parsers::expression::ToExpression;
use crate::grammar::parsers::whitespace::token_delimiter;
use crate::grammar::parsers::with_input;
use nom::character::complete::char as ch;
use nom::combinator::map;
use nom::multi::separated_list;
use nom::sequence::{delimited, pair, tuple};
use nom::IResult;

impl<'s> FuncCallExpression<'s> {
    /// Left parenthesis delimiting argument list. Probably should never change.
    pub const DELIMITER_LEFT: char = '(';

    /// Left parenthesis delimiting argument list. Probably should never change.
    pub const DELIMITER_RIGHT: char = ')';

    /// Comma separating arguments. Probably should never change.
    pub const ARG_SEPARATOR: char = ',';

    /// Parse an index expression in wright source code.
    pub fn parse(input: Fragment<'s>) -> IResult<Fragment<'s>, Self> {
        map(
            with_input(pair(
                Expression::parse,
                delimited(
                    tuple((token_delimiter, ch(Self::DELIMITER_LEFT), token_delimiter)),
                    separated_list(ch(Self::ARG_SEPARATOR), Expression::parse),
                    tuple((token_delimiter, ch(Self::DELIMITER_RIGHT), token_delimiter)),
                ),
            )),
            move |(consumed, (func, args))| Self {
                frag: consumed,
                func: Box::new(func),
                args,
            },
        )(input)
    }
}

impl<'s> HasFragment<'s> for FuncCallExpression<'s> {
    fn get_fragment(&self) -> Fragment<'s> {
        self.frag
    }
}

impl<'s> AstEq for FuncCallExpression<'s> {
    fn ast_eq(fst: &Self, snd: &Self) -> bool {
        AstEq::ast_eq(&fst.func, &snd.func) && AstEq::ast_eq(&fst.args, &snd.args)
    }
}

impl<'s> ToExpression<'s> for FuncCallExpression<'s> {
    fn create_expr(self) -> Expression<'s> {
        Expression::FuncCall(self)
    }
}
<|endoftext|>


<commit_before>use std::{cmp, fmt};

use index::{ByteIndex, Index};

/// A region of code in a source file
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Ord, PartialOrd)]
pub struct Span<I> {
    start: I,
    end: I,
}

impl<I: Index> Span<I> {
    /// Create a new span
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let span = Span::new(ByteIndex(3), ByteIndex(6));
    /// assert_eq!(span.start(), ByteIndex(3));
    /// assert_eq!(span.end(), ByteIndex(6));
    /// ```
    ///
    /// `start` and `end` are reordered to maintain the invariant that `start <= end`
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let span = Span::new(ByteIndex(6), ByteIndex(3));
    /// assert_eq!(span.start(), ByteIndex(3));
    /// assert_eq!(span.end(), ByteIndex(6));
    /// ```
    pub fn new(start: I, end: I) -> Span<I> {
        if start <= end {
            Span { start, end }
        } else {
            Span {
                start: end,
                end: start,
            }
        }
    }

    /// Makes a span from offsets relative to the start of this span.
    pub fn subspan(&self, begin: I::Offset, end: I::Offset) -> Span<I> {
        assert!(end >= begin);
        assert!(self.start() + end <= self.end());
        Span {
            start: self.start() + begin,
            end: self.start() + end,
        }
    }

    /// Create a new span from a byte start and an offset
    pub fn from_offset(start: I, off: I::Offset) -> Span<I> {
        Span::new(start, start + off)
    }

    /// Get the start index
    pub fn start(self) -> I {
        self.start
    }

    /// Get the end index
    pub fn end(self) -> I {
        self.end
    }

    /// Return a new span with the low byte position replaced with the supplied byte position
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let span = Span::new(ByteIndex(3), ByteIndex(6));
    /// assert_eq!(span.with_lo(ByteIndex(2)), Span::new(ByteIndex(2), ByteIndex(6)));
    /// assert_eq!(span.with_lo(ByteIndex(5)), Span::new(ByteIndex(5), ByteIndex(6)));
    /// assert_eq!(span.with_lo(ByteIndex(7)), Span::new(ByteIndex(6), ByteIndex(7)));
    /// ```
    pub fn with_lo(self, start: I) -> Span<I> {
        Span::new(start, self.end())
    }

    /// Return a new span with the high byte position replaced with the supplied byte position
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let span = Span::new(ByteIndex(3), ByteIndex(6));
    /// assert_eq!(span.with_hi(ByteIndex(7)), Span::new(ByteIndex(3), ByteIndex(7)));
    /// assert_eq!(span.with_hi(ByteIndex(5)), Span::new(ByteIndex(3), ByteIndex(5)));
    /// assert_eq!(span.with_hi(ByteIndex(2)), Span::new(ByteIndex(2), ByteIndex(3)));
    /// ```
    pub fn with_hi(self, end: I) -> Span<I> {
        Span::new(self.start(), end)
    }

    /// Return true if `self` fully encloses `other`.
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let a = Span::new(ByteIndex(5), ByteIndex(8));
    ///
    /// assert_eq!(a.contains(a), true);
    /// assert_eq!(a.contains(Span::new(ByteIndex(6), ByteIndex(7))), true);
    /// assert_eq!(a.contains(Span::new(ByteIndex(6), ByteIndex(10))), false);
    /// assert_eq!(a.contains(Span::new(ByteIndex(3), ByteIndex(6))), false);
    /// ```
    pub fn contains(self, other: Span<I>) -> bool {
        self.start() <= other.start() && other.end() <= self.end()
    }

    /// Return a `Span` that would enclose both `self` and `end`.
    ///
    /// ```plain
    /// self     ~~~~~~~
    /// end                     ~~~~~~~~
    /// returns  ~~~~~~~~~~~~~~~~~~~~~~~
    /// ```
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let a = Span::new(ByteIndex(2), ByteIndex(5));
    /// let b = Span::new(ByteIndex(10), ByteIndex(14));
    ///
    /// assert_eq!(a.to(b), Span::new(ByteIndex(2), ByteIndex(14)));
    /// ```
    pub fn to(self, end: Span<I>) -> Span<I> {
        Span::new(
            cmp::min(self.start(), end.start()),
            cmp::max(self.end(), end.end()),
        )
    }

    /// Return a `Span` between the end of `self` to the beginning of `end`.
    ///
    /// ```plain
    /// self     ~~~~~~~
    /// end                     ~~~~~~~~
    /// returns         ~~~~~~~~~
    /// ```
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let a = Span::new(ByteIndex(2), ByteIndex(5));
    /// let b = Span::new(ByteIndex(10), ByteIndex(14));
    ///
    /// assert_eq!(a.between(b), Span::new(ByteIndex(5), ByteIndex(10)));
    /// ```
    pub fn between(self, end: Span<I>) -> Span<I> {
        Span::new(self.end(), end.start())
    }

    /// Return a `Span` between the beginning of `self` to the beginning of `end`.
    ///
    /// ```plain
    /// self     ~~~~~~~
    /// end                     ~~~~~~~~
    /// returns  ~~~~~~~~~~~~~~~~
    /// ```
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let a = Span::new(ByteIndex(2), ByteIndex(5));
    /// let b = Span::new(ByteIndex(10), ByteIndex(14));
    ///
    /// assert_eq!(a.until(b), Span::new(ByteIndex(2), ByteIndex(10)));
    /// ```
    pub fn until(self, end: Span<I>) -> Span<I> {
        Span::new(self.start(), end.start())
    }
}

impl<I: fmt::Display> fmt::Display for Span<I> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.start.fmt(f)?;
        write!(f, "..")?;
        self.end.fmt(f)?;
        Ok(())
    }
}

pub type ByteSpan = Span<ByteIndex>;
<commit_msg>Add doc comment for ByteSpan<commit_after>use std::{cmp, fmt};

use index::{ByteIndex, Index};

/// A region of code in a source file
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Ord, PartialOrd)]
pub struct Span<I> {
    start: I,
    end: I,
}

impl<I: Index> Span<I> {
    /// Create a new span
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let span = Span::new(ByteIndex(3), ByteIndex(6));
    /// assert_eq!(span.start(), ByteIndex(3));
    /// assert_eq!(span.end(), ByteIndex(6));
    /// ```
    ///
    /// `start` and `end` are reordered to maintain the invariant that `start <= end`
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let span = Span::new(ByteIndex(6), ByteIndex(3));
    /// assert_eq!(span.start(), ByteIndex(3));
    /// assert_eq!(span.end(), ByteIndex(6));
    /// ```
    pub fn new(start: I, end: I) -> Span<I> {
        if start <= end {
            Span { start, end }
        } else {
            Span {
                start: end,
                end: start,
            }
        }
    }

    /// Makes a span from offsets relative to the start of this span.
    pub fn subspan(&self, begin: I::Offset, end: I::Offset) -> Span<I> {
        assert!(end >= begin);
        assert!(self.start() + end <= self.end());
        Span {
            start: self.start() + begin,
            end: self.start() + end,
        }
    }

    /// Create a new span from a byte start and an offset
    pub fn from_offset(start: I, off: I::Offset) -> Span<I> {
        Span::new(start, start + off)
    }

    /// Get the start index
    pub fn start(self) -> I {
        self.start
    }

    /// Get the end index
    pub fn end(self) -> I {
        self.end
    }

    /// Return a new span with the low byte position replaced with the supplied byte position
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let span = Span::new(ByteIndex(3), ByteIndex(6));
    /// assert_eq!(span.with_lo(ByteIndex(2)), Span::new(ByteIndex(2), ByteIndex(6)));
    /// assert_eq!(span.with_lo(ByteIndex(5)), Span::new(ByteIndex(5), ByteIndex(6)));
    /// assert_eq!(span.with_lo(ByteIndex(7)), Span::new(ByteIndex(6), ByteIndex(7)));
    /// ```
    pub fn with_lo(self, start: I) -> Span<I> {
        Span::new(start, self.end())
    }

    /// Return a new span with the high byte position replaced with the supplied byte position
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let span = Span::new(ByteIndex(3), ByteIndex(6));
    /// assert_eq!(span.with_hi(ByteIndex(7)), Span::new(ByteIndex(3), ByteIndex(7)));
    /// assert_eq!(span.with_hi(ByteIndex(5)), Span::new(ByteIndex(3), ByteIndex(5)));
    /// assert_eq!(span.with_hi(ByteIndex(2)), Span::new(ByteIndex(2), ByteIndex(3)));
    /// ```
    pub fn with_hi(self, end: I) -> Span<I> {
        Span::new(self.start(), end)
    }

    /// Return true if `self` fully encloses `other`.
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let a = Span::new(ByteIndex(5), ByteIndex(8));
    ///
    /// assert_eq!(a.contains(a), true);
    /// assert_eq!(a.contains(Span::new(ByteIndex(6), ByteIndex(7))), true);
    /// assert_eq!(a.contains(Span::new(ByteIndex(6), ByteIndex(10))), false);
    /// assert_eq!(a.contains(Span::new(ByteIndex(3), ByteIndex(6))), false);
    /// ```
    pub fn contains(self, other: Span<I>) -> bool {
        self.start() <= other.start() && other.end() <= self.end()
    }

    /// Return a `Span` that would enclose both `self` and `end`.
    ///
    /// ```plain
    /// self     ~~~~~~~
    /// end                     ~~~~~~~~
    /// returns  ~~~~~~~~~~~~~~~~~~~~~~~
    /// ```
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let a = Span::new(ByteIndex(2), ByteIndex(5));
    /// let b = Span::new(ByteIndex(10), ByteIndex(14));
    ///
    /// assert_eq!(a.to(b), Span::new(ByteIndex(2), ByteIndex(14)));
    /// ```
    pub fn to(self, end: Span<I>) -> Span<I> {
        Span::new(
            cmp::min(self.start(), end.start()),
            cmp::max(self.end(), end.end()),
        )
    }

    /// Return a `Span` between the end of `self` to the beginning of `end`.
    ///
    /// ```plain
    /// self     ~~~~~~~
    /// end                     ~~~~~~~~
    /// returns         ~~~~~~~~~
    /// ```
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let a = Span::new(ByteIndex(2), ByteIndex(5));
    /// let b = Span::new(ByteIndex(10), ByteIndex(14));
    ///
    /// assert_eq!(a.between(b), Span::new(ByteIndex(5), ByteIndex(10)));
    /// ```
    pub fn between(self, end: Span<I>) -> Span<I> {
        Span::new(self.end(), end.start())
    }

    /// Return a `Span` between the beginning of `self` to the beginning of `end`.
    ///
    /// ```plain
    /// self     ~~~~~~~
    /// end                     ~~~~~~~~
    /// returns  ~~~~~~~~~~~~~~~~
    /// ```
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let a = Span::new(ByteIndex(2), ByteIndex(5));
    /// let b = Span::new(ByteIndex(10), ByteIndex(14));
    ///
    /// assert_eq!(a.until(b), Span::new(ByteIndex(2), ByteIndex(10)));
    /// ```
    pub fn until(self, end: Span<I>) -> Span<I> {
        Span::new(self.start(), end.start())
    }
}

impl<I: fmt::Display> fmt::Display for Span<I> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.start.fmt(f)?;
        write!(f, "..")?;
        self.end.fmt(f)?;
        Ok(())
    }
}

/// A span of byte indices
pub type ByteSpan = Span<ByteIndex>;
<|endoftext|>