<commit_before>//! Context management

use collections::{BTreeMap, Vec};
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};

use arch::context::Context as ArchContext;
use syscall::{Error, Result};

/// File operations
pub mod file;

/// Limit on number of contexts
pub const CONTEXT_MAX_CONTEXTS: usize = 65536;

/// Maximum context files
pub const CONTEXT_MAX_FILES: usize = 65536;

/// Context list type
pub struct ContextList {
    map: BTreeMap<usize, RwLock<Context>>,
    next_id: usize
}

impl ContextList {
    pub fn new() -> Self {
        ContextList {
            map: BTreeMap::new(),
            next_id: 1
        }
    }

    pub fn get(&self, id: usize) -> Option<&RwLock<Context>> {
        self.map.get(&id)
    }

    pub fn current(&self) -> Option<&RwLock<Context>> {
        self.map.get(&CONTEXT_ID.load(Ordering::SeqCst))
    }

    pub fn new_context(&mut self) -> Result<&RwLock<Context>> {
        if self.next_id >= CONTEXT_MAX_CONTEXTS {
            self.next_id = 1;
        }

        while self.map.contains_key(&self.next_id) {
            self.next_id += 1;
        }

        if self.next_id >= CONTEXT_MAX_CONTEXTS {
            return Err(Error::TryAgain);
        }

        let id = self.next_id;
        self.next_id += 1;
        assert!(self.map.insert(id, RwLock::new(Context::new(id))).is_none());
        Ok(self.map.get(&id).expect("failed to insert new context"))
    }

    pub fn spawn(&mut self, func: extern fn()) -> Result<&RwLock<Context>> {
        let context_lock = self.new_context()?;
        {
            let mut context = context_lock.write();
            print!("{}", format!("{}: {:X}\n", context.id, func as usize));
        }
        Ok(context_lock)
    }
}

/// Contexts list
static CONTEXTS: Once<RwLock<ContextList>> = Once::new();

#[thread_local]
static CONTEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;

pub fn init() {
    let mut contexts = contexts_mut();
    let context_lock = contexts.new_context().expect("could not initialize first context");
    let context = context_lock.read();
    CONTEXT_ID.store(context.id, Ordering::SeqCst);
}

/// Initialize contexts, called if needed
fn init_contexts() -> RwLock<ContextList> {
    RwLock::new(ContextList::new())
}

/// Get the global schemes list, const
pub fn contexts() -> RwLockReadGuard<'static, ContextList> {
    CONTEXTS.call_once(init_contexts).read()
}

/// Get the global schemes list, mutable
pub fn contexts_mut() -> RwLockWriteGuard<'static, ContextList> {
    CONTEXTS.call_once(init_contexts).write()
}

/// Switch to the next context
/// Do not call this while holding locks!
pub unsafe fn context_switch() {

    current.arch.switch_to(&mut next.arch);
}

/// A context, which identifies either a process or a thread
#[derive(Debug)]
pub struct Context {
    /// The ID of this context
    pub id: usize,
    /// The architecture specific context
    pub arch: ArchContext,
    /// The open files in the scheme
    pub files: Vec<Option<file::File>>
}

impl Context {
    /// Create a new context
    pub fn new(id: usize) -> Context {
        Context {
            id: id,
            arch: ArchContext::new(),
            files: Vec::new()
        }
    }

    /// Add a file to the lowest available slot.
    /// Return the file descriptor number or None if no slot was found
    pub fn add_file(&mut self, file: file::File) -> Option<usize> {
        for (i, mut file_option) in self.files.iter_mut().enumerate() {
            if file_option.is_none() {
                *file_option = Some(file);
                return Some(i);
            }
        }
        let len = self.files.len();
        if len < CONTEXT_MAX_FILES {
            self.files.push(Some(file));
            Some(len)
        } else {
            None
        }
    }
}
<commit_msg>Fix the build. Sorry<commit_after>//! Context management

use collections::{BTreeMap, Vec};
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};

use arch::context::Context as ArchContext;
use syscall::{Error, Result};

/// File operations
pub mod file;

/// Limit on number of contexts
pub const CONTEXT_MAX_CONTEXTS: usize = 65536;

/// Maximum context files
pub const CONTEXT_MAX_FILES: usize = 65536;

/// Context list type
pub struct ContextList {
    map: BTreeMap<usize, RwLock<Context>>,
    next_id: usize
}

impl ContextList {
    pub fn new() -> Self {
        ContextList {
            map: BTreeMap::new(),
            next_id: 1
        }
    }

    pub fn get(&self, id: usize) -> Option<&RwLock<Context>> {
        self.map.get(&id)
    }

    pub fn current(&self) -> Option<&RwLock<Context>> {
        self.map.get(&CONTEXT_ID.load(Ordering::SeqCst))
    }

    pub fn new_context(&mut self) -> Result<&RwLock<Context>> {
        if self.next_id >= CONTEXT_MAX_CONTEXTS {
            self.next_id = 1;
        }

        while self.map.contains_key(&self.next_id) {
            self.next_id += 1;
        }

        if self.next_id >= CONTEXT_MAX_CONTEXTS {
            return Err(Error::TryAgain);
        }

        let id = self.next_id;
        self.next_id += 1;
        assert!(self.map.insert(id, RwLock::new(Context::new(id))).is_none());
        Ok(self.map.get(&id).expect("failed to insert new context"))
    }

    pub fn spawn(&mut self, func: extern fn()) -> Result<&RwLock<Context>> {
        let context_lock = self.new_context()?;
        {
            let mut context = context_lock.write();
            print!("{}", format!("{}: {:X}\n", context.id, func as usize));
        }
        Ok(context_lock)
    }
}

/// Contexts list
static CONTEXTS: Once<RwLock<ContextList>> = Once::new();

#[thread_local]
static CONTEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;

pub fn init() {
    let mut contexts = contexts_mut();
    let context_lock = contexts.new_context().expect("could not initialize first context");
    let context = context_lock.read();
    CONTEXT_ID.store(context.id, Ordering::SeqCst);
}

/// Initialize contexts, called if needed
fn init_contexts() -> RwLock<ContextList> {
    RwLock::new(ContextList::new())
}

/// Get the global schemes list, const
pub fn contexts() -> RwLockReadGuard<'static, ContextList> {
    CONTEXTS.call_once(init_contexts).read()
}

/// Get the global schemes list, mutable
pub fn contexts_mut() -> RwLockWriteGuard<'static, ContextList> {
    CONTEXTS.call_once(init_contexts).write()
}

/// Switch to the next context
/// Do not call this while holding locks!
pub unsafe fn context_switch() {
//    current.arch.switch_to(&mut next.arch);
}

/// A context, which identifies either a process or a thread
#[derive(Debug)]
pub struct Context {
    /// The ID of this context
    pub id: usize,
    /// The architecture specific context
    pub arch: ArchContext,
    /// The open files in the scheme
    pub files: Vec<Option<file::File>>
}

impl Context {
    /// Create a new context
    pub fn new(id: usize) -> Context {
        Context {
            id: id,
            arch: ArchContext::new(),
            files: Vec::new()
        }
    }

    /// Add a file to the lowest available slot.
    /// Return the file descriptor number or None if no slot was found
    pub fn add_file(&mut self, file: file::File) -> Option<usize> {
        for (i, mut file_option) in self.files.iter_mut().enumerate() {
            if file_option.is_none() {
                *file_option = Some(file);
                return Some(i);
            }
        }
        let len = self.files.len();
        if len < CONTEXT_MAX_FILES {
            self.files.push(Some(file));
            Some(len)
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>use alloc::boxed;
use alloc::boxed::Box;

use core::option::Option::{self, Some, None};

use super::concurrency::Atomic32;
use super::data_structures::Queue;

mod init;
mod current;
mod ready_queue;

// constants
const STACK_SIZE: usize = 2048;

// next pid
static NEXT_ID: Atomic32 = Atomic32 {i: 0};

// Process state
enum State {
    INIT,
    READY,
    RUNNING,
    BLOCKED,
    TERMINATED,
}

// A wrapper around stack pointers for use in initializing the stack
#[derive(Copy,Clone)]
struct StackPtr {
    ptr: *mut usize,
}

impl StackPtr {
    fn get_stack() -> StackPtr {
        // TODO: fudge
        // Allocate a stack
        let stack = Box::new([0; STACK_SIZE]);

        // set the pointer
        StackPtr {ptr: unsafe {boxed::into_raw(stack) as *mut usize} }
    }

    fn smash(&self) {
        // Get entry point of process
        let entry = start_proc as usize;

        // Smash the stack
        unsafe {
            for idx in (STACK_SIZE - 6)..STACK_SIZE {
                *self.ptr.offset(idx as isize) = 0;
            }
            *self.ptr.offset(-2) = entry;
        }
    }

    fn get_kesp(&self) -> StackPtr {
        // Create a new struct that contains the starting
        // kesp value for this stack
        StackPtr {ptr : (self.ptr as usize - 6) as *mut usize}
    }
}

// Process struct
pub struct Process {
    name: &'static str,
    pid: usize,
    run: fn(&Process) -> usize,
    state: State,
    stack: StackPtr,
    kesp: StackPtr,
}

impl Process {
    pub fn new(name: &'static str, run: fn(&Process) -> usize) -> Process {
        let stack = StackPtr::get_stack();
        stack.smash();

        Process {
            name: name,
            pid: NEXT_ID.get_then_add(),
            run: run,
            state: State::INIT,
            stack: stack,
            kesp: stack.get_kesp(),
        }
    }
}

pub fn init() {

    // Create the init process
    let mut init = Box::new(Process::new("init", self::init::run));

    // Create the ready q

    // Add the init process to the ready q

}

// The entry point of all processes
fn start_proc() {
    // get current process
    (*current::current()).run();
}

pub fn proc_yield(q: Option<Box<Queue<Box<Process>>>>) {//TODO: change to arbitrary list

}
<commit_msg>Implementing stuff<commit_after>use alloc::boxed;
use alloc::boxed::Box;

use core::option::Option::{self, Some, None};

use super::concurrency::Atomic32;
use super::data_structures::Queue;

mod init;
mod current;
mod ready_queue;

// constants
const STACK_SIZE: usize = 2048;

// next pid
static NEXT_ID: Atomic32 = Atomic32 {i: 0};

// Process state
enum State {
    INIT,
    READY,
    RUNNING,
    BLOCKED,
    TERMINATED,
}

// A wrapper around stack pointers for use in initializing the stack
#[derive(Copy,Clone)]
struct StackPtr {
    ptr: *mut usize,
}

impl StackPtr {
    fn get_stack() -> StackPtr {
        // TODO: fudge
        // Allocate a stack
        let stack = Box::new([0; STACK_SIZE]);

        // set the pointer
        StackPtr {ptr: unsafe {boxed::into_raw(stack) as *mut usize} }
    }

    fn smash(&self) {
        // Get entry point of process
        let entry = start_proc as usize;

        // Smash the stack
        unsafe {
            for idx in (STACK_SIZE - 6)..STACK_SIZE {
                *self.ptr.offset(idx as isize) = 0;
            }
            *self.ptr.offset(-2) = entry;
        }
    }

    fn get_kesp(&self) -> StackPtr {
        // Create a new struct that contains the starting
        // kesp value for this stack
        StackPtr {ptr : (self.ptr as usize - 6) as *mut usize}
    }
}

// Process struct
pub struct Process {
    name: &'static str,
    pid: usize,
    run: fn(&Process) -> usize,
    state: State,
    stack: StackPtr,
    kesp: StackPtr,
}

impl Process {
    pub fn new(name: &'static str, run: fn(&Process) -> usize) -> Process {
        let stack = StackPtr::get_stack();
        stack.smash();

        Process {
            name: name,
            pid: NEXT_ID.get_then_add(),
            run: run,
            state: State::INIT,
            stack: stack,
            kesp: stack.get_kesp(),
        }
    }

    pub fn dispatch(prev: Option<Box<Process>>) {
        //TODO
    }
}

pub fn init() {

    // Create the init process
    let mut init = Box::new(Process::new("init", self::init::run));

    // Create the ready q
    ready_queue::init();

    // Add the init process to the ready q
    ready_queue::make_ready(init);

}

// The entry point of all processes
fn start_proc() {
    // get current process
    let c_op = current::current();
    match c_op {
        Some(c_box) => {
            ((*c_box).run)(&*c_box);
        }
        None => {
            panic!("Start proc without current process");
        }
    }
}

pub fn proc_yield(q: Option<Box<Queue<Box<Process>>>>) {

}
<|endoftext|>


<commit_before>use std::sync::Arc;

use serde::{Serialize, Deserialize};
use tokio::sync::{RwLock, Mutex, MutexGuard};

use super::state::{TurtleState, DrawingState};
use super::renderer::display_list::PrimHandle;

/// The unique ID of a particular turtle
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct TurtleId(usize);

#[derive(Default, Debug)]
pub struct TurtleDrawings {
    pub state: TurtleState,
    pub drawings: Vec<PrimHandle>,
    /// If the turtle is currently filling, this is the handle to the fill polygon that new points
    /// should be appended to
    ///
    /// This handle will already be present in `drawings`, so it does not need to be added after
    /// the fill has begun.
    pub current_fill_polygon: Option<PrimHandle>,
}

/// The entire state of the application, shared between threads in the server
#[derive(Default, Debug)]
pub struct App {
    /// The current state of the drawing
    drawing: Mutex<DrawingState>,
    /// Each `TurtleId` indexes into this field
    ///
    /// Note that we have to be very careful deleting from this field since we don't want to
    /// invalidate any `TurtleId` or cloned `Arc<Mutex<TurtleDrawings>>`.
    ///
    /// The outer `RwLock` makes it possible to push into the `Vec` using `write` and also `clone`
    /// multiple items in the `Vec` at the same time using `read`.
    turtles: RwLock<Vec<Arc<Mutex<TurtleDrawings>>>>,
}

impl App {
    /// Adds a new turtle to the application state, returning its `TurtleId`
    pub async fn add_turtle(&self) -> TurtleId {
        let mut turtles = self.turtles.write().await;
        let id = TurtleId(turtles.len());
        turtles.push(Default::default());
        id
    }

    /// Returns a mutable handle to the drawing state
    pub async fn drawing_mut(&self) -> MutexGuard<'_, DrawingState> {
        self.drawing.lock().await
    }

    pub async fn turtles_len(&self) -> usize {
        self.turtles.read().await.len()
    }

    pub async fn turtle_ids(&self) -> impl Iterator<Item=TurtleId> + Clone {
        let len = self.turtles_len().await;
        (0..len).map(TurtleId)
    }

    /// Returns a handle to a the state and drawings of the given turtle
    pub async fn turtle(&self, id: TurtleId) -> Arc<Mutex<TurtleDrawings>> {
        let TurtleId(index) = id;
        let turtles = self.turtles.read().await;
        turtles[index].clone()
    }
}
<commit_msg>Adding and clarifying comments in app.rs<commit_after>use std::sync::Arc;

use serde::{Serialize, Deserialize};
use tokio::sync::{RwLock, Mutex, MutexGuard};

use super::state::{TurtleState, DrawingState};
use super::renderer::display_list::PrimHandle;

/// The unique ID of a particular turtle
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct TurtleId(usize);

#[derive(Default, Debug)]
pub struct TurtleDrawings {
    pub state: TurtleState,
    pub drawings: Vec<PrimHandle>,
    /// If the turtle is currently filling, this is the handle to the fill polygon that new points
    /// should be appended to
    ///
    /// This handle will already be present in `drawings`, so it does not need to be added after
    /// the fill has begun.
    pub current_fill_polygon: Option<PrimHandle>,
}

/// The entire state of the application, shared between threads in the server
#[derive(Default, Debug)]
pub struct App {
    /// The current state of the drawing
    drawing: Mutex<DrawingState>,
    /// Each `TurtleId` indexes into this field
    ///
    /// Need to be very careful deleting from this field because the `TurtleId` returned from
    /// `add_turtle()` must remain unique and thus can never be repeated. Also, we wouldn't want to
    /// invalidate any clones of the `Arc<Mutex<TurtleDrawings>>` returned from the `turtle()`
    /// method.
    ///
    /// The outer `RwLock` in this type makes it possible to 1) push into the `Vec` using `write()`
    /// and 2) `clone` multiple items in the `Vec` concurrently using `read()`.
    turtles: RwLock<Vec<Arc<Mutex<TurtleDrawings>>>>,
}

impl App {
    /// Adds a new turtle to the application state, returning its `TurtleId`
    pub async fn add_turtle(&self) -> TurtleId {
        let mut turtles = self.turtles.write().await;
        let id = TurtleId(turtles.len());
        turtles.push(Default::default());
        id
    }

    /// Returns a mutable handle to the drawing state
    pub async fn drawing_mut(&self) -> MutexGuard<'_, DrawingState> {
        self.drawing.lock().await
    }

    /// Returns the total number of turtles currently stored in the application state
    pub async fn turtles_len(&self) -> usize {
        self.turtles.read().await.len()
    }

    /// Returns the IDs of all turtles currently stored in the application state
    pub async fn turtle_ids(&self) -> impl Iterator<Item=TurtleId> + Clone {
        let len = self.turtles_len().await;
        (0..len).map(TurtleId)
    }

    /// Returns a handle to a the state and drawings of the given turtle
    ///
    /// The data is not locked, so multiple callers of this method may race to lock the data after
    /// the mutex is returned.
    pub async fn turtle(&self, id: TurtleId) -> Arc<Mutex<TurtleDrawings>> {
        let TurtleId(index) = id;
        let turtles = self.turtles.read().await;
        turtles[index].clone()
    }
}
<|endoftext|>


<commit_before>
use std::sync::Arc;
use std::collections::HashMap;
use std::borrow::Cow;
use parking_lot::RwLock;
use elements::{Internal, ValueType};
use interpreter::Error;
use interpreter::module::{ModuleInstanceInterface, ExecutionParams, ItemIndex,
	CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature};
use interpreter::memory::MemoryInstance;
use interpreter::table::TableInstance;
use interpreter::value::RuntimeValue;
use interpreter::variable::{VariableInstance, VariableType};

/// Min index of native function.
pub const NATIVE_INDEX_FUNC_MIN: u32 = 10001;
/// Min index of native global.
pub const NATIVE_INDEX_GLOBAL_MIN: u32 = 20001;

/// User functions executor.
pub trait UserFunctionExecutor {
	/// Execute function with given name.
	fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error>;
}

/// User function descriptor
#[derive(Debug, Clone)]
pub enum UserFunctionDescriptor {
	/// Static function definition
	Static(&'static str, &'static [ValueType], Option<ValueType>),
	/// Dynamic heap function definition
	Heap(String, Vec<ValueType>, Option<ValueType>),
}

impl UserFunctionDescriptor {
	/// New function with statically known params
	pub fn statik(name: &'static str, params: &'static [ValueType], result: Option<ValueType>) -> Self {
		UserFunctionDescriptor::Static(name, params, result)
	}

	/// New function with statically unknown params
	pub fn heap(name: String, params: Vec<ValueType>, result: Option<ValueType>) -> Self {
		UserFunctionDescriptor::Heap(name, params, result)
	}

	/// Name of the function
	pub fn name(&self) -> &str {
		match self {
			&UserFunctionDescriptor::Static(name, _, _) => name,
			&UserFunctionDescriptor::Heap(ref name, _, _) => name,
		}
	}

	/// Arguments of the function
	pub fn params(&self) -> &[ValueType] {
		match self {
			&UserFunctionDescriptor::Static(_, params, _) => params,
			&UserFunctionDescriptor::Heap(_, ref params, _) => params,
		}
	}

	/// Return type of the function
	pub fn return_type(&self) -> Option<ValueType> {
		match self {
			&UserFunctionDescriptor::Static(_, _, result) => result,
			&UserFunctionDescriptor::Heap(_, _, result) => result,
		}
	}
}

/// Set of user-defined module elements.
pub struct UserDefinedElements<'a> {
	/// User globals list.
	pub globals: HashMap<String, Arc<VariableInstance>>,
	/// User functions list.
	pub functions: Cow<'static, [UserFunctionDescriptor]>,
	/// Functions executor.
	pub executor: Option<&'a mut UserFunctionExecutor>,
}

/// Native module instance.
pub struct NativeModuleInstance<'a> {
	/// Underlying module reference.
	base: Arc<ModuleInstanceInterface>,
	/// User function executor.
	executor: RwLock<Option<&'a mut UserFunctionExecutor>>,
	/// By-name functions index.
	functions_by_name: HashMap<String, u32>,
	/// User functions list.
	functions: Cow<'static, [UserFunctionDescriptor]>,
	/// By-name functions index.
	globals_by_name: HashMap<String, u32>,
	/// User globals list.
	globals: Vec<Arc<VariableInstance>>,
}

impl<'a> NativeModuleInstance<'a> {
	/// Create new native module
	pub fn new(base: Arc<ModuleInstanceInterface>, elements: UserDefinedElements<'a>) -> Result<Self, Error> {
		if !elements.functions.is_empty() && elements.executor.is_none() {
			return Err(Error::Function("trying to construct native module with functions, but without executor".into()));
		}

		Ok(NativeModuleInstance {
			base: base,
			executor: RwLock::new(elements.executor),
			functions_by_name: elements.functions.iter().enumerate().map(|(i, f)| (f.name().to_owned(), i as u32)).collect(),
			functions: elements.functions,
			globals_by_name: elements.globals.iter().enumerate().map(|(i, (g_name, _))| (g_name.to_owned(), i as u32)).collect(),
			globals: elements.globals.into_iter().map(|(_, g)| g).collect(),
		})
	}
}

impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
	fn execute_index(&self, index: u32, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
		self.base.execute_index(index, params)
	}

	fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
		self.base.execute_export(name, params)
	}

	fn export_entry<'b>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error> {
		if let Some(index) = self.functions_by_name.get(name) {
			let composite_index = NATIVE_INDEX_FUNC_MIN + *index;
			match required_type {
				&ExportEntryType::Any => return Ok(Internal::Function(composite_index)),
				&ExportEntryType::Function(ref required_type) => {
					let actual_type = self.function_type(ItemIndex::Internal(composite_index))
						.expect(
							"by_name contains index; function_type succeeds for all functions from by_name; qed",
						);
					return if actual_type == *required_type {
						Ok(Internal::Function(composite_index))
					} else {
						Err(Error::Validation(format!(
							"Export function type {} mismatch. Expected function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
							index,
							required_type.params(),
							required_type.return_type(),
							actual_type.params(),
							actual_type.return_type()
						)))
					};
				}
				_ => (),
			}
		}
		if let Some(index) = self.globals_by_name.get(name) {
			let composite_index = NATIVE_INDEX_GLOBAL_MIN + *index;
			match required_type {
				&ExportEntryType::Any => {
					return Ok(Internal::Global(composite_index))
				}
				&ExportEntryType::Global(ref required_type) => {
					let actual_type = self.globals
						.get(*index as usize)
						.expect(
							"globals_by_name maps to indexes of globals; index read from globals_by_name; qed",
						)
						.variable_type();
					return if actual_type == *required_type {
						Ok(Internal::Global(composite_index))
					} else {
						Err(Error::Validation(format!(
							"Export global type {} mismatch. Expected type {:?} when got {:?}",
							index,
							required_type,
							actual_type
						)))
					};
				}
				_ => (),
			}
		}

		self.base.export_entry(name, required_type)
	}

	fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
		self.base.table(index)
	}

	fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
		self.base.memory(index)
	}

	fn global<'b>(&self, global_index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<Arc<VariableInstance>, Error> {
		let index = match global_index {
			ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
			ItemIndex::External(_) => unreachable!("trying to get global, exported by native module"),
		};

		if index < NATIVE_INDEX_GLOBAL_MIN {
			return self.base.global(global_index, variable_type, externals);
		}

		self.globals
			.get((index - NATIVE_INDEX_GLOBAL_MIN) as usize)
			.cloned()
			.ok_or(Error::Native(format!("trying to get native global with index {}", index)))
	}

	fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error> {
		let index = match function_index {
			ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
			ItemIndex::External(_) => unreachable!("trying to call function, exported by native module"),
		};

		if index < NATIVE_INDEX_FUNC_MIN || index >= NATIVE_INDEX_GLOBAL_MIN {
			return self.base.function_type(function_index);
		}

		Ok(FunctionSignature::User(self.functions
			.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
			.ok_or(Error::Native(format!("missing native function with index {}", index)))?))
	}

	fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error> {
		self.function_type(ItemIndex::Internal(type_index))
	}

	fn function_reference<'b>(&self, index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
		self.base.function_reference(index, externals)
	}

	fn function_reference_indirect<'b>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
		self.base.function_reference_indirect(table_idx, type_idx, func_idx, externals)
	}

	fn function_body<'b>(&'b self, _internal_index: u32) -> Result<Option<InternalFunction<'b>>, Error> {
		Ok(None)
	}

	fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
		if index < NATIVE_INDEX_FUNC_MIN || index >= NATIVE_INDEX_GLOBAL_MIN {
			return self.base.call_internal_function(outer, index);
		}

		self.functions
			.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
			.ok_or(Error::Native(format!("trying to call native function with index {}", index)).into())
			.and_then(|f| self.executor.write()
				.as_mut()
				.expect("function exists; if function exists, executor must also exists [checked in constructor]; qed")
				.execute(&f.name(), outer))
	}
}

/// Create wrapper for a module with given native user functions .
///
/// # Examples
///
/// ```rust
/// use parity_wasm::interpreter::{CallerContext, Error, ExecutionParams, ExportEntryType,
///                                FunctionSignature, ItemIndex, ModuleInstance,
///                                ModuleInstanceInterface, ProgramInstance, RuntimeValue,
///                                UserDefinedElements, UserError, UserFunctionDescriptor,
///                                UserFunctionExecutor};
///
/// struct MyExecutor;
///
/// impl UserFunctionExecutor for MyExecutor {
///     fn execute(
///         &mut self,
///         name: &str,
///         context: CallerContext,
///     ) -> Result<Option<RuntimeValue>, Error> {
///         match name {
///             "add" => {
///                 // fn add(a: u32, b: u32) -> u32
///                 let b = context.value_stack.pop_as::<u32>()? as u32;
///                 let a = context.value_stack.pop_as::<u32>()? as u32;
///                 let sum = a + b;
///                 Ok(Some(RuntimeValue::I32(sum as i32)))
///             }
///             _ => Err(Error::Trap("not implemented".into()).into()),
///         }
///     }
/// }
/// ```
pub fn native_module<'a>(base: Arc<ModuleInstanceInterface>, user_elements: UserDefinedElements<'a>) -> Result<NativeModuleInstance, Error> {
	NativeModuleInstance::new(base, user_elements)
}

impl<'a> PartialEq for UserFunctionDescriptor {
	fn eq(&self, other: &Self) -> bool {
		self.params() == other.params()
			&& self.return_type() == other.return_type()
	}
}
<commit_msg>Doc fix<commit_after>
use std::sync::Arc;
use std::collections::HashMap;
use std::borrow::Cow;
use parking_lot::RwLock;
use elements::{Internal, ValueType};
use interpreter::Error;
use interpreter::module::{ModuleInstanceInterface, ExecutionParams, ItemIndex,
	CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature};
use interpreter::memory::MemoryInstance;
use interpreter::table::TableInstance;
use interpreter::value::RuntimeValue;
use interpreter::variable::{VariableInstance, VariableType};

/// Min index of native function.
pub const NATIVE_INDEX_FUNC_MIN: u32 = 10001;
/// Min index of native global.
pub const NATIVE_INDEX_GLOBAL_MIN: u32 = 20001;

/// User functions executor.
pub trait UserFunctionExecutor {
	/// Execute function with given name.
	fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error>;
}

/// User function descriptor
#[derive(Debug, Clone)]
pub enum UserFunctionDescriptor {
	/// Static function definition
	Static(&'static str, &'static [ValueType], Option<ValueType>),
	/// Dynamic heap function definition
	Heap(String, Vec<ValueType>, Option<ValueType>),
}

impl UserFunctionDescriptor {
	/// New function with statically known params
	pub fn statik(name: &'static str, params: &'static [ValueType], result: Option<ValueType>) -> Self {
		UserFunctionDescriptor::Static(name, params, result)
	}

	/// New function with statically unknown params
	pub fn heap(name: String, params: Vec<ValueType>, result: Option<ValueType>) -> Self {
		UserFunctionDescriptor::Heap(name, params, result)
	}

	/// Name of the function
	pub fn name(&self) -> &str {
		match self {
			&UserFunctionDescriptor::Static(name, _, _) => name,
			&UserFunctionDescriptor::Heap(ref name, _, _) => name,
		}
	}

	/// Arguments of the function
	pub fn params(&self) -> &[ValueType] {
		match self {
			&UserFunctionDescriptor::Static(_, params, _) => params,
			&UserFunctionDescriptor::Heap(_, ref params, _) => params,
		}
	}

	/// Return type of the function
	pub fn return_type(&self) -> Option<ValueType> {
		match self {
			&UserFunctionDescriptor::Static(_, _, result) => result,
			&UserFunctionDescriptor::Heap(_, _, result) => result,
		}
	}
}

/// Set of user-defined module elements.
pub struct UserDefinedElements<'a> {
	/// User globals list.
	pub globals: HashMap<String, Arc<VariableInstance>>,
	/// User functions list.
	pub functions: Cow<'static, [UserFunctionDescriptor]>,
	/// Functions executor.
	pub executor: Option<&'a mut UserFunctionExecutor>,
}

/// Native module instance.
pub struct NativeModuleInstance<'a> {
	/// Underlying module reference.
	base: Arc<ModuleInstanceInterface>,
	/// User function executor.
	executor: RwLock<Option<&'a mut UserFunctionExecutor>>,
	/// By-name functions index.
	functions_by_name: HashMap<String, u32>,
	/// User functions list.
	functions: Cow<'static, [UserFunctionDescriptor]>,
	/// By-name functions index.
	globals_by_name: HashMap<String, u32>,
	/// User globals list.
	globals: Vec<Arc<VariableInstance>>,
}

impl<'a> NativeModuleInstance<'a> {
	/// Create new native module
	pub fn new(base: Arc<ModuleInstanceInterface>, elements: UserDefinedElements<'a>) -> Result<Self, Error> {
		if !elements.functions.is_empty() && elements.executor.is_none() {
			return Err(Error::Function("trying to construct native module with functions, but without executor".into()));
		}

		Ok(NativeModuleInstance {
			base: base,
			executor: RwLock::new(elements.executor),
			functions_by_name: elements.functions.iter().enumerate().map(|(i, f)| (f.name().to_owned(), i as u32)).collect(),
			functions: elements.functions,
			globals_by_name: elements.globals.iter().enumerate().map(|(i, (g_name, _))| (g_name.to_owned(), i as u32)).collect(),
			globals: elements.globals.into_iter().map(|(_, g)| g).collect(),
		})
	}
}

impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
	fn execute_index(&self, index: u32, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
		self.base.execute_index(index, params)
	}

	fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
		self.base.execute_export(name, params)
	}

	fn export_entry<'b>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error> {
		if let Some(index) = self.functions_by_name.get(name) {
			let composite_index = NATIVE_INDEX_FUNC_MIN + *index;
			match required_type {
				&ExportEntryType::Any => return Ok(Internal::Function(composite_index)),
				&ExportEntryType::Function(ref required_type) => {
					let actual_type = self.function_type(ItemIndex::Internal(composite_index))
						.expect(
							"by_name contains index; function_type succeeds for all functions from by_name; qed",
						);
					return if actual_type == *required_type {
						Ok(Internal::Function(composite_index))
					} else {
						Err(Error::Validation(format!(
							"Export function type {} mismatch. Expected function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
							index,
							required_type.params(),
							required_type.return_type(),
							actual_type.params(),
							actual_type.return_type()
						)))
					};
				}
				_ => (),
			}
		}
		if let Some(index) = self.globals_by_name.get(name) {
			let composite_index = NATIVE_INDEX_GLOBAL_MIN + *index;
			match required_type {
				&ExportEntryType::Any => {
					return Ok(Internal::Global(composite_index))
				}
				&ExportEntryType::Global(ref required_type) => {
					let actual_type = self.globals
						.get(*index as usize)
						.expect(
							"globals_by_name maps to indexes of globals; index read from globals_by_name; qed",
						)
						.variable_type();
					return if actual_type == *required_type {
						Ok(Internal::Global(composite_index))
					} else {
						Err(Error::Validation(format!(
							"Export global type {} mismatch. Expected type {:?} when got {:?}",
							index,
							required_type,
							actual_type
						)))
					};
				}
				_ => (),
			}
		}

		self.base.export_entry(name, required_type)
	}

	fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
		self.base.table(index)
	}

	fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
		self.base.memory(index)
	}

	fn global<'b>(&self, global_index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<Arc<VariableInstance>, Error> {
		let index = match global_index {
			ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
			ItemIndex::External(_) => unreachable!("trying to get global, exported by native module"),
		};

		if index < NATIVE_INDEX_GLOBAL_MIN {
			return self.base.global(global_index, variable_type, externals);
		}

		self.globals
			.get((index - NATIVE_INDEX_GLOBAL_MIN) as usize)
			.cloned()
			.ok_or(Error::Native(format!("trying to get native global with index {}", index)))
	}

	fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error> {
		let index = match function_index {
			ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
			ItemIndex::External(_) => unreachable!("trying to call function, exported by native module"),
		};

		if index < NATIVE_INDEX_FUNC_MIN || index >= NATIVE_INDEX_GLOBAL_MIN {
			return self.base.function_type(function_index);
		}

		Ok(FunctionSignature::User(self.functions
			.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
			.ok_or(Error::Native(format!("missing native function with index {}", index)))?))
	}

	fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error> {
		self.function_type(ItemIndex::Internal(type_index))
	}

	fn function_reference<'b>(&self, index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
		self.base.function_reference(index, externals)
	}

	fn function_reference_indirect<'b>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
		self.base.function_reference_indirect(table_idx, type_idx, func_idx, externals)
	}

	fn function_body<'b>(&'b self, _internal_index: u32) -> Result<Option<InternalFunction<'b>>, Error> {
		Ok(None)
	}

	fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
		if index < NATIVE_INDEX_FUNC_MIN || index >= NATIVE_INDEX_GLOBAL_MIN {
			return self.base.call_internal_function(outer, index);
		}

		self.functions
			.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
			.ok_or(Error::Native(format!("trying to call native function with index {}", index)).into())
			.and_then(|f| self.executor.write()
				.as_mut()
				.expect("function exists; if function exists, executor must also exists [checked in constructor]; qed")
				.execute(&f.name(), outer))
	}
}

/// Create wrapper for a module with given native user functions.
///
/// # Examples
///
/// ```rust
/// use parity_wasm::interpreter::{CallerContext, Error, ExecutionParams, ExportEntryType,
///                                FunctionSignature, ItemIndex, ModuleInstance,
///                                ModuleInstanceInterface, ProgramInstance, RuntimeValue,
///                                UserDefinedElements, UserError, UserFunctionDescriptor,
///                                UserFunctionExecutor};
///
/// struct MyExecutor;
///
/// impl UserFunctionExecutor for MyExecutor {
///     fn execute(
///         &mut self,
///         name: &str,
///         context: CallerContext,
///     ) -> Result<Option<RuntimeValue>, Error> {
///         match name {
///             "add" => {
///                 // fn add(a: u32, b: u32) -> u32
///                 let b = context.value_stack.pop_as::<u32>()? as u32;
///                 let a = context.value_stack.pop_as::<u32>()? as u32;
///                 let sum = a + b;
///                 Ok(Some(RuntimeValue::I32(sum as i32)))
///             }
///             _ => Err(Error::Trap("not implemented".into()).into()),
///         }
///     }
/// }
/// ```
pub fn native_module<'a>(base: Arc<ModuleInstanceInterface>, user_elements: UserDefinedElements<'a>) -> Result<NativeModuleInstance, Error> {
	NativeModuleInstance::new(base, user_elements)
}

impl<'a> PartialEq for UserFunctionDescriptor {
	fn eq(&self, other: &Self) -> bool {
		self.params() == other.params()
			&& self.return_type() == other.return_type()
	}
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::io::Write;

use backend::Backend;
use deserialize::{self, FromSql, FromSqlRow, Queryable};
use serialize::{self, IsNull, Output, ToSql};
use sql_types::{self, BigInt, Binary, Bool, Double, Float, Integer, NotNull, SmallInt, Text};

#[allow(dead_code)]
mod foreign_impls {
    use super::*;

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Bool"]
    struct BoolProxy(bool);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[cfg_attr(feature = "mysql", sql_type = "::sql_types::Tinyint")]
    struct I8Proxy(i8);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "SmallInt"]
    struct I16Proxy(i16);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Integer"]
    struct I32Proxy(i32);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "BigInt"]
    struct I64Proxy(i64);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[cfg_attr(feature = "postgres", sql_type = "::sql_types::Oid")]
    struct U32Proxy(u32);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Float"]
    struct F32Proxy(f32);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Double"]
    struct F64Proxy(f64);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Text"]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Date")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Time")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Timestamp")]
    struct StringProxy(String);

    #[derive(AsExpression)]
    #[diesel(foreign_derive, not_sized)]
    #[sql_type = "Text"]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Date")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Time")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Timestamp")]
    struct StrProxy(str);

    #[derive(FromSqlRow)]
    #[diesel(foreign_derive)]
    struct VecProxy<T>(Vec<T>);

    #[derive(AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Binary"]
    struct BinaryVecProxy(Vec<u8>);

    #[derive(AsExpression)]
    #[diesel(foreign_derive, not_sized)]
    #[sql_type = "Binary"]
    struct BinarySliceProxy([u8]);
}

impl NotNull for () {}

impl<ST, DB> FromSql<ST, DB> for String
where
    DB: Backend,
    *const str: FromSql<ST, DB>,
{
    fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
        let str_ptr = <*const str as FromSql<ST, DB>>::from_sql(bytes)?;
        // We know that the pointer impl will never return null
        let string = unsafe { &*str_ptr };
        Ok(string.to_owned())
    }
}

/// The returned pointer is *only* valid for the lifetime to the argument of
/// `from_sql`. This impl is intended for uses where you want to write a new
/// impl in terms of `String`, but don't want to allocate. We have to return a
/// raw pointer instead of a reference with a lifetime due to the structure of
/// `FromSql`
impl<DB: Backend<RawValue = [u8]>> FromSql<sql_types::Text, DB> for *const str {
    fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
        use std::str;
        let string = str::from_utf8(not_none!(bytes))?;
        Ok(string as *const _)
    }
}

impl<DB: Backend> ToSql<sql_types::Text, DB> for str {
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        out.write_all(self.as_bytes())
            .map(|_| IsNull::No)
            .map_err(|e| Box::new(e) as Box<Error + Send + Sync>)
    }
}

impl<DB> ToSql<sql_types::Text, DB> for String
where
    DB: Backend,
    str: ToSql<sql_types::Text, DB>,
{
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        (self as &str).to_sql(out)
    }
}

impl<ST, DB> FromSql<ST, DB> for Vec<u8>
where
    DB: Backend,
    *const [u8]: FromSql<ST, DB>,
{
    fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
        let slice_ptr = <*const [u8] as FromSql<ST, DB>>::from_sql(bytes)?;
        // We know that the pointer impl will never return null
        let bytes = unsafe { &*slice_ptr };
        Ok(bytes.to_owned())
    }
}

/// The returned pointer is *only* valid for the lifetime to the argument of
/// `from_sql`. This impl is intended for uses where you want to write a new
/// impl in terms of `Vec<u8>`, but don't want to allocate. We have to return a
/// raw pointer instead of a reference with a lifetime due to the structure of
/// `FromSql`
impl<DB: Backend<RawValue = [u8]>> FromSql<sql_types::Binary, DB> for *const [u8] {
    fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
        Ok(not_none!(bytes) as *const _)
    }
}

impl<DB> ToSql<sql_types::Binary, DB> for Vec<u8>
where
    DB: Backend,
    [u8]: ToSql<sql_types::Binary, DB>,
{
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        (self as &[u8]).to_sql(out)
    }
}

impl<DB: Backend> ToSql<sql_types::Binary, DB> for [u8] {
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        out.write_all(self)
            .map(|_| IsNull::No)
            .map_err(|e| Box::new(e) as Box<Error + Send + Sync>)
    }
}

use std::borrow::{Cow, ToOwned};
impl<'a, T: ?Sized, ST, DB> ToSql<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned + ToSql<ST, DB>,
    DB: Backend,
    T::Owned: ToSql<ST, DB>,
{
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        match *self {
            Cow::Borrowed(t) => t.to_sql(out),
            Cow::Owned(ref t) => t.to_sql(out),
        }
    }
}

impl<'a, T: ?Sized, ST, DB> FromSql<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned,
    DB: Backend,
    T::Owned: FromSql<ST, DB>,
{
    fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
        T::Owned::from_sql(bytes).map(Cow::Owned)
    }
}

impl<'a, T: ?Sized, ST, DB> FromSqlRow<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned,
    DB: Backend,
    Cow<'a, T>: FromSql<ST, DB>,
{
    fn build_from_row<R: ::row::Row<DB>>(row: &mut R) -> deserialize::Result<Self> {
        FromSql::<ST, DB>::from_sql(row.take())
    }
}

impl<'a, T: ?Sized, ST, DB> Queryable<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned,
    DB: Backend,
    Self: FromSqlRow<ST, DB>,
{
    type Row = Self;

    fn build(row: Self::Row) -> Self {
        row
    }
}

use expression::bound::Bound;
use expression::{AsExpression, Expression};

impl<'a, T: ?Sized, ST> AsExpression<ST> for Cow<'a, T>
where
    T: 'a + ToOwned,
    Bound<ST, Cow<'a, T>>: Expression<SqlType = ST>,
{
    type Expression = Bound<ST, Self>;

    fn as_expression(self) -> Self::Expression {
        Bound::new(self)
    }
}

impl<'a, 'b, T: ?Sized, ST> AsExpression<ST> for &'b Cow<'a, T>
where
    T: 'a + ToOwned,
    Bound<ST, &'b T>: Expression<SqlType = ST>,
{
    type Expression = Bound<ST, &'b T>;

    fn as_expression(self) -> Self::Expression {
        Bound::new(&**self)
    }
}
<commit_msg>Remove ToSql impl for Cow (#1499)<commit_after>use std::error::Error;
use std::io::Write;

use backend::Backend;
use deserialize::{self, FromSql, FromSqlRow, Queryable};
use serialize::{self, IsNull, Output, ToSql};
use sql_types::{self, BigInt, Binary, Bool, Double, Float, Integer, NotNull, SmallInt, Text};

#[allow(dead_code)]
mod foreign_impls {
    use super::*;

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Bool"]
    struct BoolProxy(bool);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[cfg_attr(feature = "mysql", sql_type = "::sql_types::Tinyint")]
    struct I8Proxy(i8);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "SmallInt"]
    struct I16Proxy(i16);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Integer"]
    struct I32Proxy(i32);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "BigInt"]
    struct I64Proxy(i64);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[cfg_attr(feature = "postgres", sql_type = "::sql_types::Oid")]
    struct U32Proxy(u32);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Float"]
    struct F32Proxy(f32);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Double"]
    struct F64Proxy(f64);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Text"]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Date")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Time")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Timestamp")]
    struct StringProxy(String);

    #[derive(AsExpression)]
    #[diesel(foreign_derive, not_sized)]
    #[sql_type = "Text"]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Date")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Time")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Timestamp")]
    struct StrProxy(str);

    #[derive(FromSqlRow)]
    #[diesel(foreign_derive)]
    struct VecProxy<T>(Vec<T>);

    #[derive(AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Binary"]
    struct BinaryVecProxy(Vec<u8>);

    #[derive(AsExpression)]
    #[diesel(foreign_derive, not_sized)]
    #[sql_type = "Binary"]
    struct BinarySliceProxy([u8]);
}

impl NotNull for () {}

impl<ST, DB> FromSql<ST, DB> for String
where
    DB: Backend,
    *const str: FromSql<ST, DB>,
{
    fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
        let str_ptr = <*const str as FromSql<ST, DB>>::from_sql(bytes)?;
        // We know that the pointer impl will never return null
        let string = unsafe { &*str_ptr };
        Ok(string.to_owned())
    }
}

/// The returned pointer is *only* valid for the lifetime to the argument of
/// `from_sql`. This impl is intended for uses where you want to write a new
/// impl in terms of `String`, but don't want to allocate. We have to return a
/// raw pointer instead of a reference with a lifetime due to the structure of
/// `FromSql`
impl<DB: Backend<RawValue = [u8]>> FromSql<sql_types::Text, DB> for *const str {
    fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
        use std::str;
        let string = str::from_utf8(not_none!(bytes))?;
        Ok(string as *const _)
    }
}

impl<DB: Backend> ToSql<sql_types::Text, DB> for str {
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        out.write_all(self.as_bytes())
            .map(|_| IsNull::No)
            .map_err(|e| Box::new(e) as Box<Error + Send + Sync>)
    }
}

impl<DB> ToSql<sql_types::Text, DB> for String
where
    DB: Backend,
    str: ToSql<sql_types::Text, DB>,
{
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        (self as &str).to_sql(out)
    }
}

impl<ST, DB> FromSql<ST, DB> for Vec<u8>
where
    DB: Backend,
    *const [u8]: FromSql<ST, DB>,
{
    fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
        let slice_ptr = <*const [u8] as FromSql<ST, DB>>::from_sql(bytes)?;
        // We know that the pointer impl will never return null
        let bytes = unsafe { &*slice_ptr };
        Ok(bytes.to_owned())
    }
}

/// The returned pointer is *only* valid for the lifetime to the argument of
/// `from_sql`. This impl is intended for uses where you want to write a new
/// impl in terms of `Vec<u8>`, but don't want to allocate. We have to return a
/// raw pointer instead of a reference with a lifetime due to the structure of
/// `FromSql`
impl<DB: Backend<RawValue = [u8]>> FromSql<sql_types::Binary, DB> for *const [u8] {
    fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
        Ok(not_none!(bytes) as *const _)
    }
}

impl<DB> ToSql<sql_types::Binary, DB> for Vec<u8>
where
    DB: Backend,
    [u8]: ToSql<sql_types::Binary, DB>,
{
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        (self as &[u8]).to_sql(out)
    }
}

impl<DB: Backend> ToSql<sql_types::Binary, DB> for [u8] {
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        out.write_all(self)
            .map(|_| IsNull::No)
            .map_err(|e| Box::new(e) as Box<Error + Send + Sync>)
    }
}

use std::borrow::{Cow, ToOwned};
use std::fmt;
impl<'a, T: ?Sized, ST, DB> ToSql<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned + ToSql<ST, DB>,
    DB: Backend,
    Self: fmt::Debug,
{
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        ToSql::<ST, DB>::to_sql(&**self, out)
    }
}

impl<'a, T: ?Sized, ST, DB> FromSql<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned,
    DB: Backend,
    T::Owned: FromSql<ST, DB>,
{
    fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
        T::Owned::from_sql(bytes).map(Cow::Owned)
    }
}

impl<'a, T: ?Sized, ST, DB> FromSqlRow<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned,
    DB: Backend,
    Cow<'a, T>: FromSql<ST, DB>,
{
    fn build_from_row<R: ::row::Row<DB>>(row: &mut R) -> deserialize::Result<Self> {
        FromSql::<ST, DB>::from_sql(row.take())
    }
}

impl<'a, T: ?Sized, ST, DB> Queryable<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned,
    DB: Backend,
    Self: FromSqlRow<ST, DB>,
{
    type Row = Self;

    fn build(row: Self::Row) -> Self {
        row
    }
}

use expression::bound::Bound;
use expression::{AsExpression, Expression};

impl<'a, T: ?Sized, ST> AsExpression<ST> for Cow<'a, T>
where
    T: 'a + ToOwned,
    Bound<ST, Cow<'a, T>>: Expression<SqlType = ST>,
{
    type Expression = Bound<ST, Self>;

    fn as_expression(self) -> Self::Expression {
        Bound::new(self)
    }
}

impl<'a, 'b, T: ?Sized, ST> AsExpression<ST> for &'b Cow<'a, T>
where
    T: 'a + ToOwned,
    Bound<ST, &'b T>: Expression<SqlType = ST>,
{
    type Expression = Bound<ST, &'b T>;

    fn as_expression(self) -> Self::Expression {
        Bound::new(&**self)
    }
}
<|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 http://mozilla.org/MPL/2.0/. */

//! A struct to encapsulate all the style fixups a computed style needs in order
//! for it to adhere to the CSS spec.

use app_units::Au;
use properties::{self, CascadeFlags, ComputedValues};
use properties::{SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, StyleBuilder};
#[cfg(feature = "gecko")]
use properties::PROHIBIT_DISPLAY_CONTENTS;
use properties::longhands::display::computed_value::T as display;
use properties::longhands::float::computed_value::T as float;
use properties::longhands::overflow_x::computed_value::T as overflow;
use properties::longhands::position::computed_value::T as position;

/// An unsized struct that implements all the adjustment methods.
pub struct StyleAdjuster<'a, 'b: 'a> {
    style: &'a mut StyleBuilder<'b>,
    is_root_element: bool,
}

impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
    /// Trivially constructs a new StyleAdjuster.
    pub fn new(style: &'a mut StyleBuilder<'b>, is_root_element: bool) -> Self {
        StyleAdjuster {
            style: style,
            is_root_element: is_root_element,
        }
    }

    /// https://fullscreen.spec.whatwg.org/#new-stacking-layer
    ///
    ///    Any position value other than 'absolute' and 'fixed' are
    ///    computed to 'absolute' if the element is in a top layer.
    ///
    fn adjust_for_top_layer(&mut self) {
        if !self.style.out_of_flow_positioned() && self.style.in_top_layer() {
            self.style.mutate_box().set_position(position::absolute);
        }
    }

    /// CSS 2.1 section 9.7:
    ///
    ///    If 'position' has the value 'absolute' or 'fixed', [...] the computed
    ///    value of 'float' is 'none'.
    ///
    fn adjust_for_position(&mut self) {
        if self.style.out_of_flow_positioned() && self.style.floated() {
            self.style.mutate_box().set_float(float::none);
        }
    }

    /// Apply the blockification rules based on the table in CSS 2.2 section 9.7.
    /// https://drafts.csswg.org/css2/visuren.html#dis-pos-flo
    fn blockify_if_necessary(&mut self,
                             layout_parent_style: &ComputedValues,
                             flags: CascadeFlags) {
        let mut blockify = false;
        macro_rules! blockify_if {
            ($if_what:expr) => {
                if !blockify {
                    blockify = $if_what;
                }
            }
        }

        if !flags.contains(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP) {
            blockify_if!(self.is_root_element);
            blockify_if!(layout_parent_style.get_box().clone_display().is_item_container());
        }

        let is_item_or_root = blockify;

        blockify_if!(self.style.floated());
        blockify_if!(self.style.out_of_flow_positioned());

        if !blockify {
            return;
        }

        let display = self.style.get_box().clone_display();
        let blockified_display =
            display.equivalent_block_display(self.is_root_element);
        if display != blockified_display {
            self.style.mutate_box().set_adjusted_display(blockified_display,
                                                         is_item_or_root);
        }
    }

    /// Adjust the style for text style.
    ///
    /// The adjustments here are a subset of the adjustments generally, because
    /// text only inherits properties.
    ///
    /// Note that this, for Gecko, comes through Servo_ComputedValues_Inherit.
    #[cfg(feature = "gecko")]
    pub fn adjust_for_text(&mut self) {
        self.adjust_for_text_combine_upright();
    }

    /// Change writing mode of the text frame for text-combine-upright.
    ///
    /// It is safe to look at our own style because we are looking at inherited
    /// properties, and text is just plain inheritance.
    ///
    /// TODO(emilio): we should (Gecko too) revise these adjustments in presence
    /// of display: contents.
    #[cfg(feature = "gecko")]
    fn adjust_for_text_combine_upright(&mut self) {
        use computed_values::text_combine_upright::T as text_combine_upright;
        use computed_values::writing_mode::T as writing_mode;

        let writing_mode =
            self.style.get_inheritedbox().clone_writing_mode();
        let text_combine_upright =
            self.style.get_inheritedtext().clone_text_combine_upright();

        if writing_mode != writing_mode::horizontal_tb &&
           text_combine_upright == text_combine_upright::all {
            self.style.mutate_inheritedbox().set_writing_mode(writing_mode::horizontal_tb);
        }
    }

    /// https://drafts.csswg.org/css-writing-modes-3/#block-flow:
    ///
    ///    If a box has a different writing-mode value than its containing
    ///    block:
    ///
    ///        - If the box has a specified display of inline, its display
    ///          computes to inline-block. [CSS21]
    ///
    /// This matches the adjustment that Gecko does, not exactly following
    /// the spec. See also:
    ///
    /// https://lists.w3.org/Archives/Public/www-style/2017Mar/0045.html
    /// https://github.com/servo/servo/issues/15754
    fn adjust_for_writing_mode(&mut self,
                               layout_parent_style: &ComputedValues) {
        let our_writing_mode = self.style.get_inheritedbox().clone_writing_mode();
        let parent_writing_mode = layout_parent_style.get_inheritedbox().clone_writing_mode();

        if our_writing_mode != parent_writing_mode &&
           self.style.get_box().clone_display() == display::inline {
            self.style.mutate_box().set_display(display::inline_block);
        }
    }

    #[cfg(feature = "gecko")]
    fn adjust_for_contain(&mut self) {
        use properties::longhands::contain;

        // An element with contain: paint needs to be a formatting context, and
        // also implies overflow: clip.
        //
        // TODO(emilio): This mimics Gecko, but spec links are missing!
        let contain = self.style.get_box().clone_contain();
        if !contain.contains(contain::PAINT) {
            return;
        }

        if self.style.get_box().clone_display() == display::inline {
            self.style.mutate_box().set_adjusted_display(display::inline_block,
                                                         false);
        }

        // When 'contain: paint', update overflow from 'visible' to 'clip'.
        if self.style.get_box().clone_contain().contains(contain::PAINT) {
            if self.style.get_box().clone_overflow_x() == overflow::visible {
                let mut box_style = self.style.mutate_box();
                box_style.set_overflow_x(overflow::_moz_hidden_unscrollable);
                box_style.set_overflow_y(overflow::_moz_hidden_unscrollable);
            }
        }
    }

    /// When mathvariant is not "none", font-weight and font-style are
    /// both forced to "normal".
    #[cfg(feature = "gecko")]
    fn adjust_for_mathvariant(&mut self) {
        use properties::longhands::_moz_math_variant::computed_value::T as moz_math_variant;
        use properties::longhands::font_style::computed_value::T as font_style;
        use properties::longhands::font_weight::computed_value::T as font_weight;
        if self.style.get_font().clone__moz_math_variant() != moz_math_variant::none {
            let mut font_style = self.style.mutate_font();
            // Sadly we don't have a nice name for the computed value
            // of "font-weight: normal".
            font_style.set_font_weight(font_weight::Weight400);
            font_style.set_font_style(font_style::normal);
        }
    }

    /// This implements an out-of-date spec. The new spec moves the handling of
    /// this to layout, which Gecko implements but Servo doesn't.
    ///
    /// See https://github.com/servo/servo/issues/15229
    #[cfg(feature = "servo")]
    fn adjust_for_alignment(&mut self, layout_parent_style: &ComputedValues) {
        use computed_values::align_items::T as align_items;
        use computed_values::align_self::T as align_self;

        if self.style.get_position().clone_align_self() == align_self::auto &&
           !self.style.out_of_flow_positioned() {
            let self_align =
                match layout_parent_style.get_position().clone_align_items() {
                    align_items::stretch => align_self::stretch,
                    align_items::baseline => align_self::baseline,
                    align_items::flex_start => align_self::flex_start,
                    align_items::flex_end => align_self::flex_end,
                    align_items::center => align_self::center,
                };
            self.style.mutate_position().set_align_self(self_align);
        }
    }

    /// The initial value of border-*-width may be changed at computed value
    /// time.
    ///
    /// This is moved to properties.rs for convenience.
    fn adjust_for_border_width(&mut self) {
        properties::adjust_border_width(self.style);
    }

    /// The initial value of outline-width may be changed at computed value time.
    fn adjust_for_outline(&mut self) {
        if self.style.get_outline().clone_outline_style().none_or_hidden() &&
           self.style.get_outline().outline_has_nonzero_width() {
            self.style.mutate_outline().set_outline_width(Au(0));
        }
    }

    /// CSS3 overflow-x and overflow-y require some fixup as well in some
    /// cases.
    ///
    /// overflow: clip and overflow: visible are meaningful only when used in
    /// both dimensions.
    fn adjust_for_overflow(&mut self) {
        let original_overflow_x = self.style.get_box().clone_overflow_x();
        let original_overflow_y = self.style.get_box().clone_overflow_y();

        let mut overflow_x = original_overflow_x;
        let mut overflow_y = original_overflow_y;

        if overflow_x == overflow_y {
            return;
        }

        // If 'visible' is specified but doesn't match the other dimension,
        // it turns into 'auto'.
        if overflow_x == overflow::visible {
            overflow_x = overflow::auto;
        }

        if overflow_y == overflow::visible {
            overflow_y = overflow::auto;
        }

        #[cfg(feature = "gecko")]
        {
            // overflow: clip is deprecated, so convert to hidden if it's
            // specified in only one dimension.
            if overflow_x == overflow::_moz_hidden_unscrollable {
                overflow_x = overflow::hidden;
            }
            if overflow_y == overflow::_moz_hidden_unscrollable {
                overflow_y = overflow::hidden;
            }
        }

        if overflow_x != original_overflow_x ||
           overflow_y != original_overflow_y {
            let mut box_style = self.style.mutate_box();
            box_style.set_overflow_x(overflow_x);
            box_style.set_overflow_y(overflow_y);
        }
    }

    /// Native anonymous content converts display:contents into display:inline.
    #[cfg(feature = "gecko")]
    fn adjust_for_prohibited_display_contents(&mut self, flags: CascadeFlags) {
        // TODO: We should probably convert display:contents into display:none
        // in some cases too: https://drafts.csswg.org/css-display/#unbox
        if !flags.contains(PROHIBIT_DISPLAY_CONTENTS) ||
           self.style.get_box().clone_display() != display::contents {
            return;
        }

        self.style.mutate_box().set_display(display::inline);
    }

    /// -moz-center, -moz-left and -moz-right are used for HTML's alignment.
    ///
    /// This is covering the

...

 case.
    ///
    /// In this case, we don't want to inherit the text alignment into the
    /// table.
    #[cfg(feature = "gecko")]
    fn adjust_for_table_text_align(&mut self) {
        use properties::longhands::text_align::computed_value::T as text_align;
       if self.style.get_box().clone_display() != display::table {
           return;
       }

       match self.style.get_inheritedtext().clone_text_align() {
           text_align::_moz_left |
           text_align::_moz_center |
           text_align::_moz_right => {}
           _ => return,
       }

       self.style.mutate_inheritedtext().set_text_align(text_align::start);
    }

    /// Adjusts the style to account for various fixups that don't fit naturally
    /// into the cascade.
    ///
    /// When comparing to Gecko, this is similar to the work done by
    /// `nsStyleContext::ApplyStyleFixups`.
    pub fn adjust(&mut self,
                  layout_parent_style: &ComputedValues,
                  flags: CascadeFlags) {
        #[cfg(feature = "gecko")]
        {
            self.adjust_for_prohibited_display_contents(flags);
        }
        self.adjust_for_top_layer();
        self.blockify_if_necessary(layout_parent_style, flags);
        self.adjust_for_position();
        self.adjust_for_overflow();
        #[cfg(feature = "gecko")]
        {
            self.adjust_for_table_text_align();
            self.adjust_for_contain();
            self.adjust_for_mathvariant();
        }
        #[cfg(feature = "servo")]
        {
            self.adjust_for_alignment(layout_parent_style);
        }
        self.adjust_for_border_width();
        self.adjust_for_outline();
        self.adjust_for_writing_mode(layout_parent_style);
    }
}
<commit_msg>style: Tweak an import.<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 http://mozilla.org/MPL/2.0/. */

//! A struct to encapsulate all the style fixups a computed style needs in order
//! for it to adhere to the CSS spec.

use app_units::Au;
use properties::{self, CascadeFlags, ComputedValues};
use properties::{SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, StyleBuilder};
use properties::longhands::display::computed_value::T as display;
use properties::longhands::float::computed_value::T as float;
use properties::longhands::overflow_x::computed_value::T as overflow;
use properties::longhands::position::computed_value::T as position;

/// An unsized struct that implements all the adjustment methods.
pub struct StyleAdjuster<'a, 'b: 'a> {
    style: &'a mut StyleBuilder<'b>,
    is_root_element: bool,
}

impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
    /// Trivially constructs a new StyleAdjuster.
    pub fn new(style: &'a mut StyleBuilder<'b>, is_root_element: bool) -> Self {
        StyleAdjuster {
            style: style,
            is_root_element: is_root_element,
        }
    }

    /// https://fullscreen.spec.whatwg.org/#new-stacking-layer
    ///
    ///    Any position value other than 'absolute' and 'fixed' are
    ///    computed to 'absolute' if the element is in a top layer.
    ///
    fn adjust_for_top_layer(&mut self) {
        if !self.style.out_of_flow_positioned() && self.style.in_top_layer() {
            self.style.mutate_box().set_position(position::absolute);
        }
    }

    /// CSS 2.1 section 9.7:
    ///
    ///    If 'position' has the value 'absolute' or 'fixed', [...] the computed
    ///    value of 'float' is 'none'.
    ///
    fn adjust_for_position(&mut self) {
        if self.style.out_of_flow_positioned() && self.style.floated() {
            self.style.mutate_box().set_float(float::none);
        }
    }

    /// Apply the blockification rules based on the table in CSS 2.2 section 9.7.
    /// https://drafts.csswg.org/css2/visuren.html#dis-pos-flo
    fn blockify_if_necessary(&mut self,
                             layout_parent_style: &ComputedValues,
                             flags: CascadeFlags) {
        let mut blockify = false;
        macro_rules! blockify_if {
            ($if_what:expr) => {
                if !blockify {
                    blockify = $if_what;
                }
            }
        }

        if !flags.contains(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP) {
            blockify_if!(self.is_root_element);
            blockify_if!(layout_parent_style.get_box().clone_display().is_item_container());
        }

        let is_item_or_root = blockify;

        blockify_if!(self.style.floated());
        blockify_if!(self.style.out_of_flow_positioned());

        if !blockify {
            return;
        }

        let display = self.style.get_box().clone_display();
        let blockified_display =
            display.equivalent_block_display(self.is_root_element);
        if display != blockified_display {
            self.style.mutate_box().set_adjusted_display(blockified_display,
                                                         is_item_or_root);
        }
    }

    /// Adjust the style for text style.
    ///
    /// The adjustments here are a subset of the adjustments generally, because
    /// text only inherits properties.
    ///
    /// Note that this, for Gecko, comes through Servo_ComputedValues_Inherit.
    #[cfg(feature = "gecko")]
    pub fn adjust_for_text(&mut self) {
        self.adjust_for_text_combine_upright();
    }

    /// Change writing mode of the text frame for text-combine-upright.
    ///
    /// It is safe to look at our own style because we are looking at inherited
    /// properties, and text is just plain inheritance.
    ///
    /// TODO(emilio): we should (Gecko too) revise these adjustments in presence
    /// of display: contents.
    #[cfg(feature = "gecko")]
    fn adjust_for_text_combine_upright(&mut self) {
        use computed_values::text_combine_upright::T as text_combine_upright;
        use computed_values::writing_mode::T as writing_mode;

        let writing_mode =
            self.style.get_inheritedbox().clone_writing_mode();
        let text_combine_upright =
            self.style.get_inheritedtext().clone_text_combine_upright();

        if writing_mode != writing_mode::horizontal_tb &&
           text_combine_upright == text_combine_upright::all {
            self.style.mutate_inheritedbox().set_writing_mode(writing_mode::horizontal_tb);
        }
    }

    /// https://drafts.csswg.org/css-writing-modes-3/#block-flow:
    ///
    ///    If a box has a different writing-mode value than its containing
    ///    block:
    ///
    ///        - If the box has a specified display of inline, its display
    ///          computes to inline-block. [CSS21]
    ///
    /// This matches the adjustment that Gecko does, not exactly following
    /// the spec. See also:
    ///
    /// https://lists.w3.org/Archives/Public/www-style/2017Mar/0045.html
    /// https://github.com/servo/servo/issues/15754
    fn adjust_for_writing_mode(&mut self,
                               layout_parent_style: &ComputedValues) {
        let our_writing_mode = self.style.get_inheritedbox().clone_writing_mode();
        let parent_writing_mode = layout_parent_style.get_inheritedbox().clone_writing_mode();

        if our_writing_mode != parent_writing_mode &&
           self.style.get_box().clone_display() == display::inline {
            self.style.mutate_box().set_display(display::inline_block);
        }
    }

    #[cfg(feature = "gecko")]
    fn adjust_for_contain(&mut self) {
        use properties::longhands::contain;

        // An element with contain: paint needs to be a formatting context, and
        // also implies overflow: clip.
        //
        // TODO(emilio): This mimics Gecko, but spec links are missing!
        let contain = self.style.get_box().clone_contain();
        if !contain.contains(contain::PAINT) {
            return;
        }

        if self.style.get_box().clone_display() == display::inline {
            self.style.mutate_box().set_adjusted_display(display::inline_block,
                                                         false);
        }

        // When 'contain: paint', update overflow from 'visible' to 'clip'.
        if self.style.get_box().clone_contain().contains(contain::PAINT) {
            if self.style.get_box().clone_overflow_x() == overflow::visible {
                let mut box_style = self.style.mutate_box();
                box_style.set_overflow_x(overflow::_moz_hidden_unscrollable);
                box_style.set_overflow_y(overflow::_moz_hidden_unscrollable);
            }
        }
    }

    /// When mathvariant is not "none", font-weight and font-style are
    /// both forced to "normal".
    #[cfg(feature = "gecko")]
    fn adjust_for_mathvariant(&mut self) {
        use properties::longhands::_moz_math_variant::computed_value::T as moz_math_variant;
        use properties::longhands::font_style::computed_value::T as font_style;
        use properties::longhands::font_weight::computed_value::T as font_weight;
        if self.style.get_font().clone__moz_math_variant() != moz_math_variant::none {
            let mut font_style = self.style.mutate_font();
            // Sadly we don't have a nice name for the computed value
            // of "font-weight: normal".
            font_style.set_font_weight(font_weight::Weight400);
            font_style.set_font_style(font_style::normal);
        }
    }

    /// This implements an out-of-date spec. The new spec moves the handling of
    /// this to layout, which Gecko implements but Servo doesn't.
    ///
    /// See https://github.com/servo/servo/issues/15229
    #[cfg(feature = "servo")]
    fn adjust_for_alignment(&mut self, layout_parent_style: &ComputedValues) {
        use computed_values::align_items::T as align_items;
        use computed_values::align_self::T as align_self;

        if self.style.get_position().clone_align_self() == align_self::auto &&
           !self.style.out_of_flow_positioned() {
            let self_align =
                match layout_parent_style.get_position().clone_align_items() {
                    align_items::stretch => align_self::stretch,
                    align_items::baseline => align_self::baseline,
                    align_items::flex_start => align_self::flex_start,
                    align_items::flex_end => align_self::flex_end,
                    align_items::center => align_self::center,
                };
            self.style.mutate_position().set_align_self(self_align);
        }
    }

    /// The initial value of border-*-width may be changed at computed value
    /// time.
    ///
    /// This is moved to properties.rs for convenience.
    fn adjust_for_border_width(&mut self) {
        properties::adjust_border_width(self.style);
    }

    /// The initial value of outline-width may be changed at computed value time.
    fn adjust_for_outline(&mut self) {
        if self.style.get_outline().clone_outline_style().none_or_hidden() &&
           self.style.get_outline().outline_has_nonzero_width() {
            self.style.mutate_outline().set_outline_width(Au(0));
        }
    }

    /// CSS3 overflow-x and overflow-y require some fixup as well in some
    /// cases.
    ///
    /// overflow: clip and overflow: visible are meaningful only when used in
    /// both dimensions.
    fn adjust_for_overflow(&mut self) {
        let original_overflow_x = self.style.get_box().clone_overflow_x();
        let original_overflow_y = self.style.get_box().clone_overflow_y();

        let mut overflow_x = original_overflow_x;
        let mut overflow_y = original_overflow_y;

        if overflow_x == overflow_y {
            return;
        }

        // If 'visible' is specified but doesn't match the other dimension,
        // it turns into 'auto'.
        if overflow_x == overflow::visible {
            overflow_x = overflow::auto;
        }

        if overflow_y == overflow::visible {
            overflow_y = overflow::auto;
        }

        #[cfg(feature = "gecko")]
        {
            // overflow: clip is deprecated, so convert to hidden if it's
            // specified in only one dimension.
            if overflow_x == overflow::_moz_hidden_unscrollable {
                overflow_x = overflow::hidden;
            }
            if overflow_y == overflow::_moz_hidden_unscrollable {
                overflow_y = overflow::hidden;
            }
        }

        if overflow_x != original_overflow_x ||
           overflow_y != original_overflow_y {
            let mut box_style = self.style.mutate_box();
            box_style.set_overflow_x(overflow_x);
            box_style.set_overflow_y(overflow_y);
        }
    }

    /// Native anonymous content converts display:contents into display:inline.
    #[cfg(feature = "gecko")]
    fn adjust_for_prohibited_display_contents(&mut self, flags: CascadeFlags) {
        use properties::PROHIBIT_DISPLAY_CONTENTS;

        // TODO: We should probably convert display:contents into display:none
        // in some cases too: https://drafts.csswg.org/css-display/#unbox
        if !flags.contains(PROHIBIT_DISPLAY_CONTENTS) ||
           self.style.get_box().clone_display() != display::contents {
            return;
        }

        self.style.mutate_box().set_display(display::inline);
    }

    /// -moz-center, -moz-left and -moz-right are used for HTML's alignment.
    ///
    /// This is covering the

...

 case.
    ///
    /// In this case, we don't want to inherit the text alignment into the
    /// table.
    #[cfg(feature = "gecko")]
    fn adjust_for_table_text_align(&mut self) {
        use properties::longhands::text_align::computed_value::T as text_align;
       if self.style.get_box().clone_display() != display::table {
           return;
       }

       match self.style.get_inheritedtext().clone_text_align() {
           text_align::_moz_left |
           text_align::_moz_center |
           text_align::_moz_right => {}
           _ => return,
       }

       self.style.mutate_inheritedtext().set_text_align(text_align::start);
    }

    /// Adjusts the style to account for various fixups that don't fit naturally
    /// into the cascade.
    ///
    /// When comparing to Gecko, this is similar to the work done by
    /// `nsStyleContext::ApplyStyleFixups`.
    pub fn adjust(&mut self,
                  layout_parent_style: &ComputedValues,
                  flags: CascadeFlags) {
        #[cfg(feature = "gecko")]
        {
            self.adjust_for_prohibited_display_contents(flags);
        }
        self.adjust_for_top_layer();
        self.blockify_if_necessary(layout_parent_style, flags);
        self.adjust_for_position();
        self.adjust_for_overflow();
        #[cfg(feature = "gecko")]
        {
            self.adjust_for_table_text_align();
            self.adjust_for_contain();
            self.adjust_for_mathvariant();
        }
        #[cfg(feature = "servo")]
        {
            self.adjust_for_alignment(layout_parent_style);
        }
        self.adjust_for_border_width();
        self.adjust_for_outline();
        self.adjust_for_writing_mode(layout_parent_style);
    }
}
<|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 http://mozilla.org/MPL/2.0/. */

use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::codemap::Span;
use syntax::ptr::P;
use syntax::ast::{Item, MetaItem, Expr};
use syntax::ast;
use syntax::ext::build::AstBuilder;
use syntax::ext::deriving::generic::{combine_substructure, EnumMatching, FieldInfo, MethodDef, Struct, Substructure, TraitDef, ty};

pub fn expand_dom_struct(cx: &mut ExtCtxt, _: Span, _: &MetaItem, item: P<Item>) -> P<Item> {
    let mut item2 = (*item).clone();
    item2.attrs.push(quote_attr!(cx, #[must_root]));
    item2.attrs.push(quote_attr!(cx, #[privatize]));
    item2.attrs.push(quote_attr!(cx, #[jstraceable]));

    // The following attributes are only for internal usage
    item2.attrs.push(quote_attr!(cx, #[_generate_reflector]));
    // #[dom_struct] gets consumed, so this lets us keep around a residue
    // Do NOT register a modifier/decorator on this attribute
    item2.attrs.push(quote_attr!(cx, #[_dom_struct_marker]));
    P(item2)
}

/// Provides the hook to expand `#[jstraceable]` into an implementation of `JSTraceable`
///
/// The expansion basically calls `trace()` on all of the fields of the struct/enum, erroring if they do not implement the method.
pub fn expand_jstraceable(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, item: Annotatable, push: &mut FnMut(Annotatable)) {
    let trait_def = TraitDef {
        span: span,
        attributes: Vec::new(),
        path: ty::Path::new(vec!("dom","bindings","trace","JSTraceable")),
        additional_bounds: Vec::new(),
        generics: ty::LifetimeBounds::empty(),
        methods: vec![
            MethodDef {
                name: "trace",
                generics: ty::LifetimeBounds::empty(),
                explicit_self: ty::borrowed_explicit_self(),
                args: vec!(ty::Ptr(box ty::Literal(ty::Path::new(vec!("js","jsapi","JSTracer"))), ty::Raw(ast::MutMutable))),
                ret_ty: ty::nil_ty(),
                attributes: vec![quote_attr!(cx, #[inline(always)])],
                combine_substructure: combine_substructure(box jstraceable_substructure)
            }
        ],
        associated_types: vec![],
    };
    trait_def.expand(cx, mitem, &item, push)
}

// Mostly copied from syntax::ext::deriving::hash
/// Defines how the implementation for `trace()` is to be generated
fn jstraceable_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
    let state_expr = if substr.nonself_args.len() == 1 {
        &substr.nonself_args[0]
    } else {
        cx.span_bug(trait_span, "incorrect number of arguments in `jstraceable`")
    };
    let trace_ident = substr.method_ident;
    let call_trace = |span, thing_expr| {
        let expr = cx.expr_method_call(span, thing_expr, trace_ident, vec!(state_expr.clone()));
        cx.stmt_expr(expr)
    };
    let mut stmts = Vec::new();

    let fields = match *substr.fields {
        Struct(ref fs) | EnumMatching(_, _, ref fs) => fs,
        _ => cx.span_bug(trait_span, "impossible substructure in `jstraceable`")
    };

    for &FieldInfo { ref self_, span, .. } in fields.iter() {
        stmts.push(call_trace(span, self_.clone()));
    }

    cx.expr_block(cx.block(trait_span, stmts, None))
}
<commit_msg>Update plugins API<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 http://mozilla.org/MPL/2.0/. */

use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::codemap::Span;
use syntax::ptr::P;
use syntax::ast::{Item, MetaItem, Expr};
use syntax::ast;
use syntax::ext::build::AstBuilder;
use syntax::ext::deriving::generic::{combine_substructure, EnumMatching, FieldInfo, MethodDef, Struct, Substructure, TraitDef, ty};

pub fn expand_dom_struct(cx: &mut ExtCtxt, _: Span, _: &MetaItem, item: P<Item>) -> P<Item> {
    let mut item2 = (*item).clone();
    item2.attrs.push(quote_attr!(cx, #[must_root]));
    item2.attrs.push(quote_attr!(cx, #[privatize]));
    item2.attrs.push(quote_attr!(cx, #[jstraceable]));

    // The following attributes are only for internal usage
    item2.attrs.push(quote_attr!(cx, #[_generate_reflector]));
    // #[dom_struct] gets consumed, so this lets us keep around a residue
    // Do NOT register a modifier/decorator on this attribute
    item2.attrs.push(quote_attr!(cx, #[_dom_struct_marker]));
    P(item2)
}

/// Provides the hook to expand `#[jstraceable]` into an implementation of `JSTraceable`
///
/// The expansion basically calls `trace()` on all of the fields of the struct/enum, erroring if they do not implement the method.
pub fn expand_jstraceable(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, item: Annotatable, push: &mut FnMut(Annotatable)) {
    let trait_def = TraitDef {
        span: span,
        attributes: Vec::new(),
        path: ty::Path::new(vec!("dom","bindings","trace","JSTraceable")),
        additional_bounds: Vec::new(),
        generics: ty::LifetimeBounds::empty(),
        methods: vec![
            MethodDef {
                name: "trace",
                generics: ty::LifetimeBounds::empty(),
                explicit_self: ty::borrowed_explicit_self(),
                args: vec!(ty::Ptr(box ty::Literal(ty::Path::new(vec!("js","jsapi","JSTracer"))), ty::Raw(ast::MutMutable))),
                ret_ty: ty::nil_ty(),
                attributes: vec![quote_attr!(cx, #[inline(always)])],
                is_unsafe: false,
                combine_substructure: combine_substructure(box jstraceable_substructure)
            }
        ],
        associated_types: vec![],
    };
    trait_def.expand(cx, mitem, &item, push)
}

// Mostly copied from syntax::ext::deriving::hash
/// Defines how the implementation for `trace()` is to be generated
fn jstraceable_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
    let state_expr = if substr.nonself_args.len() == 1 {
        &substr.nonself_args[0]
    } else {
        cx.span_bug(trait_span, "incorrect number of arguments in `jstraceable`")
    };
    let trace_ident = substr.method_ident;
    let call_trace = |span, thing_expr| {
        let expr = cx.expr_method_call(span, thing_expr, trace_ident, vec!(state_expr.clone()));
        cx.stmt_expr(expr)
    };
    let mut stmts = Vec::new();

    let fields = match *substr.fields {
        Struct(ref fs) | EnumMatching(_, _, ref fs) => fs,
        _ => cx.span_bug(trait_span, "impossible substructure in `jstraceable`")
    };

    for &FieldInfo { ref self_, span, .. } in fields.iter() {
        stmts.push(call_trace(span, self_.clone()));
    }

    cx.expr_block(cx.block(trait_span, stmts, None))
}
<|endoftext|>


<commit_before>use crate::utils::{is_expn_of, is_type_diagnostic_item, return_ty, span_lint_and_then};
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor};
use rustc_hir::Expr;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for usage of `panic!`, `unimplemented!`, `todo!` or `unreachable!` in a function of type result.
    ///
    /// **Why is this bad?** For some codebases, it is desirable for functions of type result to return an error instead of crashing. Hence unimplemented, panic and unreachable should be avoided.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// fn result_with_panic() -> Result<bool, String>
    /// {
    ///     panic!("error");
    /// }
    /// ```
    pub PANIC_IN_RESULT,
    restriction,
    "functions of type `Result<..>` that contain `panic!()`, `todo!()` or `unreachable()` or `unimplemented()` "
}

declare_lint_pass!(PanicInResult => [PANIC_IN_RESULT]);

impl<'tcx> LateLintPass<'tcx> for PanicInResult {
    /*
    fn check_fn(
        &mut self,
        cx: &LateContext<'tcx>,
        _: FnKind<'tcx>,
        _: &'tcx hir::FnDecl<'tcx>,
        body: &'tcx hir::Body<'tcx>,
        span: Span,
        hir_id: hir::HirId,
    ) {
        if_chain! {
            if is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym!(result_type));
            then
            {
                lint_impl_body(cx, span, body);
            }
        }
    }*/
}

struct FindPanicUnimplementedUnreachable {
    result: Vec<Span>,
}

impl<'tcx> Visitor<'tcx> for FindPanicUnimplementedUnreachable {
    type Map = Map<'tcx>;

    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
        if is_expn_of(expr.span, "unimplemented").is_some()
            || is_expn_of(expr.span, "unreachable").is_some()
            || is_expn_of(expr.span, "panic").is_some()
            || is_expn_of(expr.span, "todo").is_some()
        {
            self.result.push(expr.span);
        }
        // and check sub-expressions
        intravisit::walk_expr(self, expr);
    }

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::None
    }
}

fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir::Body<'tcx>) {
    let mut panics = FindPanicUnimplementedUnreachable { result: Vec::new() };
    panics.visit_expr(&body.value);
    if !panics.result.is_empty() {
        span_lint_and_then(
            cx,
            PANIC_IN_RESULT,
            impl_span,
            "used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result`",
            move |diag| {
                diag.help(
                    "`unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing",
                );
                diag.span_note(panics.result, "return Err() instead of panicking");
            },
        );
    }
}
<commit_msg>uncommented fn<commit_after>use crate::utils::{is_expn_of, is_type_diagnostic_item, return_ty, span_lint_and_then};
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor};
use rustc_hir::Expr;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for usage of `panic!`, `unimplemented!`, `todo!` or `unreachable!` in a function of type result.
    ///
    /// **Why is this bad?** For some codebases, it is desirable for functions of type result to return an error instead of crashing. Hence unimplemented, panic and unreachable should be avoided.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// fn result_with_panic() -> Result<bool, String>
    /// {
    ///     panic!("error");
    /// }
    /// ```
    pub PANIC_IN_RESULT,
    restriction,
    "functions of type `Result<..>` that contain `panic!()`, `todo!()` or `unreachable()` or `unimplemented()` "
}

declare_lint_pass!(PanicInResult => [PANIC_IN_RESULT]);

impl<'tcx> LateLintPass<'tcx> for PanicInResult {
    fn check_fn(
        &mut self,
        cx: &LateContext<'tcx>,
        _: FnKind<'tcx>,
        _: &'tcx hir::FnDecl<'tcx>,
        body: &'tcx hir::Body<'tcx>,
        span: Span,
        hir_id: hir::HirId,
    ) {
        if_chain! {
            if is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym!(result_type));
            then
            {
                lint_impl_body(cx, span, body);
            }
        }
    }
}

struct FindPanicUnimplementedUnreachable {
    result: Vec<Span>,
}

impl<'tcx> Visitor<'tcx> for FindPanicUnimplementedUnreachable {
    type Map = Map<'tcx>;

    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
        if is_expn_of(expr.span, "unimplemented").is_some()
            || is_expn_of(expr.span, "unreachable").is_some()
            || is_expn_of(expr.span, "panic").is_some()
            || is_expn_of(expr.span, "todo").is_some()
        {
            self.result.push(expr.span);
        }
        // and check sub-expressions
        intravisit::walk_expr(self, expr);
    }

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::None
    }
}

fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir::Body<'tcx>) {
    let mut panics = FindPanicUnimplementedUnreachable { result: Vec::new() };
    panics.visit_expr(&body.value);
    if !panics.result.is_empty() {
        span_lint_and_then(
            cx,
            PANIC_IN_RESULT,
            impl_span,
            "used `unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` in a function that returns `Result`",
            move |diag| {
                diag.help(
                    "`unimplemented!()`, `unreachable!()`, `todo!()` or `panic!()` should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing",
                );
                diag.span_note(panics.result, "return Err() instead of panicking");
            },
        );
    }
}
<|endoftext|>